create-bdpa-react-scaffold 1.9.0 → 2.0.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/create-ui-lib.js +550 -27
- package/package.json +2 -2
package/create-ui-lib.js
CHANGED
|
@@ -679,11 +679,22 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
|
|
|
679
679
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
|
680
680
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
|
681
681
|
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
|
|
682
|
+
import { Badge } from "@/components/ui/badge";
|
|
683
|
+
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
|
|
684
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
685
|
+
import { Checkbox } from "@/components/ui/checkbox";
|
|
686
|
+
import { Progress } from "@/components/ui/progress";
|
|
687
|
+
import { Separator } from "@/components/ui/separator";
|
|
688
|
+
import { Switch } from "@/components/ui/switch";
|
|
689
|
+
import { Textarea } from "@/components/ui/textarea";
|
|
690
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
691
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
|
682
692
|
import { toast } from "sonner";
|
|
683
|
-
import { Menu } from "lucide-react";
|
|
693
|
+
import { Menu, Info, CheckCircle } from "lucide-react";
|
|
684
694
|
import { ApiClient } from "./utils/api.js";
|
|
685
695
|
import Login from "./pages/auth/Login.jsx";
|
|
686
696
|
import Register from "./pages/auth/Register.jsx";
|
|
697
|
+
import ComponentTest from "./pages/ComponentTest.jsx";
|
|
687
698
|
|
|
688
699
|
const enrollmentData = [
|
|
689
700
|
{ name: "Alex", course: "Web Design Fundamentals", status: "Enrolled" },
|
|
@@ -714,7 +725,8 @@ function Dashboard() {
|
|
|
714
725
|
const navLinks = [
|
|
715
726
|
{ label: "Home", href: "/" },
|
|
716
727
|
{ label: "Login", href: "/login" },
|
|
717
|
-
{ label: "Register", href: "/register" }
|
|
728
|
+
{ label: "Register", href: "/register" },
|
|
729
|
+
{ label: "Component Test", href: "/component-test" }
|
|
718
730
|
];
|
|
719
731
|
|
|
720
732
|
return (
|
|
@@ -782,8 +794,20 @@ function Dashboard() {
|
|
|
782
794
|
<TabsTrigger value="components">Components</TabsTrigger>
|
|
783
795
|
<TabsTrigger value="auth">Auth</TabsTrigger>
|
|
784
796
|
</TabsList>
|
|
785
|
-
<TabsContent value="overview"
|
|
786
|
-
|
|
797
|
+
<TabsContent value="overview">
|
|
798
|
+
<Alert className="mt-2">
|
|
799
|
+
<CheckCircle className="h-4 w-4" />
|
|
800
|
+
<AlertTitle>Welcome!</AlertTitle>
|
|
801
|
+
<AlertDescription>Welcome to the BDPA React Scaffold and Demo. shadcn/ui components are fully installed.</AlertDescription>
|
|
802
|
+
</Alert>
|
|
803
|
+
</TabsContent>
|
|
804
|
+
<TabsContent value="components">
|
|
805
|
+
<Alert className="mt-2" variant="default">
|
|
806
|
+
<Info className="h-4 w-4" />
|
|
807
|
+
<AlertTitle>Components</AlertTitle>
|
|
808
|
+
<AlertDescription>Buttons, Cards, Inputs, Tables, Badges, Selects, and more — all from shadcn/ui.</AlertDescription>
|
|
809
|
+
</Alert>
|
|
810
|
+
</TabsContent>
|
|
787
811
|
<TabsContent value="auth"><p className="mt-2 text-sm">Login + Registration pages included.</p></TabsContent>
|
|
788
812
|
</Tabs>
|
|
789
813
|
|
|
@@ -842,10 +866,85 @@ function Dashboard() {
|
|
|
842
866
|
<Card>
|
|
843
867
|
<CardHeader><CardTitle>Button Variants</CardTitle></CardHeader>
|
|
844
868
|
<CardContent className="flex flex-wrap gap-3">
|
|
845
|
-
<
|
|
869
|
+
<TooltipProvider>
|
|
870
|
+
<Tooltip>
|
|
871
|
+
<TooltipTrigger asChild><Button>Primary</Button></TooltipTrigger>
|
|
872
|
+
<TooltipContent>Primary action</TooltipContent>
|
|
873
|
+
</Tooltip>
|
|
874
|
+
</TooltipProvider>
|
|
846
875
|
<Button variant="secondary">Secondary</Button>
|
|
847
876
|
<Button variant="destructive">Danger</Button>
|
|
848
877
|
<Button variant="outline">Outline</Button>
|
|
878
|
+
<Button variant="ghost">Ghost</Button>
|
|
879
|
+
<Button variant="link">Link</Button>
|
|
880
|
+
</CardContent>
|
|
881
|
+
</Card>
|
|
882
|
+
|
|
883
|
+
<Separator />
|
|
884
|
+
|
|
885
|
+
{/* Badge demos */}
|
|
886
|
+
<Card>
|
|
887
|
+
<CardHeader><CardTitle>Badges</CardTitle></CardHeader>
|
|
888
|
+
<CardContent className="flex flex-wrap gap-2">
|
|
889
|
+
<Badge>Default</Badge>
|
|
890
|
+
<Badge variant="secondary">Secondary</Badge>
|
|
891
|
+
<Badge variant="destructive">Destructive</Badge>
|
|
892
|
+
<Badge variant="outline">Outline</Badge>
|
|
893
|
+
</CardContent>
|
|
894
|
+
</Card>
|
|
895
|
+
|
|
896
|
+
{/* Select + Checkbox + Switch + Textarea */}
|
|
897
|
+
<div className="grid md:grid-cols-2 gap-6">
|
|
898
|
+
<Card>
|
|
899
|
+
<CardHeader><CardTitle>Select & Switch</CardTitle></CardHeader>
|
|
900
|
+
<CardContent className="space-y-4">
|
|
901
|
+
<div className="space-y-1">
|
|
902
|
+
<Label>Course Level</Label>
|
|
903
|
+
<Select>
|
|
904
|
+
<SelectTrigger>
|
|
905
|
+
<SelectValue placeholder="Select level" />
|
|
906
|
+
</SelectTrigger>
|
|
907
|
+
<SelectContent>
|
|
908
|
+
<SelectItem value="beginner">Beginner</SelectItem>
|
|
909
|
+
<SelectItem value="intermediate">Intermediate</SelectItem>
|
|
910
|
+
<SelectItem value="advanced">Advanced</SelectItem>
|
|
911
|
+
</SelectContent>
|
|
912
|
+
</Select>
|
|
913
|
+
</div>
|
|
914
|
+
<div className="flex items-center gap-2">
|
|
915
|
+
<Checkbox id="terms" />
|
|
916
|
+
<Label htmlFor="terms">Accept terms & conditions</Label>
|
|
917
|
+
</div>
|
|
918
|
+
<div className="flex items-center gap-2">
|
|
919
|
+
<Switch id="notifications" />
|
|
920
|
+
<Label htmlFor="notifications">Enable notifications</Label>
|
|
921
|
+
</div>
|
|
922
|
+
</CardContent>
|
|
923
|
+
</Card>
|
|
924
|
+
|
|
925
|
+
<Card>
|
|
926
|
+
<CardHeader><CardTitle>Textarea & Progress</CardTitle></CardHeader>
|
|
927
|
+
<CardContent className="space-y-4">
|
|
928
|
+
<div className="space-y-1">
|
|
929
|
+
<Label htmlFor="bio">Bio</Label>
|
|
930
|
+
<Textarea id="bio" placeholder="Tell us about yourself..." />
|
|
931
|
+
</div>
|
|
932
|
+
<div className="space-y-1">
|
|
933
|
+
<Label>Profile Completion</Label>
|
|
934
|
+
<Progress value={65} className="h-2" />
|
|
935
|
+
<p className="text-xs text-muted-foreground">65% complete</p>
|
|
936
|
+
</div>
|
|
937
|
+
</CardContent>
|
|
938
|
+
</Card>
|
|
939
|
+
</div>
|
|
940
|
+
|
|
941
|
+
{/* Skeleton loading demo */}
|
|
942
|
+
<Card>
|
|
943
|
+
<CardHeader><CardTitle>Skeleton Loading State</CardTitle></CardHeader>
|
|
944
|
+
<CardContent className="space-y-2">
|
|
945
|
+
<Skeleton className="h-4 w-full" />
|
|
946
|
+
<Skeleton className="h-4 w-3/4" />
|
|
947
|
+
<Skeleton className="h-4 w-1/2" />
|
|
849
948
|
</CardContent>
|
|
850
949
|
</Card>
|
|
851
950
|
|
|
@@ -906,7 +1005,7 @@ export default function App() {
|
|
|
906
1005
|
element={
|
|
907
1006
|
<Login
|
|
908
1007
|
onSubmit={() => {
|
|
909
|
-
|
|
1008
|
+
toast.success("Login submitted!");
|
|
910
1009
|
navigate("/");
|
|
911
1010
|
}}
|
|
912
1011
|
/>
|
|
@@ -917,12 +1016,13 @@ export default function App() {
|
|
|
917
1016
|
element={
|
|
918
1017
|
<Register
|
|
919
1018
|
onSubmit={() => {
|
|
920
|
-
|
|
1019
|
+
toast.success("Registration submitted!");
|
|
921
1020
|
navigate("/");
|
|
922
1021
|
}}
|
|
923
1022
|
/>
|
|
924
1023
|
}
|
|
925
1024
|
/>
|
|
1025
|
+
<Route path="/component-test" element={<ComponentTest />} />
|
|
926
1026
|
</Routes>
|
|
927
1027
|
);
|
|
928
1028
|
}
|
|
@@ -937,32 +1037,83 @@ export default function App() {
|
|
|
937
1037
|
// -------------------------------
|
|
938
1038
|
|
|
939
1039
|
write("src/pages/auth/Login.jsx", `
|
|
1040
|
+
import { useState } from "react";
|
|
940
1041
|
import { Button } from "@/components/ui/button";
|
|
941
1042
|
import { Input } from "@/components/ui/input";
|
|
942
1043
|
import { Label } from "@/components/ui/label";
|
|
943
1044
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
1045
|
+
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
1046
|
+
import { Checkbox } from "@/components/ui/checkbox";
|
|
1047
|
+
import { Separator } from "@/components/ui/separator";
|
|
1048
|
+
import { Badge } from "@/components/ui/badge";
|
|
944
1049
|
|
|
945
1050
|
export default function Login({ onSubmit }) {
|
|
1051
|
+
const [email, setEmail] = useState("");
|
|
1052
|
+
const [password, setPassword] = useState("");
|
|
1053
|
+
const [error, setError] = useState("");
|
|
1054
|
+
const [rememberMe, setRememberMe] = useState(false);
|
|
1055
|
+
|
|
1056
|
+
const handleSubmit = (e) => {
|
|
1057
|
+
e.preventDefault();
|
|
1058
|
+
if (!email || !password) {
|
|
1059
|
+
setError("Email and password are required.");
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
setError("");
|
|
1063
|
+
if (onSubmit) onSubmit({ email, password, rememberMe });
|
|
1064
|
+
};
|
|
1065
|
+
|
|
946
1066
|
return (
|
|
947
1067
|
<div className="flex items-center justify-center min-h-screen bg-gray-100">
|
|
948
1068
|
<Card className="w-full max-w-sm">
|
|
949
1069
|
<CardHeader>
|
|
950
|
-
<
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
<div className="space-y-1">
|
|
954
|
-
<Label htmlFor="email">Email</Label>
|
|
955
|
-
<Input id="email" type="email" placeholder="you@example.com" />
|
|
1070
|
+
<div className="flex items-center justify-between">
|
|
1071
|
+
<CardTitle>Sign In</CardTitle>
|
|
1072
|
+
<Badge variant="outline">shadcn/ui</Badge>
|
|
956
1073
|
</div>
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
1074
|
+
</CardHeader>
|
|
1075
|
+
<CardContent>
|
|
1076
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
1077
|
+
{error && (
|
|
1078
|
+
<Alert variant="destructive">
|
|
1079
|
+
<AlertDescription>{error}</AlertDescription>
|
|
1080
|
+
</Alert>
|
|
1081
|
+
)}
|
|
1082
|
+
<div className="space-y-1">
|
|
1083
|
+
<Label htmlFor="email">Email</Label>
|
|
1084
|
+
<Input
|
|
1085
|
+
id="email"
|
|
1086
|
+
type="email"
|
|
1087
|
+
placeholder="you@example.com"
|
|
1088
|
+
value={email}
|
|
1089
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
1090
|
+
/>
|
|
1091
|
+
</div>
|
|
1092
|
+
<div className="space-y-1">
|
|
1093
|
+
<Label htmlFor="password">Password</Label>
|
|
1094
|
+
<Input
|
|
1095
|
+
id="password"
|
|
1096
|
+
type="password"
|
|
1097
|
+
placeholder="Password"
|
|
1098
|
+
value={password}
|
|
1099
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
1100
|
+
/>
|
|
1101
|
+
</div>
|
|
1102
|
+
<div className="flex items-center gap-2">
|
|
1103
|
+
<Checkbox
|
|
1104
|
+
id="remember"
|
|
1105
|
+
checked={rememberMe}
|
|
1106
|
+
onCheckedChange={setRememberMe}
|
|
1107
|
+
/>
|
|
1108
|
+
<Label htmlFor="remember" className="text-sm">Remember me</Label>
|
|
1109
|
+
</div>
|
|
1110
|
+
<Button type="submit" className="w-full">
|
|
1111
|
+
Sign In
|
|
1112
|
+
</Button>
|
|
1113
|
+
</form>
|
|
1114
|
+
<Separator className="my-4" />
|
|
964
1115
|
<p className="text-sm text-center text-gray-600">
|
|
965
|
-
Don
|
|
1116
|
+
Don't have an account?{" "}
|
|
966
1117
|
<a href="/register" className="text-blue-600 hover:underline">
|
|
967
1118
|
Create one
|
|
968
1119
|
</a>
|
|
@@ -973,35 +1124,109 @@ export default function Login({ onSubmit }) {
|
|
|
973
1124
|
);
|
|
974
1125
|
}`);
|
|
975
1126
|
|
|
1127
|
+
|
|
976
1128
|
write("src/pages/auth/Register.jsx", `
|
|
1129
|
+
import { useState } from "react";
|
|
977
1130
|
import { Button } from "@/components/ui/button";
|
|
978
1131
|
import { Input } from "@/components/ui/input";
|
|
979
1132
|
import { Label } from "@/components/ui/label";
|
|
980
1133
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
1134
|
+
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
1135
|
+
import { Progress } from "@/components/ui/progress";
|
|
1136
|
+
import { Separator } from "@/components/ui/separator";
|
|
1137
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
1138
|
+
import { Badge } from "@/components/ui/badge";
|
|
1139
|
+
|
|
1140
|
+
function calcStrength(pw) {
|
|
1141
|
+
let s = 0;
|
|
1142
|
+
if (pw.length >= 8) s++;
|
|
1143
|
+
if (pw.length >= 12) s++;
|
|
1144
|
+
if (/[a-z]/.test(pw) && /[A-Z]/.test(pw)) s++;
|
|
1145
|
+
if (/\\d/.test(pw)) s++;
|
|
1146
|
+
if (/[^A-Za-z0-9]/.test(pw)) s++;
|
|
1147
|
+
return Math.min(s, 4);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
const strengthLabels = ["Weak", "Fair", "Good", "Strong", "Very Strong"];
|
|
1151
|
+
const strengthColors = ["bg-red-500", "bg-orange-400", "bg-yellow-400", "bg-green-400", "bg-green-600"];
|
|
981
1152
|
|
|
982
1153
|
export default function Register({ onSubmit }) {
|
|
1154
|
+
const [name, setName] = useState("");
|
|
1155
|
+
const [email, setEmail] = useState("");
|
|
1156
|
+
const [password, setPassword] = useState("");
|
|
1157
|
+
const [role, setRole] = useState("");
|
|
1158
|
+
const [error, setError] = useState("");
|
|
1159
|
+
const strength = calcStrength(password);
|
|
1160
|
+
|
|
1161
|
+
const handleSubmit = (e) => {
|
|
1162
|
+
e.preventDefault();
|
|
1163
|
+
if (!name || !email || !password) {
|
|
1164
|
+
setError("All fields are required.");
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
if (password.length < 8) {
|
|
1168
|
+
setError("Password must be at least 8 characters.");
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
setError("");
|
|
1172
|
+
if (onSubmit) onSubmit({ name, email, password, role });
|
|
1173
|
+
};
|
|
1174
|
+
|
|
983
1175
|
return (
|
|
984
1176
|
<div className="flex items-center justify-center min-h-screen bg-gray-100">
|
|
985
1177
|
<Card className="w-full max-w-sm">
|
|
986
1178
|
<CardHeader>
|
|
987
|
-
<
|
|
1179
|
+
<div className="flex items-center justify-between">
|
|
1180
|
+
<CardTitle>Create Account</CardTitle>
|
|
1181
|
+
<Badge variant="outline">shadcn/ui</Badge>
|
|
1182
|
+
</div>
|
|
988
1183
|
</CardHeader>
|
|
989
|
-
<CardContent
|
|
1184
|
+
<CardContent>
|
|
1185
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
1186
|
+
{error && (
|
|
1187
|
+
<Alert variant="destructive">
|
|
1188
|
+
<AlertDescription>{error}</AlertDescription>
|
|
1189
|
+
</Alert>
|
|
1190
|
+
)}
|
|
990
1191
|
<div className="space-y-1">
|
|
991
1192
|
<Label htmlFor="name">Full Name</Label>
|
|
992
|
-
<Input id="name" placeholder="Your Name" />
|
|
1193
|
+
<Input id="name" placeholder="Your Name" value={name} onChange={(e) => setName(e.target.value)} />
|
|
993
1194
|
</div>
|
|
994
1195
|
<div className="space-y-1">
|
|
995
1196
|
<Label htmlFor="email">Email</Label>
|
|
996
|
-
<Input id="email" type="email" placeholder="you@example.com" />
|
|
1197
|
+
<Input id="email" type="email" placeholder="you@example.com" value={email} onChange={(e) => setEmail(e.target.value)} />
|
|
1198
|
+
</div>
|
|
1199
|
+
<div className="space-y-1">
|
|
1200
|
+
<Label htmlFor="r-role">Role</Label>
|
|
1201
|
+
<Select onValueChange={setRole}>
|
|
1202
|
+
<SelectTrigger id="r-role">
|
|
1203
|
+
<SelectValue placeholder="Select your role" />
|
|
1204
|
+
</SelectTrigger>
|
|
1205
|
+
<SelectContent>
|
|
1206
|
+
<SelectItem value="student">Student</SelectItem>
|
|
1207
|
+
<SelectItem value="mentor">Mentor</SelectItem>
|
|
1208
|
+
<SelectItem value="admin">Admin</SelectItem>
|
|
1209
|
+
</SelectContent>
|
|
1210
|
+
</Select>
|
|
997
1211
|
</div>
|
|
998
1212
|
<div className="space-y-1">
|
|
999
1213
|
<Label htmlFor="password">Password</Label>
|
|
1000
|
-
<Input id="password" type="password" placeholder="••••••••" />
|
|
1214
|
+
<Input id="password" type="password" placeholder="••••••••" value={password} onChange={(e) => setPassword(e.target.value)} />
|
|
1001
1215
|
</div>
|
|
1002
|
-
|
|
1216
|
+
{password && (
|
|
1217
|
+
<div className="space-y-1">
|
|
1218
|
+
<Progress value={(strength / 4) * 100} className="h-2" />
|
|
1219
|
+
<p className="text-xs text-muted-foreground">
|
|
1220
|
+
Strength: <span className="font-medium">{strengthLabels[strength]}</span>
|
|
1221
|
+
</p>
|
|
1222
|
+
</div>
|
|
1223
|
+
)}
|
|
1224
|
+
</div>
|
|
1225
|
+
<Button type="submit" className="w-full">
|
|
1003
1226
|
Register
|
|
1004
1227
|
</Button>
|
|
1228
|
+
</form>
|
|
1229
|
+
<Separator className="my-4" />
|
|
1005
1230
|
<p className="text-sm text-center text-gray-600">
|
|
1006
1231
|
Already have an account?{" "}
|
|
1007
1232
|
<a href="/login" className="text-blue-600 hover:underline">
|
|
@@ -1015,6 +1240,304 @@ export default function Register({ onSubmit }) {
|
|
|
1015
1240
|
}
|
|
1016
1241
|
`);
|
|
1017
1242
|
|
|
1243
|
+
// -------------------------------
|
|
1244
|
+
// ComponentTest page — comprehensive shadcn test
|
|
1245
|
+
// -------------------------------
|
|
1246
|
+
|
|
1247
|
+
write("src/pages/ComponentTest.jsx", `
|
|
1248
|
+
import { useState } from "react";
|
|
1249
|
+
import { Button } from "@/components/ui/button";
|
|
1250
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
1251
|
+
import { Input } from "@/components/ui/input";
|
|
1252
|
+
import { Label } from "@/components/ui/label";
|
|
1253
|
+
import { Badge } from "@/components/ui/badge";
|
|
1254
|
+
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
|
|
1255
|
+
import { Checkbox } from "@/components/ui/checkbox";
|
|
1256
|
+
import { Switch } from "@/components/ui/switch";
|
|
1257
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
1258
|
+
import { Progress } from "@/components/ui/progress";
|
|
1259
|
+
import { Separator } from "@/components/ui/separator";
|
|
1260
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
1261
|
+
import { Textarea } from "@/components/ui/textarea";
|
|
1262
|
+
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
|
|
1263
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
|
1264
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
|
|
1265
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
|
1266
|
+
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
|
|
1267
|
+
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|
1268
|
+
import { toast } from "sonner";
|
|
1269
|
+
import { CheckCircle, Info, AlertCircle } from "lucide-react";
|
|
1270
|
+
|
|
1271
|
+
const sampleRows = [
|
|
1272
|
+
{ id: 1, name: "Ada Lovelace", role: "Student", status: "Active" },
|
|
1273
|
+
{ id: 2, name: "Grace Hopper", role: "Mentor", status: "Active" },
|
|
1274
|
+
{ id: 3, name: "Alan Turing", role: "Admin", status: "Inactive" },
|
|
1275
|
+
];
|
|
1276
|
+
|
|
1277
|
+
export default function ComponentTest() {
|
|
1278
|
+
const [dialogOpen, setDialogOpen] = useState(false);
|
|
1279
|
+
const [progress, setProgress] = useState(40);
|
|
1280
|
+
const [switchOn, setSwitchOn] = useState(false);
|
|
1281
|
+
const [checked, setChecked] = useState(false);
|
|
1282
|
+
|
|
1283
|
+
return (
|
|
1284
|
+
<div className="p-6 max-w-4xl mx-auto space-y-8">
|
|
1285
|
+
<div className="flex items-center justify-between">
|
|
1286
|
+
<h1 className="text-3xl font-bold">shadcn/ui Component Test</h1>
|
|
1287
|
+
<Badge>All Components</Badge>
|
|
1288
|
+
</div>
|
|
1289
|
+
|
|
1290
|
+
<Separator />
|
|
1291
|
+
|
|
1292
|
+
{/* Alerts */}
|
|
1293
|
+
<Card>
|
|
1294
|
+
<CardHeader><CardTitle>Alert</CardTitle></CardHeader>
|
|
1295
|
+
<CardContent className="space-y-3">
|
|
1296
|
+
<Alert>
|
|
1297
|
+
<Info className="h-4 w-4" />
|
|
1298
|
+
<AlertTitle>Info</AlertTitle>
|
|
1299
|
+
<AlertDescription>This is a default informational alert.</AlertDescription>
|
|
1300
|
+
</Alert>
|
|
1301
|
+
<Alert variant="destructive">
|
|
1302
|
+
<AlertCircle className="h-4 w-4" />
|
|
1303
|
+
<AlertTitle>Error</AlertTitle>
|
|
1304
|
+
<AlertDescription>Something went wrong. Please try again.</AlertDescription>
|
|
1305
|
+
</Alert>
|
|
1306
|
+
</CardContent>
|
|
1307
|
+
</Card>
|
|
1308
|
+
|
|
1309
|
+
{/* Avatar */}
|
|
1310
|
+
<Card>
|
|
1311
|
+
<CardHeader><CardTitle>Avatar</CardTitle></CardHeader>
|
|
1312
|
+
<CardContent className="flex gap-4">
|
|
1313
|
+
<Avatar>
|
|
1314
|
+
<AvatarImage src="https://github.com/shadcn.png" alt="shadcn" />
|
|
1315
|
+
<AvatarFallback>CN</AvatarFallback>
|
|
1316
|
+
</Avatar>
|
|
1317
|
+
<Avatar>
|
|
1318
|
+
<AvatarFallback>AL</AvatarFallback>
|
|
1319
|
+
</Avatar>
|
|
1320
|
+
<Avatar>
|
|
1321
|
+
<AvatarFallback>GH</AvatarFallback>
|
|
1322
|
+
</Avatar>
|
|
1323
|
+
</CardContent>
|
|
1324
|
+
</Card>
|
|
1325
|
+
|
|
1326
|
+
{/* Badge */}
|
|
1327
|
+
<Card>
|
|
1328
|
+
<CardHeader><CardTitle>Badge</CardTitle></CardHeader>
|
|
1329
|
+
<CardContent className="flex flex-wrap gap-2">
|
|
1330
|
+
<Badge>Default</Badge>
|
|
1331
|
+
<Badge variant="secondary">Secondary</Badge>
|
|
1332
|
+
<Badge variant="destructive">Destructive</Badge>
|
|
1333
|
+
<Badge variant="outline">Outline</Badge>
|
|
1334
|
+
</CardContent>
|
|
1335
|
+
</Card>
|
|
1336
|
+
|
|
1337
|
+
{/* Button */}
|
|
1338
|
+
<Card>
|
|
1339
|
+
<CardHeader><CardTitle>Button</CardTitle></CardHeader>
|
|
1340
|
+
<CardContent className="flex flex-wrap gap-2">
|
|
1341
|
+
<Button onClick={() => toast.success("Primary clicked!")}>Primary</Button>
|
|
1342
|
+
<Button variant="secondary">Secondary</Button>
|
|
1343
|
+
<Button variant="destructive">Destructive</Button>
|
|
1344
|
+
<Button variant="outline">Outline</Button>
|
|
1345
|
+
<Button variant="ghost">Ghost</Button>
|
|
1346
|
+
<Button variant="link">Link</Button>
|
|
1347
|
+
<Button disabled>Disabled</Button>
|
|
1348
|
+
<Button size="sm">Small</Button>
|
|
1349
|
+
<Button size="lg">Large</Button>
|
|
1350
|
+
</CardContent>
|
|
1351
|
+
</Card>
|
|
1352
|
+
|
|
1353
|
+
{/* Checkbox + Switch */}
|
|
1354
|
+
<Card>
|
|
1355
|
+
<CardHeader><CardTitle>Checkbox & Switch</CardTitle></CardHeader>
|
|
1356
|
+
<CardContent className="space-y-3">
|
|
1357
|
+
<div className="flex items-center gap-2">
|
|
1358
|
+
<Checkbox id="test-cb" checked={checked} onCheckedChange={setChecked} />
|
|
1359
|
+
<Label htmlFor="test-cb">Accept terms: {checked ? "Yes" : "No"}</Label>
|
|
1360
|
+
</div>
|
|
1361
|
+
<div className="flex items-center gap-2">
|
|
1362
|
+
<Switch id="test-sw" checked={switchOn} onCheckedChange={setSwitchOn} />
|
|
1363
|
+
<Label htmlFor="test-sw">Notifications: {switchOn ? "On" : "Off"}</Label>
|
|
1364
|
+
</div>
|
|
1365
|
+
</CardContent>
|
|
1366
|
+
</Card>
|
|
1367
|
+
|
|
1368
|
+
{/* Input + Textarea + Select + Label */}
|
|
1369
|
+
<Card>
|
|
1370
|
+
<CardHeader><CardTitle>Input / Textarea / Select</CardTitle></CardHeader>
|
|
1371
|
+
<CardContent className="space-y-4">
|
|
1372
|
+
<div className="space-y-1">
|
|
1373
|
+
<Label htmlFor="ct-name">Name</Label>
|
|
1374
|
+
<Input id="ct-name" placeholder="Enter your name" />
|
|
1375
|
+
</div>
|
|
1376
|
+
<div className="space-y-1">
|
|
1377
|
+
<Label htmlFor="ct-bio">Bio</Label>
|
|
1378
|
+
<Textarea id="ct-bio" placeholder="Tell us about yourself" />
|
|
1379
|
+
</div>
|
|
1380
|
+
<div className="space-y-1">
|
|
1381
|
+
<Label>Role</Label>
|
|
1382
|
+
<Select>
|
|
1383
|
+
<SelectTrigger>
|
|
1384
|
+
<SelectValue placeholder="Choose a role" />
|
|
1385
|
+
</SelectTrigger>
|
|
1386
|
+
<SelectContent>
|
|
1387
|
+
<SelectItem value="student">Student</SelectItem>
|
|
1388
|
+
<SelectItem value="mentor">Mentor</SelectItem>
|
|
1389
|
+
<SelectItem value="admin">Admin</SelectItem>
|
|
1390
|
+
</SelectContent>
|
|
1391
|
+
</Select>
|
|
1392
|
+
</div>
|
|
1393
|
+
</CardContent>
|
|
1394
|
+
</Card>
|
|
1395
|
+
|
|
1396
|
+
{/* Progress */}
|
|
1397
|
+
<Card>
|
|
1398
|
+
<CardHeader><CardTitle>Progress</CardTitle></CardHeader>
|
|
1399
|
+
<CardContent className="space-y-3">
|
|
1400
|
+
<Progress value={progress} />
|
|
1401
|
+
<div className="flex gap-2">
|
|
1402
|
+
<Button size="sm" onClick={() => setProgress(Math.max(0, progress - 10))}>-10</Button>
|
|
1403
|
+
<Button size="sm" onClick={() => setProgress(Math.min(100, progress + 10))}>+10</Button>
|
|
1404
|
+
<span className="text-sm self-center">{progress}%</span>
|
|
1405
|
+
</div>
|
|
1406
|
+
</CardContent>
|
|
1407
|
+
</Card>
|
|
1408
|
+
|
|
1409
|
+
{/* Skeleton */}
|
|
1410
|
+
<Card>
|
|
1411
|
+
<CardHeader><CardTitle>Skeleton</CardTitle></CardHeader>
|
|
1412
|
+
<CardContent className="space-y-2">
|
|
1413
|
+
<div className="flex items-center gap-3">
|
|
1414
|
+
<Skeleton className="h-10 w-10 rounded-full" />
|
|
1415
|
+
<div className="space-y-1 flex-1">
|
|
1416
|
+
<Skeleton className="h-4 w-full" />
|
|
1417
|
+
<Skeleton className="h-4 w-2/3" />
|
|
1418
|
+
</div>
|
|
1419
|
+
</div>
|
|
1420
|
+
</CardContent>
|
|
1421
|
+
</Card>
|
|
1422
|
+
|
|
1423
|
+
{/* Tabs */}
|
|
1424
|
+
<Card>
|
|
1425
|
+
<CardHeader><CardTitle>Tabs</CardTitle></CardHeader>
|
|
1426
|
+
<CardContent>
|
|
1427
|
+
<Tabs defaultValue="tab1">
|
|
1428
|
+
<TabsList>
|
|
1429
|
+
<TabsTrigger value="tab1">Tab One</TabsTrigger>
|
|
1430
|
+
<TabsTrigger value="tab2">Tab Two</TabsTrigger>
|
|
1431
|
+
<TabsTrigger value="tab3">Tab Three</TabsTrigger>
|
|
1432
|
+
</TabsList>
|
|
1433
|
+
<TabsContent value="tab1"><p className="mt-2 text-sm">Content for Tab One.</p></TabsContent>
|
|
1434
|
+
<TabsContent value="tab2"><p className="mt-2 text-sm">Content for Tab Two.</p></TabsContent>
|
|
1435
|
+
<TabsContent value="tab3"><p className="mt-2 text-sm">Content for Tab Three.</p></TabsContent>
|
|
1436
|
+
</Tabs>
|
|
1437
|
+
</CardContent>
|
|
1438
|
+
</Card>
|
|
1439
|
+
|
|
1440
|
+
{/* Table */}
|
|
1441
|
+
<Card>
|
|
1442
|
+
<CardHeader><CardTitle>Table</CardTitle></CardHeader>
|
|
1443
|
+
<CardContent>
|
|
1444
|
+
<Table>
|
|
1445
|
+
<TableHeader>
|
|
1446
|
+
<TableRow>
|
|
1447
|
+
<TableHead>#</TableHead>
|
|
1448
|
+
<TableHead>Name</TableHead>
|
|
1449
|
+
<TableHead>Role</TableHead>
|
|
1450
|
+
<TableHead>Status</TableHead>
|
|
1451
|
+
</TableRow>
|
|
1452
|
+
</TableHeader>
|
|
1453
|
+
<TableBody>
|
|
1454
|
+
{sampleRows.map((r) => (
|
|
1455
|
+
<TableRow key={r.id}>
|
|
1456
|
+
<TableCell>{r.id}</TableCell>
|
|
1457
|
+
<TableCell>{r.name}</TableCell>
|
|
1458
|
+
<TableCell>{r.role}</TableCell>
|
|
1459
|
+
<TableCell>
|
|
1460
|
+
<Badge variant={r.status === "Active" ? "default" : "secondary"}>{r.status}</Badge>
|
|
1461
|
+
</TableCell>
|
|
1462
|
+
</TableRow>
|
|
1463
|
+
))}
|
|
1464
|
+
</TableBody>
|
|
1465
|
+
</Table>
|
|
1466
|
+
</CardContent>
|
|
1467
|
+
</Card>
|
|
1468
|
+
|
|
1469
|
+
{/* Dialog */}
|
|
1470
|
+
<Card>
|
|
1471
|
+
<CardHeader><CardTitle>Dialog</CardTitle></CardHeader>
|
|
1472
|
+
<CardContent>
|
|
1473
|
+
<Button onClick={() => setDialogOpen(true)}>Open Dialog</Button>
|
|
1474
|
+
<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
|
|
1475
|
+
<DialogContent>
|
|
1476
|
+
<DialogHeader>
|
|
1477
|
+
<DialogTitle>shadcn Dialog</DialogTitle>
|
|
1478
|
+
<DialogDescription>This is a modal dialog from shadcn/ui.</DialogDescription>
|
|
1479
|
+
</DialogHeader>
|
|
1480
|
+
<p className="text-sm">Dialog content goes here.</p>
|
|
1481
|
+
<Button className="mt-4" onClick={() => setDialogOpen(false)}>Close</Button>
|
|
1482
|
+
</DialogContent>
|
|
1483
|
+
</Dialog>
|
|
1484
|
+
</CardContent>
|
|
1485
|
+
</Card>
|
|
1486
|
+
|
|
1487
|
+
{/* Sheet */}
|
|
1488
|
+
<Card>
|
|
1489
|
+
<CardHeader><CardTitle>Sheet</CardTitle></CardHeader>
|
|
1490
|
+
<CardContent>
|
|
1491
|
+
<Sheet>
|
|
1492
|
+
<SheetTrigger asChild>
|
|
1493
|
+
<Button variant="outline">Open Sheet</Button>
|
|
1494
|
+
</SheetTrigger>
|
|
1495
|
+
<SheetContent>
|
|
1496
|
+
<SheetHeader>
|
|
1497
|
+
<SheetTitle>Side Sheet</SheetTitle>
|
|
1498
|
+
</SheetHeader>
|
|
1499
|
+
<p className="mt-4 text-sm">Sheet content from shadcn/ui.</p>
|
|
1500
|
+
</SheetContent>
|
|
1501
|
+
</Sheet>
|
|
1502
|
+
</CardContent>
|
|
1503
|
+
</Card>
|
|
1504
|
+
|
|
1505
|
+
{/* Tooltip */}
|
|
1506
|
+
<Card>
|
|
1507
|
+
<CardHeader><CardTitle>Tooltip</CardTitle></CardHeader>
|
|
1508
|
+
<CardContent>
|
|
1509
|
+
<TooltipProvider>
|
|
1510
|
+
<Tooltip>
|
|
1511
|
+
<TooltipTrigger asChild>
|
|
1512
|
+
<Button variant="outline">Hover me</Button>
|
|
1513
|
+
</TooltipTrigger>
|
|
1514
|
+
<TooltipContent>
|
|
1515
|
+
<p>This is a shadcn Tooltip</p>
|
|
1516
|
+
</TooltipContent>
|
|
1517
|
+
</Tooltip>
|
|
1518
|
+
</TooltipProvider>
|
|
1519
|
+
</CardContent>
|
|
1520
|
+
</Card>
|
|
1521
|
+
|
|
1522
|
+
{/* Toast */}
|
|
1523
|
+
<Card>
|
|
1524
|
+
<CardHeader><CardTitle>Toast (Sonner)</CardTitle></CardHeader>
|
|
1525
|
+
<CardContent className="flex flex-wrap gap-2">
|
|
1526
|
+
<Button onClick={() => toast.success("Success toast!")}>Success</Button>
|
|
1527
|
+
<Button variant="destructive" onClick={() => toast.error("Error toast!")}>Error</Button>
|
|
1528
|
+
<Button variant="outline" onClick={() => toast.info("Info toast!")}>Info</Button>
|
|
1529
|
+
<Button variant="secondary" onClick={() => toast.warning("Warning toast!")}>Warning</Button>
|
|
1530
|
+
</CardContent>
|
|
1531
|
+
</Card>
|
|
1532
|
+
|
|
1533
|
+
<div className="flex justify-center pt-4">
|
|
1534
|
+
<a href="/" className="text-sm text-blue-600 hover:underline">← Back to Home</a>
|
|
1535
|
+
</div>
|
|
1536
|
+
</div>
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
`);
|
|
1540
|
+
|
|
1018
1541
|
// -------------------------------
|
|
1019
1542
|
// Layout Components
|
|
1020
1543
|
// -------------------------------
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-bdpa-react-scaffold",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Scaffold a React + Tailwind
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Scaffold a React + Tailwind + shadcn/ui component demo via Vite.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-bdpa-react-scaffold": "create-ui-lib.js"
|
|
7
7
|
},
|