pxengine 0.1.12 → 0.1.14
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 +227 -291
- package/dist/index.d.cts +15 -11
- package/dist/index.d.ts +15 -11
- package/dist/index.js +225 -287
- package/dist/registry.json +20 -22
- package/package.json +2 -4
- package/config/tailwind-preset.js +0 -106
- package/src/atoms/AccordionAtom.tsx +0 -44
- package/src/atoms/AlertAtom.tsx +0 -48
- package/src/atoms/AlertDialogAtom.tsx +0 -66
- package/src/atoms/AspectRatioAtom.tsx +0 -27
- package/src/atoms/AvatarAtom.tsx +0 -21
- package/src/atoms/BadgeAtom.tsx +0 -35
- package/src/atoms/BreadcrumbAtom.tsx +0 -36
- package/src/atoms/ButtonAtom.tsx +0 -65
- package/src/atoms/CalendarAtom.tsx +0 -24
- package/src/atoms/CardAtom.tsx +0 -66
- package/src/atoms/CarouselAtom.tsx +0 -40
- package/src/atoms/ChartAtom.tsx +0 -192
- package/src/atoms/CheckboxAtom.tsx +0 -33
- package/src/atoms/CollapsibleAtom.tsx +0 -44
- package/src/atoms/CommandAtom.tsx +0 -46
- package/src/atoms/ContextMenuAtom.tsx +0 -49
- package/src/atoms/DialogAtom.tsx +0 -68
- package/src/atoms/DrawerAtom.tsx +0 -49
- package/src/atoms/DropdownMenuAtom.tsx +0 -49
- package/src/atoms/FormInputAtom.tsx +0 -101
- package/src/atoms/FormSelectAtom.tsx +0 -110
- package/src/atoms/FormTextareaAtom.tsx +0 -93
- package/src/atoms/InputAtom.tsx +0 -216
- package/src/atoms/InputOTPAtom.tsx +0 -49
- package/src/atoms/KbdAtom.tsx +0 -25
- package/src/atoms/LabelAtom.tsx +0 -23
- package/src/atoms/LayoutAtom.tsx +0 -45
- package/src/atoms/PaginationAtom.tsx +0 -49
- package/src/atoms/PopoverAtom.tsx +0 -40
- package/src/atoms/ProgressAtom.tsx +0 -15
- package/src/atoms/RadioGroupAtom.tsx +0 -31
- package/src/atoms/RatingAtom.tsx +0 -37
- package/src/atoms/ResizableAtom.tsx +0 -51
- package/src/atoms/ScrollAreaAtom.tsx +0 -31
- package/src/atoms/SeparatorAtom.tsx +0 -16
- package/src/atoms/SheetAtom.tsx +0 -72
- package/src/atoms/SkeletonAtom.tsx +0 -22
- package/src/atoms/SliderAtom.tsx +0 -32
- package/src/atoms/SpinnerAtom.tsx +0 -26
- package/src/atoms/SwitchAtom.tsx +0 -32
- package/src/atoms/TableAtom.tsx +0 -60
- package/src/atoms/TabsAtom.tsx +0 -40
- package/src/atoms/TextAtom.tsx +0 -36
- package/src/atoms/TextareaAtom.tsx +0 -42
- package/src/atoms/TimelineAtom.tsx +0 -77
- package/src/atoms/ToggleAtom.tsx +0 -36
- package/src/atoms/TooltipAtom.tsx +0 -39
- package/src/atoms/VideoAtom.tsx +0 -34
- package/src/atoms/index.ts +0 -49
- package/src/components/index.ts +0 -178
- package/src/components/ui/accordion.tsx +0 -56
- package/src/components/ui/alert-dialog.tsx +0 -139
- package/src/components/ui/alert.tsx +0 -59
- package/src/components/ui/aspect-ratio.tsx +0 -5
- package/src/components/ui/avatar.tsx +0 -50
- package/src/components/ui/badge.tsx +0 -36
- package/src/components/ui/breadcrumb.tsx +0 -115
- package/src/components/ui/button-group.tsx +0 -83
- package/src/components/ui/button.tsx +0 -56
- package/src/components/ui/calendar.tsx +0 -213
- package/src/components/ui/card.tsx +0 -79
- package/src/components/ui/carousel.tsx +0 -260
- package/src/components/ui/chart.tsx +0 -367
- package/src/components/ui/checkbox.tsx +0 -28
- package/src/components/ui/collapsible.tsx +0 -11
- package/src/components/ui/command.tsx +0 -153
- package/src/components/ui/context-menu.tsx +0 -198
- package/src/components/ui/dialog.tsx +0 -122
- package/src/components/ui/drawer.tsx +0 -116
- package/src/components/ui/dropdown-menu.tsx +0 -200
- package/src/components/ui/empty.tsx +0 -104
- package/src/components/ui/field.tsx +0 -244
- package/src/components/ui/form.tsx +0 -176
- package/src/components/ui/hover-card.tsx +0 -27
- package/src/components/ui/index.ts +0 -54
- package/src/components/ui/input-group.tsx +0 -168
- package/src/components/ui/input-otp.tsx +0 -69
- package/src/components/ui/input.tsx +0 -22
- package/src/components/ui/item.tsx +0 -193
- package/src/components/ui/kbd.tsx +0 -28
- package/src/components/ui/label.tsx +0 -26
- package/src/components/ui/menubar.tsx +0 -254
- package/src/components/ui/navigation-menu.tsx +0 -128
- package/src/components/ui/pagination.tsx +0 -117
- package/src/components/ui/popover.tsx +0 -29
- package/src/components/ui/progress.tsx +0 -28
- package/src/components/ui/radio-group.tsx +0 -42
- package/src/components/ui/resizable.tsx +0 -44
- package/src/components/ui/scroll-area.tsx +0 -46
- package/src/components/ui/select.tsx +0 -160
- package/src/components/ui/separator.tsx +0 -29
- package/src/components/ui/sheet.tsx +0 -140
- package/src/components/ui/sidebar.tsx +0 -771
- package/src/components/ui/skeleton.tsx +0 -15
- package/src/components/ui/slider.tsx +0 -26
- package/src/components/ui/sonner.tsx +0 -45
- package/src/components/ui/spinner.tsx +0 -16
- package/src/components/ui/switch.tsx +0 -27
- package/src/components/ui/table.tsx +0 -117
- package/src/components/ui/tabs.tsx +0 -53
- package/src/components/ui/textarea.tsx +0 -22
- package/src/components/ui/toggle-group.tsx +0 -61
- package/src/components/ui/toggle.tsx +0 -43
- package/src/components/ui/tooltip.tsx +0 -30
- package/src/hooks/use-mobile.tsx +0 -19
- package/src/index.ts +0 -24
- package/src/lib/countries.ts +0 -203
- package/src/lib/index.ts +0 -2
- package/src/lib/utils.ts +0 -15
- package/src/lib/validators/index.ts +0 -1
- package/src/lib/validators/theme.ts +0 -148
- package/src/molecules/creator-discovery/AudienceDemographicsCard/AudienceDemographicsCard.tsx +0 -44
- package/src/molecules/creator-discovery/AudienceDemographicsCard/index.ts +0 -1
- package/src/molecules/creator-discovery/AudienceMetricCard/AudienceMetricCard.tsx +0 -50
- package/src/molecules/creator-discovery/AudienceMetricCard/index.ts +0 -1
- package/src/molecules/creator-discovery/BrandAffinityGroup/BrandAffinityGroup.tsx +0 -36
- package/src/molecules/creator-discovery/BrandAffinityGroup/index.ts +0 -1
- package/src/molecules/creator-discovery/CampaignSeedCard/CampaignSeedCard.tsx +0 -123
- package/src/molecules/creator-discovery/CampaignSeedCard/CampaignSeedCard.types.ts +0 -13
- package/src/molecules/creator-discovery/CampaignSeedCard/index.ts +0 -2
- package/src/molecules/creator-discovery/ContentPreviewGallery/ContentPreviewGallery.tsx +0 -41
- package/src/molecules/creator-discovery/ContentPreviewGallery/index.ts +0 -1
- package/src/molecules/creator-discovery/CreatorActionHeader/CreatorActionHeader.tsx +0 -77
- package/src/molecules/creator-discovery/CreatorActionHeader/index.ts +0 -1
- package/src/molecules/creator-discovery/CreatorGridCard/CreatorGridCard.tsx +0 -104
- package/src/molecules/creator-discovery/CreatorGridCard/index.ts +0 -1
- package/src/molecules/creator-discovery/CreatorProfileSummary/CreatorProfileSummary.tsx +0 -65
- package/src/molecules/creator-discovery/CreatorProfileSummary/index.ts +0 -1
- package/src/molecules/creator-discovery/GrowthChartCard/GrowthChartCard.tsx +0 -58
- package/src/molecules/creator-discovery/GrowthChartCard/index.ts +0 -1
- package/src/molecules/creator-discovery/MCQCard/MCQCard.tsx +0 -165
- package/src/molecules/creator-discovery/MCQCard/MCQCard.types.ts +0 -71
- package/src/molecules/creator-discovery/MCQCard/index.ts +0 -2
- package/src/molecules/creator-discovery/PlatformIconGroup/PlatformIconGroup.tsx +0 -72
- package/src/molecules/creator-discovery/PlatformIconGroup/index.ts +0 -1
- package/src/molecules/creator-discovery/SearchSpecCard/CustomFieldRenderers.tsx +0 -334
- package/src/molecules/creator-discovery/SearchSpecCard/SearchSpecCard.tsx +0 -111
- package/src/molecules/creator-discovery/SearchSpecCard/SearchSpecCard.types.ts +0 -18
- package/src/molecules/creator-discovery/SearchSpecCard/index.ts +0 -3
- package/src/molecules/creator-discovery/TopPostsGrid/TopPostsGrid.tsx +0 -49
- package/src/molecules/creator-discovery/TopPostsGrid/index.ts +0 -1
- package/src/molecules/creator-discovery/index.ts +0 -13
- package/src/molecules/generic/ActionButton/ActionButton.tsx +0 -137
- package/src/molecules/generic/ActionButton/ActionButton.types.ts +0 -68
- package/src/molecules/generic/ActionButton/index.ts +0 -2
- package/src/molecules/generic/DataGrid/DataGrid.tsx +0 -102
- package/src/molecules/generic/DataGrid/index.ts +0 -1
- package/src/molecules/generic/EditableField/EditableField.tsx +0 -229
- package/src/molecules/generic/EditableField/EditableField.types.ts +0 -73
- package/src/molecules/generic/EditableField/index.ts +0 -2
- package/src/molecules/generic/EmptyState/EmptyState.tsx +0 -61
- package/src/molecules/generic/EmptyState/index.ts +0 -1
- package/src/molecules/generic/FileUpload/FileUpload.tsx +0 -62
- package/src/molecules/generic/FileUpload/index.ts +0 -1
- package/src/molecules/generic/FilterBar/FilterBar.tsx +0 -54
- package/src/molecules/generic/FilterBar/index.ts +0 -1
- package/src/molecules/generic/FormCard/FormCard.tsx +0 -136
- package/src/molecules/generic/FormCard/FormCard.types.ts +0 -93
- package/src/molecules/generic/FormCard/index.ts +0 -2
- package/src/molecules/generic/LoadingOverlay/LoadingOverlay.tsx +0 -39
- package/src/molecules/generic/LoadingOverlay/index.ts +0 -1
- package/src/molecules/generic/NotificationList/NotificationList.tsx +0 -80
- package/src/molecules/generic/NotificationList/index.ts +0 -1
- package/src/molecules/generic/StatsGrid/StatsGrid.tsx +0 -80
- package/src/molecules/generic/StatsGrid/index.ts +0 -1
- package/src/molecules/generic/StepWizard/StepWizard.tsx +0 -67
- package/src/molecules/generic/StepWizard/index.ts +0 -1
- package/src/molecules/generic/TagCloud/TagCloud.tsx +0 -32
- package/src/molecules/generic/TagCloud/index.ts +0 -1
- package/src/molecules/generic/index.ts +0 -12
- package/src/molecules/index.ts +0 -2
- package/src/render/PXEngineRenderer.tsx +0 -458
- package/src/render/index.ts +0 -1
- package/src/styles/globals.css +0 -146
- package/src/types/atoms.ts +0 -450
- package/src/types/common.ts +0 -116
- package/src/types/index.ts +0 -3
- package/src/types/molecules.ts +0 -279
- package/src/types/schema.ts +0 -12
|
@@ -1,458 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { UIComponent, UISchema } from "../types/schema";
|
|
3
|
-
import * as Atoms from "../atoms";
|
|
4
|
-
import * as Molecules from "../molecules/index";
|
|
5
|
-
|
|
6
|
-
// Import all shadcn UI components
|
|
7
|
-
import * as UIComponents from "../components/ui/index";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Components that require specific React Context and cannot be rendered in isolation.
|
|
11
|
-
* These components will show helpful error messages if used directly in schemas.
|
|
12
|
-
*/
|
|
13
|
-
const CONTEXT_DEPENDENT_COMPONENTS = new Set([
|
|
14
|
-
// Form components - require FormField + FormItem context
|
|
15
|
-
"FormLabel",
|
|
16
|
-
"FormControl",
|
|
17
|
-
"FormDescription",
|
|
18
|
-
"FormMessage",
|
|
19
|
-
"FormItem",
|
|
20
|
-
"FormField",
|
|
21
|
-
// Select components - require Select parent
|
|
22
|
-
"SelectContent",
|
|
23
|
-
"SelectItem",
|
|
24
|
-
"SelectValue",
|
|
25
|
-
"SelectTrigger",
|
|
26
|
-
"SelectGroup",
|
|
27
|
-
"SelectLabel",
|
|
28
|
-
"SelectSeparator",
|
|
29
|
-
// Accordion components - require Accordion parent
|
|
30
|
-
"AccordionContent",
|
|
31
|
-
"AccordionItem",
|
|
32
|
-
"AccordionTrigger",
|
|
33
|
-
// Tabs components - require Tabs parent
|
|
34
|
-
"TabsContent",
|
|
35
|
-
"TabsList",
|
|
36
|
-
"TabsTrigger",
|
|
37
|
-
// Dialog components - require Dialog parent
|
|
38
|
-
"DialogContent",
|
|
39
|
-
"DialogHeader",
|
|
40
|
-
"DialogFooter",
|
|
41
|
-
"DialogTitle",
|
|
42
|
-
"DialogDescription",
|
|
43
|
-
"DialogClose",
|
|
44
|
-
// Sheet components - require Sheet parent
|
|
45
|
-
"SheetContent",
|
|
46
|
-
"SheetHeader",
|
|
47
|
-
"SheetFooter",
|
|
48
|
-
"SheetTitle",
|
|
49
|
-
"SheetDescription",
|
|
50
|
-
"SheetClose",
|
|
51
|
-
// AlertDialog components - require AlertDialog parent
|
|
52
|
-
"AlertDialogContent",
|
|
53
|
-
"AlertDialogHeader",
|
|
54
|
-
"AlertDialogFooter",
|
|
55
|
-
"AlertDialogTitle",
|
|
56
|
-
"AlertDialogDescription",
|
|
57
|
-
"AlertDialogAction",
|
|
58
|
-
"AlertDialogCancel",
|
|
59
|
-
// Dropdown components - require DropdownMenu parent
|
|
60
|
-
"DropdownMenuContent",
|
|
61
|
-
"DropdownMenuItem",
|
|
62
|
-
"DropdownMenuLabel",
|
|
63
|
-
"DropdownMenuSeparator",
|
|
64
|
-
"DropdownMenuCheckboxItem",
|
|
65
|
-
"DropdownMenuRadioItem",
|
|
66
|
-
"DropdownMenuRadioGroup",
|
|
67
|
-
// Popover components - require Popover parent
|
|
68
|
-
"PopoverContent",
|
|
69
|
-
// Tooltip components - require TooltipProvider parent
|
|
70
|
-
"TooltipContent",
|
|
71
|
-
// Context Menu components
|
|
72
|
-
"ContextMenuContent",
|
|
73
|
-
"ContextMenuItem",
|
|
74
|
-
// Navigation Menu components
|
|
75
|
-
"NavigationMenuContent",
|
|
76
|
-
"NavigationMenuItem",
|
|
77
|
-
]);
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Mapping of problematic components to their Atom alternatives
|
|
81
|
-
*/
|
|
82
|
-
const COMPONENT_SUGGESTIONS: Record<string, string> = {
|
|
83
|
-
FormLabel: "FormInputAtom (with label prop)",
|
|
84
|
-
FormControl: "FormInputAtom",
|
|
85
|
-
FormItem: "FormInputAtom",
|
|
86
|
-
FormField: "FormInputAtom",
|
|
87
|
-
Select: "FormSelectAtom or InputAtom with inputType='select'",
|
|
88
|
-
SelectContent: "FormSelectAtom or InputAtom with inputType='select'",
|
|
89
|
-
SelectItem: "FormSelectAtom or InputAtom with inputType='select'",
|
|
90
|
-
Tabs: "TabsAtom",
|
|
91
|
-
TabsContent: "TabsAtom",
|
|
92
|
-
TabsList: "TabsAtom",
|
|
93
|
-
Dialog: "DialogAtom",
|
|
94
|
-
DialogContent: "DialogAtom",
|
|
95
|
-
Sheet: "SheetAtom",
|
|
96
|
-
SheetContent: "SheetAtom",
|
|
97
|
-
AlertDialog: "AlertDialogAtom",
|
|
98
|
-
AlertDialogContent: "AlertDialogAtom",
|
|
99
|
-
Accordion: "AccordionAtom",
|
|
100
|
-
AccordionItem: "AccordionAtom",
|
|
101
|
-
Input: "InputAtom",
|
|
102
|
-
Textarea: "InputAtom with inputType='textarea'",
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* PXEngineRenderer
|
|
107
|
-
*
|
|
108
|
-
* Handles both the full schema { version, root } and individual components.
|
|
109
|
-
* Dynamically resolves components from Atoms/Molecules/UI Components registry.
|
|
110
|
-
* Prevents rendering of context-dependent components to avoid React errors.
|
|
111
|
-
*/
|
|
112
|
-
interface PXEngineRendererProps {
|
|
113
|
-
schema: UISchema | UIComponent;
|
|
114
|
-
onAction?: (action: string, payload?: any) => void;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Renders an error message for context-dependent components
|
|
119
|
-
*/
|
|
120
|
-
const renderContextDependentError = (
|
|
121
|
-
componentName: string,
|
|
122
|
-
normalizedName: string,
|
|
123
|
-
key: string,
|
|
124
|
-
): React.ReactNode => {
|
|
125
|
-
const suggestion =
|
|
126
|
-
COMPONENT_SUGGESTIONS[normalizedName] ||
|
|
127
|
-
`${componentName}Atom (if available)`;
|
|
128
|
-
|
|
129
|
-
return (
|
|
130
|
-
<div
|
|
131
|
-
key={key}
|
|
132
|
-
className="p-4 border-2 border-amber-500/50 rounded-lg bg-amber-50/80 space-y-2 my-2"
|
|
133
|
-
>
|
|
134
|
-
<div className="flex items-start gap-2">
|
|
135
|
-
<span className="text-amber-600 font-bold text-lg">⚠️</span>
|
|
136
|
-
<div className="flex-1">
|
|
137
|
-
<p className="text-sm font-semibold text-amber-900">
|
|
138
|
-
Invalid Component: {componentName}
|
|
139
|
-
</p>
|
|
140
|
-
<p className="text-xs text-amber-700 mt-1">
|
|
141
|
-
This component requires React Context and cannot be rendered
|
|
142
|
-
directly in schemas.
|
|
143
|
-
</p>
|
|
144
|
-
</div>
|
|
145
|
-
</div>
|
|
146
|
-
<div className="bg-white/60 p-3 rounded border border-amber-200">
|
|
147
|
-
<p className="text-xs font-semibold text-gray-700 mb-1.5">
|
|
148
|
-
✓ Use instead:
|
|
149
|
-
</p>
|
|
150
|
-
<code className="text-xs text-blue-700 bg-blue-50 px-2 py-1 rounded">
|
|
151
|
-
{suggestion}
|
|
152
|
-
</code>
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
155
|
-
);
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Renders an error message for components not found in any registry
|
|
160
|
-
*/
|
|
161
|
-
const renderNotFoundError = (
|
|
162
|
-
componentName: string,
|
|
163
|
-
key: string,
|
|
164
|
-
): React.ReactNode => {
|
|
165
|
-
return (
|
|
166
|
-
<div
|
|
167
|
-
key={key}
|
|
168
|
-
className="p-3 border border-dashed border-red-500/50 text-red-500 text-xs rounded bg-red-50/30 my-2"
|
|
169
|
-
>
|
|
170
|
-
<span className="font-semibold">❌ Unknown Component:</span>{" "}
|
|
171
|
-
{componentName}
|
|
172
|
-
<p className="text-[10px] text-red-400 mt-1">
|
|
173
|
-
Component not found in Atoms, Molecules, or UI Components registry.
|
|
174
|
-
</p>
|
|
175
|
-
</div>
|
|
176
|
-
);
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Normalizes props and extracts dynamic Tailwind-like classes into inline styles.
|
|
181
|
-
* This ensures that user-entered colors like bg-[#ff0000] work even if not in the bundle.
|
|
182
|
-
*/
|
|
183
|
-
const normalizeProps = (
|
|
184
|
-
props: Record<string, any>,
|
|
185
|
-
): { normalized: Record<string, any>; dynamicStyle: React.CSSProperties } => {
|
|
186
|
-
const normalized: Record<string, any> = {};
|
|
187
|
-
const dynamicStyle: any = {};
|
|
188
|
-
|
|
189
|
-
Object.entries(props).forEach(([key, value]) => {
|
|
190
|
-
// 1. Handle className parsing for dynamic styles
|
|
191
|
-
if (key === "className" && typeof value === "string") {
|
|
192
|
-
// Improved split that handles Tailwind arbitrary values with spaces/underscores inside brackets
|
|
193
|
-
const classes = value.match(/(?:[^\s\[]|\[[^\]]*\])+/g) || [];
|
|
194
|
-
classes.forEach((cls) => {
|
|
195
|
-
// Hex colors: bg-[#...], text-[#...], border-[#...] (supporting opacity/etc)
|
|
196
|
-
const hexMatch = cls.match(
|
|
197
|
-
/^(bg|text|border)-\[#([0-9a-fA-F]{3,6})(?:\/(\d+))?\]$/,
|
|
198
|
-
);
|
|
199
|
-
if (hexMatch) {
|
|
200
|
-
const [, type, hex, opacity] = hexMatch;
|
|
201
|
-
const color = `#${hex}${
|
|
202
|
-
opacity
|
|
203
|
-
? Math.round((parseInt(opacity) / 100) * 255)
|
|
204
|
-
.toString(16)
|
|
205
|
-
.padStart(2, "0")
|
|
206
|
-
: ""
|
|
207
|
-
}`;
|
|
208
|
-
if (type === "bg") dynamicStyle.backgroundColor = color;
|
|
209
|
-
if (type === "text") dynamicStyle.color = color;
|
|
210
|
-
if (type === "border") dynamicStyle.borderColor = color;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Arbitrary rounding: rounded-[...]
|
|
214
|
-
const roundedMatch = cls.match(/^rounded-\[(.+)\]$/);
|
|
215
|
-
if (roundedMatch) {
|
|
216
|
-
dynamicStyle.borderRadius = roundedMatch[1].replace(/_/g, " ");
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Arbitrary padding: p-[...], px-[...], py-[...]
|
|
220
|
-
const paddingMatch = cls.match(/^(p|px|py)-\[(.+)\]$/);
|
|
221
|
-
if (paddingMatch) {
|
|
222
|
-
const [, type, val] = paddingMatch;
|
|
223
|
-
const cssVal = val.replace(/_/g, " ");
|
|
224
|
-
if (type === "p") dynamicStyle.padding = cssVal;
|
|
225
|
-
if (type === "px") {
|
|
226
|
-
dynamicStyle.paddingLeft = cssVal;
|
|
227
|
-
dynamicStyle.paddingRight = cssVal;
|
|
228
|
-
}
|
|
229
|
-
if (type === "py") {
|
|
230
|
-
dynamicStyle.paddingTop = cssVal;
|
|
231
|
-
dynamicStyle.paddingBottom = cssVal;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Arbitrary shadows: shadow-[...]
|
|
236
|
-
const shadowMatch = cls.match(/^shadow-\[(.+)\]$/);
|
|
237
|
-
if (shadowMatch) {
|
|
238
|
-
dynamicStyle.boxShadow = shadowMatch[1].replace(/_/g, " ");
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
normalized[key] = value;
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Skip technical internal props that shouldn't leak into DOM
|
|
246
|
-
if (["type", "component", "name"].includes(key)) {
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// 2. Handle stringified booleans
|
|
251
|
-
if (value === "true") {
|
|
252
|
-
normalized[key] = true;
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
if (value === "false") {
|
|
256
|
-
normalized[key] = false;
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// 3. Handle stringified numbers
|
|
261
|
-
if (
|
|
262
|
-
typeof value === "string" &&
|
|
263
|
-
value.trim() !== "" &&
|
|
264
|
-
!isNaN(Number(value)) &&
|
|
265
|
-
(value.includes(".") ||
|
|
266
|
-
(value.length < 10 && !value.startsWith("0")) ||
|
|
267
|
-
value === "0")
|
|
268
|
-
) {
|
|
269
|
-
normalized[key] = Number(value);
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
normalized[key] = value;
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
return { normalized, dynamicStyle };
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
export const PXEngineRenderer: React.FC<PXEngineRendererProps> = ({
|
|
280
|
-
schema,
|
|
281
|
-
onAction,
|
|
282
|
-
}) => {
|
|
283
|
-
if (!schema) return null;
|
|
284
|
-
|
|
285
|
-
// Extract root if it's a full UISchema
|
|
286
|
-
const root = (schema as any).root || (schema as UIComponent);
|
|
287
|
-
|
|
288
|
-
const renderRecursive = (
|
|
289
|
-
component: UIComponent | string | any,
|
|
290
|
-
index?: number,
|
|
291
|
-
): React.ReactNode => {
|
|
292
|
-
// 1. Handle text nodes (string or number)
|
|
293
|
-
if (typeof component === "string" || typeof component === "number") {
|
|
294
|
-
return component;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// 2. Handle already rendered React elements
|
|
298
|
-
if (React.isValidElement(component)) {
|
|
299
|
-
return component;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
if (!component || typeof component !== "object") return null;
|
|
303
|
-
|
|
304
|
-
// Support 'component' alias for name/type
|
|
305
|
-
const {
|
|
306
|
-
type,
|
|
307
|
-
name,
|
|
308
|
-
component: componentType,
|
|
309
|
-
props = {},
|
|
310
|
-
children = [],
|
|
311
|
-
id,
|
|
312
|
-
...remainingProps
|
|
313
|
-
} = component;
|
|
314
|
-
|
|
315
|
-
// Determine the component logic name to search for
|
|
316
|
-
const componentName = name || type || componentType;
|
|
317
|
-
if (!componentName || typeof componentName !== "string") return null;
|
|
318
|
-
|
|
319
|
-
// Merge explicit props with flattened props (remainingProps)
|
|
320
|
-
// Priority: explicit props > flattened props
|
|
321
|
-
const rawProps = { ...remainingProps, ...props };
|
|
322
|
-
const { normalized: finalProps, dynamicStyle } = normalizeProps(rawProps);
|
|
323
|
-
|
|
324
|
-
// Also pass ID if not already in props
|
|
325
|
-
if (id && !finalProps.id) {
|
|
326
|
-
finalProps.id = id;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Generate a unique key from id, index, or random
|
|
330
|
-
const uniqueKey =
|
|
331
|
-
id ||
|
|
332
|
-
`${componentName}-${index || Math.random().toString(36).substr(2, 9)}`;
|
|
333
|
-
|
|
334
|
-
// Normalize name to PascalCase for the *primary* identifier
|
|
335
|
-
const normalizedName =
|
|
336
|
-
componentName.charAt(0).toUpperCase() + componentName.slice(1);
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Helper to resolve a component by a given identifier string.
|
|
340
|
-
* Checks Atoms -> Molecules -> UI Components.
|
|
341
|
-
*/
|
|
342
|
-
const resolveComponent = (identifier: string) => {
|
|
343
|
-
const normalized =
|
|
344
|
-
identifier.charAt(0).toUpperCase() + identifier.slice(1);
|
|
345
|
-
const atomName = normalized.endsWith("Atom")
|
|
346
|
-
? normalized
|
|
347
|
-
: `${normalized}Atom`;
|
|
348
|
-
|
|
349
|
-
// Priority 1: Atoms
|
|
350
|
-
let Comp =
|
|
351
|
-
(Atoms as any)[atomName] ||
|
|
352
|
-
(Atoms as any)[normalized] ||
|
|
353
|
-
(Atoms as any)[identifier];
|
|
354
|
-
|
|
355
|
-
// Priority 2: Molecules
|
|
356
|
-
if (!Comp) {
|
|
357
|
-
Comp = (Molecules as any)[normalized] || (Molecules as any)[identifier];
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// Priority 3: UI Components
|
|
361
|
-
if (!Comp && !CONTEXT_DEPENDENT_COMPONENTS.has(normalized)) {
|
|
362
|
-
Comp =
|
|
363
|
-
(UIComponents as any)[normalized] ||
|
|
364
|
-
(UIComponents as any)[identifier];
|
|
365
|
-
}
|
|
366
|
-
return Comp;
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
// 1. Attempt using 'name' (or 'type' if name matches)
|
|
370
|
-
let TargetComponent = resolveComponent(componentName);
|
|
371
|
-
let resolvedIdentifier = componentName;
|
|
372
|
-
|
|
373
|
-
// 2. FALLBACK: If 'name' failed but 'type' is different, try 'type'
|
|
374
|
-
// This allows "name": "Dashboard" (descriptive) with "type": "layout" (functional)
|
|
375
|
-
if (!TargetComponent && type && type !== componentName) {
|
|
376
|
-
TargetComponent = resolveComponent(type);
|
|
377
|
-
if (TargetComponent) {
|
|
378
|
-
resolvedIdentifier = type;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// 4. Handle component not found or context-dependent
|
|
383
|
-
if (!TargetComponent) {
|
|
384
|
-
if (CONTEXT_DEPENDENT_COMPONENTS.has(normalizedName)) {
|
|
385
|
-
return renderContextDependentError(
|
|
386
|
-
componentName,
|
|
387
|
-
normalizedName,
|
|
388
|
-
uniqueKey,
|
|
389
|
-
);
|
|
390
|
-
} else {
|
|
391
|
-
// Show generic "not found" error
|
|
392
|
-
console.warn(
|
|
393
|
-
`[PXEngineRenderer] Component not found: ${componentName}`,
|
|
394
|
-
);
|
|
395
|
-
return renderNotFoundError(componentName, uniqueKey);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// Calculate atom name for the *resolved* component to check for render props
|
|
400
|
-
const resolvedNormalized =
|
|
401
|
-
resolvedIdentifier.charAt(0).toUpperCase() + resolvedIdentifier.slice(1);
|
|
402
|
-
const atomName = resolvedNormalized.endsWith("Atom")
|
|
403
|
-
? resolvedNormalized
|
|
404
|
-
: `${resolvedNormalized}Atom`;
|
|
405
|
-
|
|
406
|
-
// 4. Determine if component expects 'renderComponent' prop (for Atoms with children management)
|
|
407
|
-
// Only components that explicitly handle children via renderComponent should get it
|
|
408
|
-
const ATOMS_WITH_RENDER = new Set([
|
|
409
|
-
"LayoutAtom",
|
|
410
|
-
"CardAtom",
|
|
411
|
-
"TabsAtom",
|
|
412
|
-
"AccordionAtom",
|
|
413
|
-
"ScrollAreaAtom",
|
|
414
|
-
"CarouselAtom",
|
|
415
|
-
"AspectRatioAtom",
|
|
416
|
-
"CollapsibleAtom",
|
|
417
|
-
"TooltipAtom",
|
|
418
|
-
"PopoverAtom",
|
|
419
|
-
"DialogAtom",
|
|
420
|
-
"SheetAtom",
|
|
421
|
-
"ResizableAtom",
|
|
422
|
-
]);
|
|
423
|
-
const isAtomWithRenderProp = ATOMS_WITH_RENDER.has(atomName);
|
|
424
|
-
|
|
425
|
-
// 5. Render Component
|
|
426
|
-
// Merge dynamic style with existing style prop if any
|
|
427
|
-
const finalStyle = { ...dynamicStyle, ...(finalProps.style || {}) };
|
|
428
|
-
|
|
429
|
-
if (isAtomWithRenderProp) {
|
|
430
|
-
// Atoms handle their own children via renderComponent
|
|
431
|
-
return (
|
|
432
|
-
<TargetComponent
|
|
433
|
-
key={uniqueKey}
|
|
434
|
-
{...finalProps}
|
|
435
|
-
style={finalStyle}
|
|
436
|
-
onAction={onAction}
|
|
437
|
-
renderComponent={renderRecursive}
|
|
438
|
-
children={children}
|
|
439
|
-
/>
|
|
440
|
-
);
|
|
441
|
-
} else {
|
|
442
|
-
// Standard shadcn components - pass children as React children
|
|
443
|
-
return (
|
|
444
|
-
<TargetComponent key={uniqueKey} {...finalProps} style={finalStyle}>
|
|
445
|
-
{Array.isArray(children)
|
|
446
|
-
? children.map((child, idx) => renderRecursive(child, idx))
|
|
447
|
-
: children}
|
|
448
|
-
</TargetComponent>
|
|
449
|
-
);
|
|
450
|
-
}
|
|
451
|
-
};
|
|
452
|
-
|
|
453
|
-
return (
|
|
454
|
-
<div className="px-engine-root relative w-full h-full">
|
|
455
|
-
{renderRecursive(root)}
|
|
456
|
-
</div>
|
|
457
|
-
);
|
|
458
|
-
};
|
package/src/render/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./PXEngineRenderer";
|
package/src/styles/globals.css
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
|
|
3
|
-
@custom-variant dark (&:is(.dark *));
|
|
4
|
-
@tailwind components;
|
|
5
|
-
@tailwind utilities;
|
|
6
|
-
|
|
7
|
-
@layer base {
|
|
8
|
-
:root {
|
|
9
|
-
--background: 0 0% 100%;
|
|
10
|
-
--foreground: 222.2 84% 4.9%;
|
|
11
|
-
--card: 0 0% 100%;
|
|
12
|
-
--card-foreground: 222.2 84% 4.9%;
|
|
13
|
-
--popover: 0 0% 100%;
|
|
14
|
-
--popover-foreground: 222.2 84% 4.9%;
|
|
15
|
-
--primary: 222.2 47.4% 11.2%;
|
|
16
|
-
--primary-foreground: 210 40% 98%;
|
|
17
|
-
--secondary: 210 40% 96.1%;
|
|
18
|
-
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
19
|
-
--muted: 210 40% 96.1%;
|
|
20
|
-
--muted-foreground: 215.4 16.3% 46.9%;
|
|
21
|
-
--accent: 210 40% 96.1%;
|
|
22
|
-
--accent-foreground: 222.2 47.4% 11.2%;
|
|
23
|
-
--destructive: 0 84.2% 60.2%;
|
|
24
|
-
--destructive-foreground: 210 40% 98%;
|
|
25
|
-
--border: 214.3 31.8% 91.4%;
|
|
26
|
-
--input: 214.3 31.8% 91.4%;
|
|
27
|
-
--ring: 222.2 84% 4.9%;
|
|
28
|
-
--radius: 0.5rem;
|
|
29
|
-
|
|
30
|
-
/* Custom theme variables (will be inherited from client) */
|
|
31
|
-
--gray25: #fcfcfd;
|
|
32
|
-
--gray50: #f9fafb;
|
|
33
|
-
--gray100: #f2f4f7;
|
|
34
|
-
--gray200: #eaecf0;
|
|
35
|
-
--gray300: #d0d5dd;
|
|
36
|
-
--gray400: #98a2b3;
|
|
37
|
-
--gray500: #667085;
|
|
38
|
-
--gray600: #475467;
|
|
39
|
-
--gray700: #344054;
|
|
40
|
-
--gray800: #1d2939;
|
|
41
|
-
--gray900: #101828;
|
|
42
|
-
--purple100: #f4f3ff;
|
|
43
|
-
--purple200: #988cff;
|
|
44
|
-
--purple500: #6941c6;
|
|
45
|
-
--purple-text: #7f56d9;
|
|
46
|
-
--purple50: #f9f5ff;
|
|
47
|
-
--purple20: #f4ebff;
|
|
48
|
-
--purple-border: #d6bbfb;
|
|
49
|
-
--purpleLight: #f4f3ff;
|
|
50
|
-
--purple-text-1: #7f56d9;
|
|
51
|
-
--purple-text-2: #6941c6;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.dark {
|
|
55
|
-
--background: 222.2 84% 4.9%;
|
|
56
|
-
--foreground: 210 40% 98%;
|
|
57
|
-
--card: 222.2 84% 4.9%;
|
|
58
|
-
--card-foreground: 210 40% 98%;
|
|
59
|
-
--popover: 222.2 84% 4.9%;
|
|
60
|
-
--popover-foreground: 210 40% 98%;
|
|
61
|
-
--primary: 210 40% 98%;
|
|
62
|
-
--primary-foreground: 222.2 47.4% 11.2%;
|
|
63
|
-
--secondary: 217.2 32.6% 17.5%;
|
|
64
|
-
--secondary-foreground: 210 40% 98%;
|
|
65
|
-
--muted: 217.2 32.6% 17.5%;
|
|
66
|
-
--muted-foreground: 215 20.2% 65.1%;
|
|
67
|
-
--accent: 217.2 32.6% 17.5%;
|
|
68
|
-
--accent-foreground: 210 40% 98%;
|
|
69
|
-
--destructive: 0 62.8% 30.6%;
|
|
70
|
-
--destructive-foreground: 210 40% 98%;
|
|
71
|
-
--border: 217.2 32.6% 17.5%;
|
|
72
|
-
--input: 217.2 32.6% 17.5%;
|
|
73
|
-
--ring: 212.7 26.8% 83.9%;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
@layer base {
|
|
78
|
-
* {
|
|
79
|
-
@apply border-border;
|
|
80
|
-
}
|
|
81
|
-
body {
|
|
82
|
-
@apply bg-background text-foreground;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
:root {
|
|
87
|
-
--sidebar: hsl(0 0% 98%);
|
|
88
|
-
--sidebar-foreground: hsl(240 5.3% 26.1%);
|
|
89
|
-
--sidebar-primary: hsl(240 5.9% 10%);
|
|
90
|
-
--sidebar-primary-foreground: hsl(0 0% 98%);
|
|
91
|
-
--sidebar-accent: hsl(240 4.8% 95.9%);
|
|
92
|
-
--sidebar-accent-foreground: hsl(240 5.9% 10%);
|
|
93
|
-
--sidebar-border: hsl(220 13% 91%);
|
|
94
|
-
--sidebar-ring: hsl(217.2 91.2% 59.8%);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.dark {
|
|
98
|
-
--sidebar: hsl(240 5.9% 10%);
|
|
99
|
-
--sidebar-foreground: hsl(240 4.8% 95.9%);
|
|
100
|
-
--sidebar-primary: hsl(224.3 76.3% 48%);
|
|
101
|
-
--sidebar-primary-foreground: hsl(0 0% 100%);
|
|
102
|
-
--sidebar-accent: hsl(240 3.7% 15.9%);
|
|
103
|
-
--sidebar-accent-foreground: hsl(240 4.8% 95.9%);
|
|
104
|
-
--sidebar-border: hsl(240 3.7% 15.9%);
|
|
105
|
-
--sidebar-ring: hsl(217.2 91.2% 59.8%);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
@theme inline {
|
|
109
|
-
--color-sidebar: var(--sidebar);
|
|
110
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
111
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
112
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
113
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
114
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
115
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
116
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
117
|
-
--animate-accordion-down: accordion-down 0.2s ease-out;
|
|
118
|
-
--animate-accordion-up: accordion-up 0.2s ease-out;
|
|
119
|
-
|
|
120
|
-
@keyframes accordion-down {
|
|
121
|
-
from {
|
|
122
|
-
height: 0;
|
|
123
|
-
}
|
|
124
|
-
to {
|
|
125
|
-
height: var(--radix-accordion-content-height);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
@keyframes accordion-up {
|
|
130
|
-
from {
|
|
131
|
-
height: var(--radix-accordion-content-height);
|
|
132
|
-
}
|
|
133
|
-
to {
|
|
134
|
-
height: 0;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
@layer base {
|
|
140
|
-
* {
|
|
141
|
-
@apply border-border outline-ring/50;
|
|
142
|
-
}
|
|
143
|
-
body {
|
|
144
|
-
@apply bg-background text-foreground;
|
|
145
|
-
}
|
|
146
|
-
}
|