pxengine 0.1.12 → 0.1.13
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/registry.json +1 -1
- 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,41 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { ContentPreviewGalleryMolecule } from "../../../types/molecules";
|
|
3
|
-
import { cn } from "@/lib/utils";
|
|
4
|
-
import { Play } from "lucide-react";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* ContentPreviewGallery
|
|
8
|
-
* Grid/Gallery of thumbnail previews.
|
|
9
|
-
*/
|
|
10
|
-
export const ContentPreviewGallery: React.FC<ContentPreviewGalleryMolecule> = ({
|
|
11
|
-
items,
|
|
12
|
-
className,
|
|
13
|
-
}) => {
|
|
14
|
-
return (
|
|
15
|
-
<div className={cn("grid grid-cols-2 gap-2", className)}>
|
|
16
|
-
{items.map((item, i) => (
|
|
17
|
-
<a
|
|
18
|
-
key={i}
|
|
19
|
-
href={item.url || "#"}
|
|
20
|
-
target="_blank"
|
|
21
|
-
rel="noopener noreferrer"
|
|
22
|
-
className="group relative aspect-square overflow-hidden rounded-2xl bg-gray-100"
|
|
23
|
-
>
|
|
24
|
-
<img
|
|
25
|
-
src={item.thumbnail}
|
|
26
|
-
alt="Content preview"
|
|
27
|
-
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-110"
|
|
28
|
-
/>
|
|
29
|
-
{item.type === "video" && (
|
|
30
|
-
<div className="absolute inset-0 flex items-center justify-center bg-black/10 group-hover:bg-black/20 transition-colors">
|
|
31
|
-
<div className="rounded-full bg-white/30 backdrop-blur-md p-3 text-white ring-1 ring-white/50">
|
|
32
|
-
<Play className="h-6 w-6 fill-white" />
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
)}
|
|
36
|
-
<div className="absolute inset-0 ring-1 ring-inset ring-black/10 rounded-2xl" />
|
|
37
|
-
</a>
|
|
38
|
-
))}
|
|
39
|
-
</div>
|
|
40
|
-
);
|
|
41
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./ContentPreviewGallery";
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Button } from "@/components/ui/button";
|
|
3
|
-
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|
4
|
-
import { CreatorActionHeaderMolecule } from "../../../types/molecules";
|
|
5
|
-
import { cn } from "@/lib/utils";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* CreatorActionHeader
|
|
9
|
-
* A premium header for profile views with banner and sticky actions.
|
|
10
|
-
*/
|
|
11
|
-
export const CreatorActionHeader: React.FC<CreatorActionHeaderMolecule> = ({
|
|
12
|
-
bannerSrc,
|
|
13
|
-
avatarSrc,
|
|
14
|
-
name,
|
|
15
|
-
handle,
|
|
16
|
-
actions,
|
|
17
|
-
className,
|
|
18
|
-
}) => {
|
|
19
|
-
return (
|
|
20
|
-
<div
|
|
21
|
-
className={cn(
|
|
22
|
-
"relative w-full rounded-[40px] overflow-hidden bg-white border border-purple-50 shadow-sm",
|
|
23
|
-
className,
|
|
24
|
-
)}
|
|
25
|
-
>
|
|
26
|
-
{/* Banner */}
|
|
27
|
-
<div className="h-48 w-full bg-gradient-to-r from-purple-100 to-indigo-100 relative">
|
|
28
|
-
{bannerSrc && (
|
|
29
|
-
<img
|
|
30
|
-
src={bannerSrc}
|
|
31
|
-
className="h-full w-full object-cover"
|
|
32
|
-
alt="Banner"
|
|
33
|
-
/>
|
|
34
|
-
)}
|
|
35
|
-
<div className="absolute inset-0 bg-black/5" />
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
{/* Profile Info & Actions */}
|
|
39
|
-
<div className="px-8 pb-8 flex flex-col md:flex-row md:items-end justify-between gap-6 -mt-12 relative z-10">
|
|
40
|
-
<div className="flex flex-col md:flex-row items-start md:items-end gap-6">
|
|
41
|
-
<div className="p-2 bg-white rounded-[32px] shadow-lg">
|
|
42
|
-
<Avatar className="h-32 w-32 rounded-[24px] border-4 border-white">
|
|
43
|
-
<AvatarImage src={avatarSrc} className="rounded-[24px]" />
|
|
44
|
-
<AvatarFallback className="rounded-[24px] bg-purple-50 text-purple-600 text-3xl font-bold">
|
|
45
|
-
{name.charAt(0)}
|
|
46
|
-
</AvatarFallback>
|
|
47
|
-
</Avatar>
|
|
48
|
-
</div>
|
|
49
|
-
<div className="mb-2">
|
|
50
|
-
<h1 className="text-3xl font-bold text-gray-900 tracking-tight">
|
|
51
|
-
{name}
|
|
52
|
-
</h1>
|
|
53
|
-
<p className="text-purple-600 font-medium tracking-wide">
|
|
54
|
-
@{handle}
|
|
55
|
-
</p>
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
|
|
59
|
-
<div className="flex items-center gap-3 mb-2">
|
|
60
|
-
{actions.map((action, i) => (
|
|
61
|
-
<Button
|
|
62
|
-
key={i}
|
|
63
|
-
variant={(action.variant as any) || "default"}
|
|
64
|
-
className={cn(
|
|
65
|
-
"rounded-2xl px-6 h-11 font-bold transition-all",
|
|
66
|
-
action.variant === "default" &&
|
|
67
|
-
"bg-purple-600 hover:bg-purple-700 shadow-md hover:shadow-purple-200",
|
|
68
|
-
)}
|
|
69
|
-
>
|
|
70
|
-
{action.label}
|
|
71
|
-
</Button>
|
|
72
|
-
))}
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
</div>
|
|
76
|
-
);
|
|
77
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./CreatorActionHeader";
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Card, CardContent } from "@/components/ui/card";
|
|
3
|
-
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|
4
|
-
import { CreatorGridCardMolecule } from "../../../types/molecules";
|
|
5
|
-
import { cn } from "@/lib/utils";
|
|
6
|
-
import { Instagram, Youtube, Video, Twitter } from "lucide-react";
|
|
7
|
-
|
|
8
|
-
const TikTokIcon = ({ className }: { className?: string }) => (
|
|
9
|
-
<Video className={className} /> // Placeholder
|
|
10
|
-
);
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* CreatorGridCard
|
|
14
|
-
* A visually rich card for discovery grids.
|
|
15
|
-
*/
|
|
16
|
-
export const CreatorGridCard: React.FC<CreatorGridCardMolecule> = ({
|
|
17
|
-
bannerSrc,
|
|
18
|
-
avatarSrc,
|
|
19
|
-
name,
|
|
20
|
-
handle,
|
|
21
|
-
metrics,
|
|
22
|
-
platforms,
|
|
23
|
-
className,
|
|
24
|
-
}) => {
|
|
25
|
-
const getIcon = (p: string) => {
|
|
26
|
-
switch (p.toLowerCase()) {
|
|
27
|
-
case "instagram":
|
|
28
|
-
return Instagram;
|
|
29
|
-
case "tiktok":
|
|
30
|
-
return TikTokIcon;
|
|
31
|
-
case "youtube":
|
|
32
|
-
return Youtube;
|
|
33
|
-
case "twitter":
|
|
34
|
-
return Twitter;
|
|
35
|
-
default:
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<Card
|
|
42
|
-
className={cn(
|
|
43
|
-
"group overflow-hidden rounded-[32px] border-none bg-white shadow-sm hover:shadow-xl transition-all duration-300",
|
|
44
|
-
className,
|
|
45
|
-
)}
|
|
46
|
-
>
|
|
47
|
-
<div className="relative h-32 w-full overflow-hidden">
|
|
48
|
-
{bannerSrc ? (
|
|
49
|
-
<img
|
|
50
|
-
src={bannerSrc}
|
|
51
|
-
alt={name}
|
|
52
|
-
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-110"
|
|
53
|
-
/>
|
|
54
|
-
) : (
|
|
55
|
-
<div className="h-full w-full bg-gradient-to-br from-purple-500 to-indigo-600" />
|
|
56
|
-
)}
|
|
57
|
-
<div className="absolute inset-x-0 bottom-0 h-1/2 bg-gradient-to-t from-black/20 to-transparent" />
|
|
58
|
-
</div>
|
|
59
|
-
|
|
60
|
-
<CardContent className="relative pt-0 px-5 pb-6">
|
|
61
|
-
<div className="absolute -top-10 left-5">
|
|
62
|
-
<Avatar className="h-20 w-20 border-4 border-white shadow-lg ring-2 ring-purple-100">
|
|
63
|
-
<AvatarImage src={avatarSrc} alt={name} />
|
|
64
|
-
<AvatarFallback className="bg-purple-50 text-purple-700 font-bold text-xl">
|
|
65
|
-
{name.charAt(0)}
|
|
66
|
-
</AvatarFallback>
|
|
67
|
-
</Avatar>
|
|
68
|
-
</div>
|
|
69
|
-
|
|
70
|
-
<div className="mt-12 flex flex-col gap-1">
|
|
71
|
-
<h3 className="text-xl font-bold text-gray-900 truncate">{name}</h3>
|
|
72
|
-
<p className="text-sm text-muted-foreground font-medium">@{handle}</p>
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
<div className="mt-4 flex gap-2">
|
|
76
|
-
{platforms.map((p) => {
|
|
77
|
-
const Icon = getIcon(p);
|
|
78
|
-
return Icon ? (
|
|
79
|
-
<div
|
|
80
|
-
key={p}
|
|
81
|
-
className="p-1.5 rounded-lg bg-gray-50 text-gray-600 hover:text-purple-600 hover:bg-purple-50 transition-colors"
|
|
82
|
-
>
|
|
83
|
-
<Icon className="h-4 w-4" />
|
|
84
|
-
</div>
|
|
85
|
-
) : null;
|
|
86
|
-
})}
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
<div className="mt-6 grid grid-cols-2 gap-4 border-t border-gray-50 pt-4">
|
|
90
|
-
{metrics.map((m, i) => (
|
|
91
|
-
<div key={i} className="flex flex-col">
|
|
92
|
-
<span className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">
|
|
93
|
-
{m.label}
|
|
94
|
-
</span>
|
|
95
|
-
<span className="text-sm font-bold text-purple-700">
|
|
96
|
-
{m.value}
|
|
97
|
-
</span>
|
|
98
|
-
</div>
|
|
99
|
-
))}
|
|
100
|
-
</div>
|
|
101
|
-
</CardContent>
|
|
102
|
-
</Card>
|
|
103
|
-
);
|
|
104
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./CreatorGridCard";
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { AvatarAtom } from "../../../atoms/AvatarAtom";
|
|
3
|
-
import { TextAtom } from "../../../atoms/TextAtom";
|
|
4
|
-
import { CreatorProfileSummaryMolecule } from "../../../types/molecules";
|
|
5
|
-
import { cn } from "@/lib/utils";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* CreatorProfileSummary
|
|
9
|
-
* A compact row showing avatar, name, and key metrics.
|
|
10
|
-
*/
|
|
11
|
-
export const CreatorProfileSummary: React.FC<CreatorProfileSummaryMolecule> = ({
|
|
12
|
-
avatarSrc,
|
|
13
|
-
name,
|
|
14
|
-
followerCount,
|
|
15
|
-
engagementRate,
|
|
16
|
-
className,
|
|
17
|
-
}) => {
|
|
18
|
-
return (
|
|
19
|
-
<div
|
|
20
|
-
className={cn(
|
|
21
|
-
"flex items-center gap-4 p-3 rounded-2xl bg-white/40 border border-purple-50 shadow-sm",
|
|
22
|
-
className,
|
|
23
|
-
)}
|
|
24
|
-
>
|
|
25
|
-
<AvatarAtom
|
|
26
|
-
id={`avatar-${name}`}
|
|
27
|
-
type="avatar"
|
|
28
|
-
src={avatarSrc}
|
|
29
|
-
fallback={name.charAt(0)}
|
|
30
|
-
className="w-12 h-12 ring-2 ring-purple-100"
|
|
31
|
-
/>
|
|
32
|
-
<div className="flex flex-col flex-1">
|
|
33
|
-
<TextAtom
|
|
34
|
-
id={`name-${name}`}
|
|
35
|
-
type="text"
|
|
36
|
-
content={name}
|
|
37
|
-
variant="h4"
|
|
38
|
-
className="text-gray-900 leading-tight"
|
|
39
|
-
/>
|
|
40
|
-
<div className="flex gap-3 mt-1">
|
|
41
|
-
{followerCount && (
|
|
42
|
-
<div className="flex flex-col">
|
|
43
|
-
<span className="text-[10px] uppercase tracking-wider text-muted-foreground font-bold">
|
|
44
|
-
Followers
|
|
45
|
-
</span>
|
|
46
|
-
<span className="text-xs font-semibold text-purple-700">
|
|
47
|
-
{followerCount}
|
|
48
|
-
</span>
|
|
49
|
-
</div>
|
|
50
|
-
)}
|
|
51
|
-
{engagementRate && (
|
|
52
|
-
<div className="flex flex-col border-l border-purple-100 pl-3">
|
|
53
|
-
<span className="text-[10px] uppercase tracking-wider text-muted-foreground font-bold">
|
|
54
|
-
Engagement
|
|
55
|
-
</span>
|
|
56
|
-
<span className="text-xs font-semibold text-indigo-600">
|
|
57
|
-
{engagementRate}
|
|
58
|
-
</span>
|
|
59
|
-
</div>
|
|
60
|
-
)}
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
);
|
|
65
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./CreatorProfileSummary";
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
|
3
|
-
import { ChartAtom } from "../../../atoms/ChartAtom";
|
|
4
|
-
import { GrowthChartCardMolecule } from "../../../types/molecules";
|
|
5
|
-
import { cn } from "@/lib/utils";
|
|
6
|
-
import { TrendingUp } from "lucide-react";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* GrowthChartCard
|
|
10
|
-
* Visualizes time-series growth data for follower and engagement metrics.
|
|
11
|
-
*/
|
|
12
|
-
export const GrowthChartCard: React.FC<GrowthChartCardMolecule> = ({
|
|
13
|
-
title,
|
|
14
|
-
data,
|
|
15
|
-
config,
|
|
16
|
-
metric,
|
|
17
|
-
period,
|
|
18
|
-
className,
|
|
19
|
-
}) => {
|
|
20
|
-
return (
|
|
21
|
-
<Card
|
|
22
|
-
className={cn(
|
|
23
|
-
"rounded-[32px] border-purple-50 shadow-sm overflow-hidden",
|
|
24
|
-
className,
|
|
25
|
-
)}
|
|
26
|
-
>
|
|
27
|
-
<CardHeader className="flex flex-row items-center justify-between pb-2 space-y-0">
|
|
28
|
-
<div>
|
|
29
|
-
<CardTitle className="text-lg font-bold text-gray-900">
|
|
30
|
-
{title}
|
|
31
|
-
</CardTitle>
|
|
32
|
-
<p className="text-xs text-muted-foreground">{period}</p>
|
|
33
|
-
</div>
|
|
34
|
-
<div className="bg-green-50 p-2 rounded-xl">
|
|
35
|
-
<TrendingUp className="w-4 h-4 text-green-600" />
|
|
36
|
-
</div>
|
|
37
|
-
</CardHeader>
|
|
38
|
-
<CardContent>
|
|
39
|
-
<div className="h-[200px] w-full mt-4">
|
|
40
|
-
<ChartAtom
|
|
41
|
-
type="chart"
|
|
42
|
-
id="growth-trend"
|
|
43
|
-
chartType="area"
|
|
44
|
-
data={data}
|
|
45
|
-
config={config}
|
|
46
|
-
XAxisKey="date"
|
|
47
|
-
showTooltip={true}
|
|
48
|
-
showLegend={false}
|
|
49
|
-
/>
|
|
50
|
-
</div>
|
|
51
|
-
<div className="mt-4 flex items-center justify-between">
|
|
52
|
-
<span className="text-sm font-medium text-gray-500">{metric}</span>
|
|
53
|
-
<span className="text-sm font-bold text-purple-600">+12.5%</span>
|
|
54
|
-
</div>
|
|
55
|
-
</CardContent>
|
|
56
|
-
</Card>
|
|
57
|
-
);
|
|
58
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./GrowthChartCard";
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { MCQCardProps } from "./MCQCard.types";
|
|
3
|
-
import {
|
|
4
|
-
Card,
|
|
5
|
-
CardContent,
|
|
6
|
-
CardHeader,
|
|
7
|
-
CardTitle,
|
|
8
|
-
CardFooter,
|
|
9
|
-
Badge,
|
|
10
|
-
} from "@/components";
|
|
11
|
-
import { ActionButton } from "../../generic/ActionButton";
|
|
12
|
-
import { cn } from "@/lib/utils";
|
|
13
|
-
import { CheckCircle2, Sparkles } from "lucide-react";
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* MCQCard
|
|
17
|
-
*
|
|
18
|
-
* A molecule for Multiple Choice Questions.
|
|
19
|
-
* Supports:
|
|
20
|
-
* - Recommended options with styling
|
|
21
|
-
* - Radio-style selection
|
|
22
|
-
* - Integrated ActionButton with countdown
|
|
23
|
-
* - Peer/Agent approval labels
|
|
24
|
-
* - Premium aesthetics
|
|
25
|
-
*/
|
|
26
|
-
export const MCQCard = React.memo<MCQCardProps>(
|
|
27
|
-
({
|
|
28
|
-
question,
|
|
29
|
-
options,
|
|
30
|
-
recommended,
|
|
31
|
-
selectedOption,
|
|
32
|
-
onSelect,
|
|
33
|
-
onProceed,
|
|
34
|
-
isLatestMessage = true,
|
|
35
|
-
countdown,
|
|
36
|
-
isPaused = false,
|
|
37
|
-
onPause,
|
|
38
|
-
isLoading = false,
|
|
39
|
-
className,
|
|
40
|
-
selectionStatus,
|
|
41
|
-
}) => {
|
|
42
|
-
const handleOptionClick = (key: string) => {
|
|
43
|
-
if (isLatestMessage && !isLoading) {
|
|
44
|
-
onSelect?.(key);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const handleProceed = () => {
|
|
49
|
-
if (selectedOption || recommended) {
|
|
50
|
-
onProceed?.(selectedOption || recommended || "");
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
return (
|
|
55
|
-
<Card
|
|
56
|
-
className={cn(
|
|
57
|
-
"w-full rounded-[24px] border border-gray200 bg-white shadow-sm overflow-hidden",
|
|
58
|
-
className,
|
|
59
|
-
)}
|
|
60
|
-
>
|
|
61
|
-
<CardHeader className="pb-2">
|
|
62
|
-
<CardTitle className="text-lg font-bold text-gray-900 tracking-tight leading-snug">
|
|
63
|
-
{question}
|
|
64
|
-
</CardTitle>
|
|
65
|
-
</CardHeader>
|
|
66
|
-
|
|
67
|
-
<CardContent className="space-y-3 pb-6">
|
|
68
|
-
{Object.entries(options).map(([key, label]) => {
|
|
69
|
-
const isSelected = selectedOption === key;
|
|
70
|
-
const isRecommended = key === recommended;
|
|
71
|
-
|
|
72
|
-
return (
|
|
73
|
-
<div
|
|
74
|
-
key={key}
|
|
75
|
-
onClick={() => handleOptionClick(key)}
|
|
76
|
-
className={cn(
|
|
77
|
-
"group relative flex items-start gap-4 p-4 rounded-2xl border transition-all duration-200 cursor-pointer",
|
|
78
|
-
isSelected
|
|
79
|
-
? "border-purple500 bg-purple50/30"
|
|
80
|
-
: "border-gray-100 bg-gray-50/30 hover:border-gray-300 hover:bg-gray-50",
|
|
81
|
-
isLoading && "opacity-50 cursor-not-allowed",
|
|
82
|
-
)}
|
|
83
|
-
>
|
|
84
|
-
{/* Radio Circle */}
|
|
85
|
-
<div
|
|
86
|
-
className={cn(
|
|
87
|
-
"mt-1 w-5 h-5 rounded-full border-2 flex items-center justify-center transition-colors",
|
|
88
|
-
isSelected
|
|
89
|
-
? "border-purple500 bg-purple500"
|
|
90
|
-
: "border-gray-300 bg-white group-hover:border-gray-400",
|
|
91
|
-
)}
|
|
92
|
-
>
|
|
93
|
-
{isSelected && (
|
|
94
|
-
<div className="w-1.5 h-1.5 rounded-full bg-white" />
|
|
95
|
-
)}
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
<div className="flex-1 space-y-1.5">
|
|
99
|
-
<div className="flex items-center gap-2 flex-wrap">
|
|
100
|
-
<span
|
|
101
|
-
className={cn(
|
|
102
|
-
"text-sm font-semibold transition-colors",
|
|
103
|
-
isSelected ? "text-purple900" : "text-gray700",
|
|
104
|
-
)}
|
|
105
|
-
>
|
|
106
|
-
{label}
|
|
107
|
-
</span>
|
|
108
|
-
|
|
109
|
-
{isRecommended && (
|
|
110
|
-
<Badge
|
|
111
|
-
variant="outline"
|
|
112
|
-
className="bg-green-50 text-green-700 border-green-100 flex items-center gap-1 text-[10px] py-0 h-5"
|
|
113
|
-
>
|
|
114
|
-
<Sparkles className="h-3 w-3" />
|
|
115
|
-
Recommended
|
|
116
|
-
</Badge>
|
|
117
|
-
)}
|
|
118
|
-
|
|
119
|
-
{isSelected && !isLatestMessage && (
|
|
120
|
-
<Badge
|
|
121
|
-
variant="outline"
|
|
122
|
-
className="bg-purple-50 text-purple-700 border-purple-100 text-[10px] py-0 h-5"
|
|
123
|
-
>
|
|
124
|
-
Selected
|
|
125
|
-
</Badge>
|
|
126
|
-
)}
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
);
|
|
131
|
-
})}
|
|
132
|
-
</CardContent>
|
|
133
|
-
|
|
134
|
-
<CardFooter className="flex flex-col gap-4 pt-0 border-t border-gray-100/50 bg-gray-50/30 p-6">
|
|
135
|
-
{isLatestMessage ? (
|
|
136
|
-
<div className="w-full flex justify-center">
|
|
137
|
-
<ActionButton
|
|
138
|
-
label={
|
|
139
|
-
selectedOption ? "Continue" : "Proceed with Recommendation"
|
|
140
|
-
}
|
|
141
|
-
countdown={countdown}
|
|
142
|
-
isPaused={isPaused}
|
|
143
|
-
onPause={onPause}
|
|
144
|
-
onProceed={handleProceed}
|
|
145
|
-
isLoading={isLoading}
|
|
146
|
-
disabled={!selectedOption && !recommended}
|
|
147
|
-
/>
|
|
148
|
-
</div>
|
|
149
|
-
) : (
|
|
150
|
-
<div className="w-full flex justify-end items-center gap-1.5 text-green-600 text-xs font-semibold">
|
|
151
|
-
<CheckCircle2 className="h-4 w-4" />
|
|
152
|
-
<span>
|
|
153
|
-
{selectionStatus === "agent"
|
|
154
|
-
? "Suggested by Agent, Approved by You"
|
|
155
|
-
: "Selected by You"}
|
|
156
|
-
</span>
|
|
157
|
-
</div>
|
|
158
|
-
)}
|
|
159
|
-
</CardFooter>
|
|
160
|
-
</Card>
|
|
161
|
-
);
|
|
162
|
-
},
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
MCQCard.displayName = "MCQCard";
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
export interface MCQOption {
|
|
2
|
-
key: string;
|
|
3
|
-
label: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export interface MCQCardProps {
|
|
7
|
-
/**
|
|
8
|
-
* The question being asked
|
|
9
|
-
*/
|
|
10
|
-
question: string;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The options to choose from
|
|
14
|
-
*/
|
|
15
|
-
options: Record<string, string>;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* The key of the recommended option
|
|
19
|
-
*/
|
|
20
|
-
recommended?: string;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* The currently selected option key
|
|
24
|
-
*/
|
|
25
|
-
selectedOption?: string;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Triggered when an option is selected
|
|
29
|
-
*/
|
|
30
|
-
onSelect?: (key: string) => void;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Triggered when the user clicks continue
|
|
34
|
-
*/
|
|
35
|
-
onProceed?: (key: string) => void;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Whether the message is the latest
|
|
39
|
-
*/
|
|
40
|
-
isLatestMessage?: boolean;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Countdown in seconds
|
|
44
|
-
*/
|
|
45
|
-
countdown?: number;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Whether the countdown is paused
|
|
49
|
-
*/
|
|
50
|
-
isPaused?: boolean;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Pause/Resume handler
|
|
54
|
-
*/
|
|
55
|
-
onPause?: () => void;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Loading state during submission
|
|
59
|
-
*/
|
|
60
|
-
isLoading?: boolean;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Custom className
|
|
64
|
-
*/
|
|
65
|
-
className?: string;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Who made the final selection (for historical view)
|
|
69
|
-
*/
|
|
70
|
-
selectionStatus?: "user" | "agent";
|
|
71
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { PlatformIconGroupMolecule } from "../../../types/molecules";
|
|
3
|
-
import { cn } from "@/lib/utils";
|
|
4
|
-
import { Instagram, Youtube, Twitter, Video } from "lucide-react";
|
|
5
|
-
|
|
6
|
-
const TikTokIcon = ({ className }: { className?: string }) => (
|
|
7
|
-
<Video className={className} /> // Placeholder for TikTok
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* PlatformIconGroup
|
|
12
|
-
* Displays a horizontal list of active social platform icons.
|
|
13
|
-
*/
|
|
14
|
-
export const PlatformIconGroup: React.FC<PlatformIconGroupMolecule> = ({
|
|
15
|
-
platforms,
|
|
16
|
-
className,
|
|
17
|
-
}) => {
|
|
18
|
-
const getIcon = (platform: string) => {
|
|
19
|
-
switch (platform) {
|
|
20
|
-
case "instagram":
|
|
21
|
-
return Instagram;
|
|
22
|
-
case "tiktok":
|
|
23
|
-
return TikTokIcon;
|
|
24
|
-
case "youtube":
|
|
25
|
-
return Youtube;
|
|
26
|
-
case "twitter":
|
|
27
|
-
return Twitter;
|
|
28
|
-
default:
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const getColors = (platform: string) => {
|
|
34
|
-
switch (platform) {
|
|
35
|
-
case "instagram":
|
|
36
|
-
return "text-pink-600 bg-pink-50 hover:bg-pink-100 border-pink-100";
|
|
37
|
-
case "tiktok":
|
|
38
|
-
return "text-zinc-900 bg-zinc-100 hover:bg-zinc-200 border-zinc-200";
|
|
39
|
-
case "youtube":
|
|
40
|
-
return "text-red-600 bg-red-50 hover:bg-red-100 border-red-100";
|
|
41
|
-
case "twitter":
|
|
42
|
-
return "text-sky-500 bg-sky-50 hover:bg-sky-100 border-sky-100";
|
|
43
|
-
default:
|
|
44
|
-
return "text-gray-500 bg-gray-50 border-gray-100";
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<div className={cn("flex gap-2", className)}>
|
|
50
|
-
{platforms.map((p, i) => {
|
|
51
|
-
const Icon = getIcon(p.platform);
|
|
52
|
-
if (!Icon) return null;
|
|
53
|
-
|
|
54
|
-
return (
|
|
55
|
-
<a
|
|
56
|
-
key={i}
|
|
57
|
-
href={p.url || "#"}
|
|
58
|
-
target="_blank"
|
|
59
|
-
rel="noopener noreferrer"
|
|
60
|
-
title={p.handle || p.platform}
|
|
61
|
-
className={cn(
|
|
62
|
-
"p-1.5 rounded-lg border transition-colors flex items-center justify-center",
|
|
63
|
-
getColors(p.platform),
|
|
64
|
-
)}
|
|
65
|
-
>
|
|
66
|
-
<Icon className="w-4 h-4" />
|
|
67
|
-
</a>
|
|
68
|
-
);
|
|
69
|
-
})}
|
|
70
|
-
</div>
|
|
71
|
-
);
|
|
72
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./PlatformIconGroup";
|