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.
Files changed (2) hide show
  1. package/create-ui-lib.js +550 -27
  2. 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"><p className="mt-2 text-sm">Welcome to the BDPA React Scaffold and Demo.</p></TabsContent>
786
- <TabsContent value="components"><p className="mt-2 text-sm">Buttons, Cards, Inputs, Tables, and more.</p></TabsContent>
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
- <Button>Primary</Button>
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 &amp; 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 &amp; 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 &amp; 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
- alert("Login submitted!");
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
- alert("Registration submitted!");
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
- <CardTitle>Sign In</CardTitle>
951
- </CardHeader>
952
- <CardContent className="space-y-4">
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
- <div className="space-y-1">
958
- <Label htmlFor="password">Password</Label>
959
- <Input id="password" type="password" placeholder="••••••••" />
960
- </div>
961
- <Button className="w-full" onClick={onSubmit}>
962
- Sign In
963
- </Button>
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
- Dont have an account?{" "}
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
- <CardTitle>Create Account</CardTitle>
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 className="space-y-4">
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
- <Button className="w-full" onClick={onSubmit}>
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 &amp; 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">&larr; 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": "1.9.0",
4
- "description": "Scaffold a React + Tailwind UI library demo via Vite.",
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
  },