pxengine 0.1.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.
- package/README.md +175 -0
- package/config/tailwind-preset.js +106 -0
- package/dist/index.d.mts +1259 -0
- package/dist/index.d.ts +1259 -0
- package/dist/index.js +5175 -0
- package/dist/index.mjs +4929 -0
- package/package.json +94 -0
- package/src/atoms/AccordionAtom.tsx +44 -0
- package/src/atoms/AlertAtom.tsx +46 -0
- package/src/atoms/AlertDialogAtom.tsx +66 -0
- package/src/atoms/AspectRatioAtom.tsx +27 -0
- package/src/atoms/AvatarAtom.tsx +20 -0
- package/src/atoms/BadgeAtom.tsx +25 -0
- package/src/atoms/BreadcrumbAtom.tsx +36 -0
- package/src/atoms/ButtonAtom.tsx +63 -0
- package/src/atoms/CalendarAtom.tsx +24 -0
- package/src/atoms/CardAtom.tsx +64 -0
- package/src/atoms/CarouselAtom.tsx +40 -0
- package/src/atoms/CollapsibleAtom.tsx +44 -0
- package/src/atoms/CommandAtom.tsx +46 -0
- package/src/atoms/DialogAtom.tsx +68 -0
- package/src/atoms/InputAtom.tsx +162 -0
- package/src/atoms/LayoutAtom.tsx +43 -0
- package/src/atoms/PaginationAtom.tsx +49 -0
- package/src/atoms/PopoverAtom.tsx +40 -0
- package/src/atoms/ProgressAtom.tsx +15 -0
- package/src/atoms/ScrollAreaAtom.tsx +31 -0
- package/src/atoms/SeparatorAtom.tsx +16 -0
- package/src/atoms/SheetAtom.tsx +72 -0
- package/src/atoms/SkeletonAtom.tsx +22 -0
- package/src/atoms/SpinnerAtom.tsx +26 -0
- package/src/atoms/TableAtom.tsx +58 -0
- package/src/atoms/TabsAtom.tsx +40 -0
- package/src/atoms/TextAtom.tsx +35 -0
- package/src/atoms/TooltipAtom.tsx +39 -0
- package/src/atoms/index.ts +28 -0
- package/src/components/index.ts +178 -0
- package/src/components/ui/accordion.tsx +56 -0
- package/src/components/ui/alert-dialog.tsx +139 -0
- package/src/components/ui/alert.tsx +59 -0
- package/src/components/ui/aspect-ratio.tsx +5 -0
- package/src/components/ui/avatar.tsx +50 -0
- package/src/components/ui/badge.tsx +36 -0
- package/src/components/ui/breadcrumb.tsx +115 -0
- package/src/components/ui/button-group.tsx +83 -0
- package/src/components/ui/button.tsx +56 -0
- package/src/components/ui/calendar.tsx +213 -0
- package/src/components/ui/card.tsx +79 -0
- package/src/components/ui/carousel.tsx +260 -0
- package/src/components/ui/chart.tsx +367 -0
- package/src/components/ui/checkbox.tsx +28 -0
- package/src/components/ui/collapsible.tsx +11 -0
- package/src/components/ui/command.tsx +153 -0
- package/src/components/ui/context-menu.tsx +198 -0
- package/src/components/ui/dialog.tsx +122 -0
- package/src/components/ui/drawer.tsx +116 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/empty.tsx +104 -0
- package/src/components/ui/field.tsx +244 -0
- package/src/components/ui/form.tsx +176 -0
- package/src/components/ui/hover-card.tsx +27 -0
- package/src/components/ui/input-group.tsx +168 -0
- package/src/components/ui/input-otp.tsx +69 -0
- package/src/components/ui/input.tsx +22 -0
- package/src/components/ui/item.tsx +193 -0
- package/src/components/ui/kbd.tsx +28 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/menubar.tsx +254 -0
- package/src/components/ui/navigation-menu.tsx +128 -0
- package/src/components/ui/pagination.tsx +117 -0
- package/src/components/ui/popover.tsx +29 -0
- package/src/components/ui/progress.tsx +28 -0
- package/src/components/ui/radio-group.tsx +42 -0
- package/src/components/ui/resizable.tsx +45 -0
- package/src/components/ui/scroll-area.tsx +46 -0
- package/src/components/ui/select.tsx +160 -0
- package/src/components/ui/separator.tsx +29 -0
- package/src/components/ui/sheet.tsx +140 -0
- package/src/components/ui/sidebar.tsx +771 -0
- package/src/components/ui/skeleton.tsx +15 -0
- package/src/components/ui/slider.tsx +26 -0
- package/src/components/ui/sonner.tsx +45 -0
- package/src/components/ui/spinner.tsx +16 -0
- package/src/components/ui/switch.tsx +27 -0
- package/src/components/ui/table.tsx +117 -0
- package/src/components/ui/tabs.tsx +53 -0
- package/src/components/ui/textarea.tsx +22 -0
- package/src/components/ui/toggle-group.tsx +61 -0
- package/src/components/ui/toggle.tsx +43 -0
- package/src/components/ui/tooltip.tsx +30 -0
- package/src/hooks/use-mobile.tsx +19 -0
- package/src/index.ts +24 -0
- package/src/lib/countries.ts +203 -0
- package/src/lib/index.ts +2 -0
- package/src/lib/utils.ts +15 -0
- package/src/lib/validators/index.ts +1 -0
- package/src/lib/validators/theme.ts +148 -0
- package/src/molecules/creator-discovery/CampaignSeedCard/CampaignSeedCard.tsx +123 -0
- package/src/molecules/creator-discovery/CampaignSeedCard/CampaignSeedCard.types.ts +13 -0
- package/src/molecules/creator-discovery/CampaignSeedCard/index.ts +2 -0
- package/src/molecules/creator-discovery/MCQCard/MCQCard.tsx +165 -0
- package/src/molecules/creator-discovery/MCQCard/MCQCard.types.ts +71 -0
- package/src/molecules/creator-discovery/MCQCard/index.ts +2 -0
- package/src/molecules/creator-discovery/SearchSpecCard/CustomFieldRenderers.tsx +334 -0
- package/src/molecules/creator-discovery/SearchSpecCard/SearchSpecCard.tsx +111 -0
- package/src/molecules/creator-discovery/SearchSpecCard/SearchSpecCard.types.ts +18 -0
- package/src/molecules/creator-discovery/SearchSpecCard/index.ts +3 -0
- package/src/molecules/creator-discovery/index.ts +3 -0
- package/src/molecules/generic/ActionButton/ActionButton.tsx +137 -0
- package/src/molecules/generic/ActionButton/ActionButton.types.ts +68 -0
- package/src/molecules/generic/ActionButton/index.ts +2 -0
- package/src/molecules/generic/EditableField/EditableField.tsx +229 -0
- package/src/molecules/generic/EditableField/EditableField.types.ts +73 -0
- package/src/molecules/generic/EditableField/index.ts +2 -0
- package/src/molecules/generic/FormCard/FormCard.tsx +136 -0
- package/src/molecules/generic/FormCard/FormCard.types.ts +93 -0
- package/src/molecules/generic/FormCard/index.ts +2 -0
- package/src/molecules/generic/index.ts +3 -0
- package/src/molecules/index.ts +2 -0
- package/src/render/PXEngineRenderer.tsx +272 -0
- package/src/render/index.ts +1 -0
- package/src/styles/globals.css +146 -0
- package/src/types/atoms.ts +294 -0
- package/src/types/common.ts +116 -0
- package/src/types/index.ts +3 -0
- package/src/types/molecules.ts +54 -0
- package/src/types/schema.ts +12 -0
package/package.json
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pxengine",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shadcn-based UI component library for agent-driven interfaces",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"config",
|
|
11
|
+
"src"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
15
|
+
"dev": "tsup src/index.ts --format cjs,esm --watch --dts",
|
|
16
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
17
|
+
"type-check": "tsc --noEmit"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"react",
|
|
21
|
+
"ui",
|
|
22
|
+
"components",
|
|
23
|
+
"shadcn",
|
|
24
|
+
"tailwind",
|
|
25
|
+
"atomic-design",
|
|
26
|
+
"agent-ui"
|
|
27
|
+
],
|
|
28
|
+
"author": "PXEngine Team",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"react": "^18.0.0",
|
|
32
|
+
"react-dom": "^18.0.0",
|
|
33
|
+
"tailwindcss": "^3.4.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^20.19.30",
|
|
37
|
+
"@types/react": "^19.0.2",
|
|
38
|
+
"@types/react-dom": "^19.0.2",
|
|
39
|
+
"autoprefixer": "^10.4.23",
|
|
40
|
+
"eslint": "^8.0.0",
|
|
41
|
+
"postcss": "^8.5.6",
|
|
42
|
+
"tailwindcss": "^4.1.18",
|
|
43
|
+
"tailwindcss-animate": "^1.0.7",
|
|
44
|
+
"tsup": "^8.3.5",
|
|
45
|
+
"typescript": "^5.7.2"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@hookform/resolvers": "^5.2.2",
|
|
49
|
+
"@radix-ui/react-accordion": "^1.2.12",
|
|
50
|
+
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
51
|
+
"@radix-ui/react-aspect-ratio": "^1.1.8",
|
|
52
|
+
"@radix-ui/react-avatar": "^1.1.11",
|
|
53
|
+
"@radix-ui/react-checkbox": "^1.3.3",
|
|
54
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
55
|
+
"@radix-ui/react-context-menu": "^2.2.16",
|
|
56
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
57
|
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
58
|
+
"@radix-ui/react-hover-card": "^1.1.15",
|
|
59
|
+
"@radix-ui/react-label": "^2.1.8",
|
|
60
|
+
"@radix-ui/react-menubar": "^1.1.16",
|
|
61
|
+
"@radix-ui/react-navigation-menu": "^1.2.14",
|
|
62
|
+
"@radix-ui/react-popover": "^1.1.15",
|
|
63
|
+
"@radix-ui/react-progress": "^1.1.8",
|
|
64
|
+
"@radix-ui/react-radio-group": "^1.3.8",
|
|
65
|
+
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
66
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
67
|
+
"@radix-ui/react-separator": "^1.1.8",
|
|
68
|
+
"@radix-ui/react-slider": "^1.3.6",
|
|
69
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
70
|
+
"@radix-ui/react-switch": "^1.2.6",
|
|
71
|
+
"@radix-ui/react-tabs": "^1.1.13",
|
|
72
|
+
"@radix-ui/react-toggle": "^1.1.10",
|
|
73
|
+
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
74
|
+
"@radix-ui/react-tooltip": "^1.2.8",
|
|
75
|
+
"class-variance-authority": "^0.7.1",
|
|
76
|
+
"clsx": "^2.1.1",
|
|
77
|
+
"cmdk": "^1.1.1",
|
|
78
|
+
"date-fns": "^4.1.0",
|
|
79
|
+
"embla-carousel-react": "^8.6.0",
|
|
80
|
+
"framer-motion": "^11.18.2",
|
|
81
|
+
"input-otp": "^1.4.2",
|
|
82
|
+
"lucide-react": "^0.475.0",
|
|
83
|
+
"next-themes": "^0.4.6",
|
|
84
|
+
"rc-slider": "^11.1.7",
|
|
85
|
+
"react-day-picker": "^9.13.0",
|
|
86
|
+
"react-hook-form": "^7.71.1",
|
|
87
|
+
"react-resizable-panels": "^4.5.2",
|
|
88
|
+
"recharts": "^2.15.4",
|
|
89
|
+
"sonner": "^2.0.7",
|
|
90
|
+
"tailwind-merge": "^2.6.0",
|
|
91
|
+
"vaul": "^1.1.2",
|
|
92
|
+
"zod": "^4.3.6"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Accordion,
|
|
4
|
+
AccordionItem,
|
|
5
|
+
AccordionTrigger,
|
|
6
|
+
AccordionContent,
|
|
7
|
+
} from "@/components/ui/accordion";
|
|
8
|
+
import { AccordionAtomType, UIComponent } from "../types/schema";
|
|
9
|
+
import { cn } from "@/lib/utils";
|
|
10
|
+
|
|
11
|
+
interface Props extends AccordionAtomType {
|
|
12
|
+
renderComponent: (component: UIComponent) => React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const AccordionAtom: React.FC<Props> = ({
|
|
16
|
+
items,
|
|
17
|
+
className,
|
|
18
|
+
renderComponent,
|
|
19
|
+
}) => {
|
|
20
|
+
return (
|
|
21
|
+
<Accordion type="single" collapsible className={cn("w-full", className)}>
|
|
22
|
+
{items.map((item) => (
|
|
23
|
+
<AccordionItem
|
|
24
|
+
key={item.value}
|
|
25
|
+
value={item.value}
|
|
26
|
+
className="border-gray-100"
|
|
27
|
+
>
|
|
28
|
+
<AccordionTrigger className="text-sm font-semibold hover:no-underline hover:text-purple600 py-4">
|
|
29
|
+
{item.trigger}
|
|
30
|
+
</AccordionTrigger>
|
|
31
|
+
<AccordionContent>
|
|
32
|
+
<div className="pt-2 pb-4">
|
|
33
|
+
{item.content.map((child) => (
|
|
34
|
+
<React.Fragment key={child.id}>
|
|
35
|
+
{renderComponent(child)}
|
|
36
|
+
</React.Fragment>
|
|
37
|
+
))}
|
|
38
|
+
</div>
|
|
39
|
+
</AccordionContent>
|
|
40
|
+
</AccordionItem>
|
|
41
|
+
))}
|
|
42
|
+
</Accordion>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
|
|
3
|
+
import { AlertAtomType } from "../types/schema";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
import { AlertCircle, CheckCircle2, Info, AlertTriangle } from "lucide-react";
|
|
6
|
+
|
|
7
|
+
export const AlertAtom: React.FC<AlertAtomType> = ({
|
|
8
|
+
title,
|
|
9
|
+
description,
|
|
10
|
+
variant = "default",
|
|
11
|
+
className,
|
|
12
|
+
}) => {
|
|
13
|
+
const IconMap: any = {
|
|
14
|
+
default: Info,
|
|
15
|
+
destructive: AlertCircle,
|
|
16
|
+
warning: AlertTriangle,
|
|
17
|
+
info: Info,
|
|
18
|
+
success: CheckCircle2,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const Icon = IconMap[variant] || Info;
|
|
22
|
+
|
|
23
|
+
const variantMap: any = {
|
|
24
|
+
warning:
|
|
25
|
+
"border-amber-200 bg-amber-50 text-amber-900 [&>svg]:text-amber-600",
|
|
26
|
+
info: "border-blue-200 bg-blue-50 text-blue-900 [&>svg]:text-blue-600",
|
|
27
|
+
success:
|
|
28
|
+
"border-green-200 bg-green-50 text-green-900 [&>svg]:text-green-600",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const customClass = variantMap[variant] || "";
|
|
32
|
+
const shadcnVariant = ["warning", "info", "success"].includes(variant)
|
|
33
|
+
? "default"
|
|
34
|
+
: (variant as any);
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Alert
|
|
38
|
+
variant={shadcnVariant}
|
|
39
|
+
className={cn("rounded-2xl", customClass, className)}
|
|
40
|
+
>
|
|
41
|
+
<Icon className="h-4 w-4" />
|
|
42
|
+
<AlertTitle className="font-bold">{title}</AlertTitle>
|
|
43
|
+
{description && <AlertDescription>{description}</AlertDescription>}
|
|
44
|
+
</Alert>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
AlertDialog,
|
|
4
|
+
AlertDialogAction,
|
|
5
|
+
AlertDialogCancel,
|
|
6
|
+
AlertDialogContent,
|
|
7
|
+
AlertDialogDescription,
|
|
8
|
+
AlertDialogFooter,
|
|
9
|
+
AlertDialogHeader,
|
|
10
|
+
AlertDialogTitle,
|
|
11
|
+
AlertDialogTrigger,
|
|
12
|
+
} from "@/components/ui/alert-dialog";
|
|
13
|
+
import { AlertDialogAtomType, UIComponent } from "../types/schema";
|
|
14
|
+
import { cn } from "@/lib/utils";
|
|
15
|
+
|
|
16
|
+
interface Props extends AlertDialogAtomType {
|
|
17
|
+
renderComponent: (component: UIComponent) => React.ReactNode;
|
|
18
|
+
onAction?: (action: string) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const AlertDialogAtom: React.FC<Props> = ({
|
|
22
|
+
title,
|
|
23
|
+
description,
|
|
24
|
+
trigger,
|
|
25
|
+
confirmLabel = "Continue",
|
|
26
|
+
cancelLabel = "Cancel",
|
|
27
|
+
action,
|
|
28
|
+
onAction,
|
|
29
|
+
className,
|
|
30
|
+
renderComponent,
|
|
31
|
+
}) => {
|
|
32
|
+
return (
|
|
33
|
+
<AlertDialog>
|
|
34
|
+
<AlertDialogTrigger asChild>
|
|
35
|
+
<div className={cn("inline-block cursor-pointer", className)}>
|
|
36
|
+
{trigger.map((child) => (
|
|
37
|
+
<React.Fragment key={child.id}>
|
|
38
|
+
{renderComponent(child)}
|
|
39
|
+
</React.Fragment>
|
|
40
|
+
))}
|
|
41
|
+
</div>
|
|
42
|
+
</AlertDialogTrigger>
|
|
43
|
+
<AlertDialogContent className="rounded-3xl p-6 bg-white shadow-3xl border-gray-100">
|
|
44
|
+
<AlertDialogHeader>
|
|
45
|
+
<AlertDialogTitle className="text-lg font-bold text-gray-900">
|
|
46
|
+
{title}
|
|
47
|
+
</AlertDialogTitle>
|
|
48
|
+
<AlertDialogDescription className="text-gray-500 font-medium">
|
|
49
|
+
{description}
|
|
50
|
+
</AlertDialogDescription>
|
|
51
|
+
</AlertDialogHeader>
|
|
52
|
+
<AlertDialogFooter className="gap-2 sm:gap-0">
|
|
53
|
+
<AlertDialogCancel className="rounded-full border-gray-200 hover:bg-gray-50 font-semibold">
|
|
54
|
+
{cancelLabel}
|
|
55
|
+
</AlertDialogCancel>
|
|
56
|
+
<AlertDialogAction
|
|
57
|
+
onClick={() => action && onAction?.(action)}
|
|
58
|
+
className="rounded-full bg-purple500 hover:bg-purple600 text-white font-semibold transition-all shadow-md hover:shadow-lg"
|
|
59
|
+
>
|
|
60
|
+
{confirmLabel}
|
|
61
|
+
</AlertDialogAction>
|
|
62
|
+
</AlertDialogFooter>
|
|
63
|
+
</AlertDialogContent>
|
|
64
|
+
</AlertDialog>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { AspectRatio } from "@/components/ui/aspect-ratio";
|
|
3
|
+
import { AspectRatioAtomType, UIComponent } from "../types/schema";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
interface Props extends AspectRatioAtomType {
|
|
7
|
+
renderComponent: (component: UIComponent) => React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const AspectRatioAtom: React.FC<Props> = ({
|
|
11
|
+
ratio = 16 / 9,
|
|
12
|
+
children,
|
|
13
|
+
className,
|
|
14
|
+
renderComponent,
|
|
15
|
+
}) => {
|
|
16
|
+
return (
|
|
17
|
+
<div className={cn("w-full", className)}>
|
|
18
|
+
<AspectRatio ratio={ratio}>
|
|
19
|
+
{children.map((child) => (
|
|
20
|
+
<React.Fragment key={child.id}>
|
|
21
|
+
{renderComponent(child)}
|
|
22
|
+
</React.Fragment>
|
|
23
|
+
))}
|
|
24
|
+
</AspectRatio>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
|
3
|
+
import { AvatarAtomType } from "../types/schema";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
export const AvatarAtom: React.FC<AvatarAtomType> = ({
|
|
7
|
+
src,
|
|
8
|
+
fallback,
|
|
9
|
+
alt,
|
|
10
|
+
className,
|
|
11
|
+
}) => {
|
|
12
|
+
return (
|
|
13
|
+
<Avatar className={cn("h-10 w-10", className)}>
|
|
14
|
+
{src && <AvatarImage src={src} alt={alt} />}
|
|
15
|
+
<AvatarFallback className="bg-purple50 text-purple600 font-bold uppercase">
|
|
16
|
+
{fallback}
|
|
17
|
+
</AvatarFallback>
|
|
18
|
+
</Avatar>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Badge } from "@/components/ui/badge";
|
|
3
|
+
import { BadgeAtomType } from "../types/schema";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
export const BadgeAtom: React.FC<BadgeAtomType> = ({
|
|
7
|
+
label,
|
|
8
|
+
variant = "default",
|
|
9
|
+
className,
|
|
10
|
+
}) => {
|
|
11
|
+
const customVariants: any = {
|
|
12
|
+
purple: "bg-purple50 text-purple700 border-purple100 hover:bg-purple100",
|
|
13
|
+
green: "bg-green-50 text-green-700 border-green-100 hover:bg-green-100",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const isCustom = ["purple", "green"].includes(variant || "");
|
|
17
|
+
const shadcnVariant = isCustom ? "outline" : (variant as any);
|
|
18
|
+
const customClass = isCustom ? customVariants[variant!] : "";
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Badge variant={shadcnVariant} className={cn(customClass, className)}>
|
|
22
|
+
{label}
|
|
23
|
+
</Badge>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Breadcrumb,
|
|
4
|
+
BreadcrumbItem,
|
|
5
|
+
BreadcrumbLink,
|
|
6
|
+
BreadcrumbList,
|
|
7
|
+
BreadcrumbPage,
|
|
8
|
+
BreadcrumbSeparator,
|
|
9
|
+
} from "@/components/ui/breadcrumb";
|
|
10
|
+
import { BreadcrumbAtomType } from "../types/schema";
|
|
11
|
+
|
|
12
|
+
export const BreadcrumbAtom: React.FC<BreadcrumbAtomType> = ({
|
|
13
|
+
items,
|
|
14
|
+
className,
|
|
15
|
+
}) => {
|
|
16
|
+
return (
|
|
17
|
+
<Breadcrumb className={className}>
|
|
18
|
+
<BreadcrumbList>
|
|
19
|
+
{items.map((item, index) => (
|
|
20
|
+
<React.Fragment key={index}>
|
|
21
|
+
<BreadcrumbItem>
|
|
22
|
+
{item.isCurrent ? (
|
|
23
|
+
<BreadcrumbPage>{item.label}</BreadcrumbPage>
|
|
24
|
+
) : (
|
|
25
|
+
<BreadcrumbLink href={item.href || "#"}>
|
|
26
|
+
{item.label}
|
|
27
|
+
</BreadcrumbLink>
|
|
28
|
+
)}
|
|
29
|
+
</BreadcrumbItem>
|
|
30
|
+
{index < items.length - 1 && <BreadcrumbSeparator />}
|
|
31
|
+
</React.Fragment>
|
|
32
|
+
))}
|
|
33
|
+
</BreadcrumbList>
|
|
34
|
+
</Breadcrumb>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Button } from "@/components/ui/button";
|
|
3
|
+
import { ButtonAtomType } from "../types/schema";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
import { Loader2 } from "lucide-react";
|
|
6
|
+
|
|
7
|
+
interface Props extends ButtonAtomType {
|
|
8
|
+
onAction?: (action: string) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* ButtonAtom
|
|
13
|
+
* Wraps shadcn Button with schema support and premium variants
|
|
14
|
+
*/
|
|
15
|
+
export const ButtonAtom: React.FC<Props> = ({
|
|
16
|
+
label,
|
|
17
|
+
variant = "default",
|
|
18
|
+
size = "default",
|
|
19
|
+
action,
|
|
20
|
+
disabled = false,
|
|
21
|
+
isLoading = false,
|
|
22
|
+
onAction,
|
|
23
|
+
className,
|
|
24
|
+
}) => {
|
|
25
|
+
const handleClick = (e: React.MouseEvent) => {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
e.stopPropagation();
|
|
28
|
+
if (action && onAction) {
|
|
29
|
+
onAction(action);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const variantMap: any = {
|
|
34
|
+
purple:
|
|
35
|
+
"bg-purple500 hover:bg-purple600 text-white shadow-md hover:shadow-lg transition-all",
|
|
36
|
+
gradient:
|
|
37
|
+
"bg-gradient-to-r from-purple500 to-indigo-600 hover:from-purple600 hover:to-indigo-700 text-white shadow-lg",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const customClass = variantMap[variant] || "";
|
|
41
|
+
const shadcnVariant = ["purple", "gradient"].includes(variant)
|
|
42
|
+
? "default"
|
|
43
|
+
: (variant as any);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<Button
|
|
47
|
+
variant={shadcnVariant}
|
|
48
|
+
size={size as any}
|
|
49
|
+
disabled={disabled || isLoading}
|
|
50
|
+
onClick={handleClick}
|
|
51
|
+
className={cn("rounded-full font-semibold", customClass, className)}
|
|
52
|
+
>
|
|
53
|
+
{isLoading ? (
|
|
54
|
+
<>
|
|
55
|
+
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
|
56
|
+
{label}
|
|
57
|
+
</>
|
|
58
|
+
) : (
|
|
59
|
+
label
|
|
60
|
+
)}
|
|
61
|
+
</Button>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Calendar } from "@/components/ui/calendar";
|
|
3
|
+
import { CalendarAtomType } from "../types/schema";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
export const CalendarAtom: React.FC<CalendarAtomType> = ({
|
|
7
|
+
mode = "single",
|
|
8
|
+
selectedDate,
|
|
9
|
+
className,
|
|
10
|
+
}) => {
|
|
11
|
+
// Simple conversion for demonstration
|
|
12
|
+
const date = selectedDate ? new Date(selectedDate as string) : undefined;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div
|
|
16
|
+
className={cn(
|
|
17
|
+
"p-3 bg-white rounded-3xl border border-gray-100 shadow-sm inline-block",
|
|
18
|
+
className,
|
|
19
|
+
)}
|
|
20
|
+
>
|
|
21
|
+
<Calendar mode={mode as any} selected={date} className="rounded-xl" />
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Card,
|
|
4
|
+
CardHeader,
|
|
5
|
+
CardTitle,
|
|
6
|
+
CardDescription,
|
|
7
|
+
CardContent,
|
|
8
|
+
CardFooter,
|
|
9
|
+
} from "@/components/ui/card";
|
|
10
|
+
import { CardAtomType, UIComponent } from "../types/schema";
|
|
11
|
+
import { cn } from "@/lib/utils";
|
|
12
|
+
|
|
13
|
+
interface Props extends CardAtomType {
|
|
14
|
+
renderComponent: (component: UIComponent) => React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* CardAtom
|
|
19
|
+
* Standardized Card wrapper for the Universal Renderer
|
|
20
|
+
*/
|
|
21
|
+
export const CardAtom: React.FC<Props> = ({
|
|
22
|
+
title,
|
|
23
|
+
description,
|
|
24
|
+
children,
|
|
25
|
+
footer,
|
|
26
|
+
className,
|
|
27
|
+
renderComponent,
|
|
28
|
+
}) => {
|
|
29
|
+
return (
|
|
30
|
+
<Card
|
|
31
|
+
className={cn(
|
|
32
|
+
"rounded-[24px] border border-gray200 shadow-sm overflow-hidden",
|
|
33
|
+
className,
|
|
34
|
+
)}
|
|
35
|
+
>
|
|
36
|
+
{(title || description) && (
|
|
37
|
+
<CardHeader>
|
|
38
|
+
{title && (
|
|
39
|
+
<CardTitle className="text-xl font-bold text-gray-900">
|
|
40
|
+
{title}
|
|
41
|
+
</CardTitle>
|
|
42
|
+
)}
|
|
43
|
+
{description && <CardDescription>{description}</CardDescription>}
|
|
44
|
+
</CardHeader>
|
|
45
|
+
)}
|
|
46
|
+
<CardContent className="space-y-4">
|
|
47
|
+
{children.map((child) => (
|
|
48
|
+
<React.Fragment key={child.id}>
|
|
49
|
+
{renderComponent(child)}
|
|
50
|
+
</React.Fragment>
|
|
51
|
+
))}
|
|
52
|
+
</CardContent>
|
|
53
|
+
{footer && footer.length > 0 && (
|
|
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)}
|
|
58
|
+
</React.Fragment>
|
|
59
|
+
))}
|
|
60
|
+
</CardFooter>
|
|
61
|
+
)}
|
|
62
|
+
</Card>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Carousel,
|
|
4
|
+
CarouselContent,
|
|
5
|
+
CarouselItem,
|
|
6
|
+
CarouselNext,
|
|
7
|
+
CarouselPrevious,
|
|
8
|
+
} from "@/components/ui/carousel";
|
|
9
|
+
import { CarouselAtomType, UIComponent } from "../types/schema";
|
|
10
|
+
import { cn } from "@/lib/utils";
|
|
11
|
+
|
|
12
|
+
interface Props extends CarouselAtomType {
|
|
13
|
+
renderComponent: (component: UIComponent) => React.ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const CarouselAtom: React.FC<Props> = ({
|
|
17
|
+
items,
|
|
18
|
+
className,
|
|
19
|
+
renderComponent,
|
|
20
|
+
}) => {
|
|
21
|
+
return (
|
|
22
|
+
<Carousel className={cn("w-full max-w-xs mx-auto", className)}>
|
|
23
|
+
<CarouselContent>
|
|
24
|
+
{items.map((slide, index) => (
|
|
25
|
+
<CarouselItem key={index}>
|
|
26
|
+
<div className="p-1">
|
|
27
|
+
{slide.map((child) => (
|
|
28
|
+
<React.Fragment key={child.id}>
|
|
29
|
+
{renderComponent(child)}
|
|
30
|
+
</React.Fragment>
|
|
31
|
+
))}
|
|
32
|
+
</div>
|
|
33
|
+
</CarouselItem>
|
|
34
|
+
))}
|
|
35
|
+
</CarouselContent>
|
|
36
|
+
<CarouselPrevious />
|
|
37
|
+
<CarouselNext />
|
|
38
|
+
</Carousel>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Collapsible,
|
|
4
|
+
CollapsibleContent,
|
|
5
|
+
CollapsibleTrigger,
|
|
6
|
+
} from "@/components/ui/collapsible";
|
|
7
|
+
import { CollapsibleAtomType, UIComponent } from "../types/schema";
|
|
8
|
+
import { cn } from "@/lib/utils";
|
|
9
|
+
|
|
10
|
+
interface Props extends CollapsibleAtomType {
|
|
11
|
+
renderComponent: (component: UIComponent) => React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const CollapsibleAtom: React.FC<Props> = ({
|
|
15
|
+
trigger,
|
|
16
|
+
content,
|
|
17
|
+
defaultOpen = false,
|
|
18
|
+
className,
|
|
19
|
+
renderComponent,
|
|
20
|
+
}) => {
|
|
21
|
+
return (
|
|
22
|
+
<Collapsible
|
|
23
|
+
defaultOpen={defaultOpen}
|
|
24
|
+
className={cn("w-full space-y-2", className)}
|
|
25
|
+
>
|
|
26
|
+
<CollapsibleTrigger asChild>
|
|
27
|
+
<div className="flex items-center justify-between space-x-4 px-4 py-2 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition-colors">
|
|
28
|
+
{trigger.map((child) => (
|
|
29
|
+
<React.Fragment key={child.id}>
|
|
30
|
+
{renderComponent(child)}
|
|
31
|
+
</React.Fragment>
|
|
32
|
+
))}
|
|
33
|
+
</div>
|
|
34
|
+
</CollapsibleTrigger>
|
|
35
|
+
<CollapsibleContent className="space-y-2">
|
|
36
|
+
{content.map((child) => (
|
|
37
|
+
<React.Fragment key={child.id}>
|
|
38
|
+
{renderComponent(child)}
|
|
39
|
+
</React.Fragment>
|
|
40
|
+
))}
|
|
41
|
+
</CollapsibleContent>
|
|
42
|
+
</Collapsible>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Command,
|
|
4
|
+
CommandEmpty,
|
|
5
|
+
CommandGroup,
|
|
6
|
+
CommandInput,
|
|
7
|
+
CommandItem,
|
|
8
|
+
CommandList,
|
|
9
|
+
CommandSeparator,
|
|
10
|
+
} from "@/components/ui/command";
|
|
11
|
+
import { CommandAtomType } from "../types/schema";
|
|
12
|
+
import { cn } from "@/lib/utils";
|
|
13
|
+
|
|
14
|
+
export const CommandAtom: React.FC<CommandAtomType> = ({
|
|
15
|
+
placeholder = "Search...",
|
|
16
|
+
groups,
|
|
17
|
+
className,
|
|
18
|
+
}) => {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
className={cn(
|
|
22
|
+
"rounded-2xl border border-gray-100 shadow-lg overflow-hidden bg-white max-w-[400px]",
|
|
23
|
+
className,
|
|
24
|
+
)}
|
|
25
|
+
>
|
|
26
|
+
<Command>
|
|
27
|
+
<CommandInput placeholder={placeholder} />
|
|
28
|
+
<CommandList>
|
|
29
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
30
|
+
{groups.map((group, i) => (
|
|
31
|
+
<React.Fragment key={i}>
|
|
32
|
+
<CommandGroup heading={group.heading}>
|
|
33
|
+
{group.items.map((item, j) => (
|
|
34
|
+
<CommandItem key={j} value={item.value}>
|
|
35
|
+
<span>{item.label}</span>
|
|
36
|
+
</CommandItem>
|
|
37
|
+
))}
|
|
38
|
+
</CommandGroup>
|
|
39
|
+
{i < groups.length - 1 && <CommandSeparator />}
|
|
40
|
+
</React.Fragment>
|
|
41
|
+
))}
|
|
42
|
+
</CommandList>
|
|
43
|
+
</Command>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
};
|