create-bdpa-react-scaffold 2.0.0 → 2.0.3
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 +154 -71
- package/package.json +1 -1
package/create-ui-lib.js
CHANGED
|
@@ -168,7 +168,6 @@ write("package.json", `
|
|
|
168
168
|
"react": "^18.2.0",
|
|
169
169
|
"react-dom": "^18.2.0",
|
|
170
170
|
"react-router-dom": "^6.20.0",
|
|
171
|
-
"lucide-react": "^0.344.0",
|
|
172
171
|
"bcryptjs": "^2.4.3",
|
|
173
172
|
"class-variance-authority": "^0.7.0",
|
|
174
173
|
"clsx": "^2.1.0",
|
|
@@ -658,6 +657,7 @@ export function cn(...inputs) {
|
|
|
658
657
|
write("src/index.js", `
|
|
659
658
|
export { Button } from "./components/ui/button.jsx";
|
|
660
659
|
|
|
660
|
+
export { default as Home } from "./pages/Home.jsx";
|
|
661
661
|
export { default as Login } from "./pages/auth/Login.jsx";
|
|
662
662
|
export { default as Register } from "./pages/auth/Register.jsx";
|
|
663
663
|
|
|
@@ -669,8 +669,134 @@ export { hashPassword, verifyPassword, getPasswordStrength, getPasswordStrengthL
|
|
|
669
669
|
`);
|
|
670
670
|
|
|
671
671
|
write("src/App.jsx", `
|
|
672
|
-
import { useState } from "react";
|
|
673
672
|
import { Routes, Route, useNavigate } from "react-router-dom";
|
|
673
|
+
import { toast } from "sonner";
|
|
674
|
+
import Home from "./pages/Home.jsx";
|
|
675
|
+
import Login from "./pages/auth/Login.jsx";
|
|
676
|
+
import Register from "./pages/auth/Register.jsx";
|
|
677
|
+
import ComponentTest from "./pages/ComponentTest.jsx";
|
|
678
|
+
|
|
679
|
+
export default function App() {
|
|
680
|
+
const navigate = useNavigate();
|
|
681
|
+
|
|
682
|
+
return (
|
|
683
|
+
<Routes>
|
|
684
|
+
<Route path="/" element={<Home />} />
|
|
685
|
+
<Route
|
|
686
|
+
path="/login"
|
|
687
|
+
element={
|
|
688
|
+
<Login
|
|
689
|
+
onSubmit={() => {
|
|
690
|
+
toast.success("Login submitted!");
|
|
691
|
+
navigate("/");
|
|
692
|
+
}}
|
|
693
|
+
/>
|
|
694
|
+
}
|
|
695
|
+
/>
|
|
696
|
+
<Route
|
|
697
|
+
path="/register"
|
|
698
|
+
element={
|
|
699
|
+
<Register
|
|
700
|
+
onSubmit={() => {
|
|
701
|
+
toast.success("Registration submitted!");
|
|
702
|
+
navigate("/");
|
|
703
|
+
}}
|
|
704
|
+
/>
|
|
705
|
+
}
|
|
706
|
+
/>
|
|
707
|
+
<Route path="/component-test" element={<ComponentTest />} />
|
|
708
|
+
</Routes>
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
`);
|
|
712
|
+
|
|
713
|
+
write("src/components/ui/icons.jsx", `
|
|
714
|
+
// Local SVG icon module — inline icon components, no external icon library needed.
|
|
715
|
+
// All icons accept className and other SVG props.
|
|
716
|
+
|
|
717
|
+
function SvgIcon({ className = "h-4 w-4", children, ...props }) {
|
|
718
|
+
return (
|
|
719
|
+
<svg
|
|
720
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
721
|
+
viewBox="0 0 24 24"
|
|
722
|
+
fill="none"
|
|
723
|
+
stroke="currentColor"
|
|
724
|
+
strokeWidth="2"
|
|
725
|
+
strokeLinecap="round"
|
|
726
|
+
strokeLinejoin="round"
|
|
727
|
+
className={className}
|
|
728
|
+
{...props}
|
|
729
|
+
>
|
|
730
|
+
{children}
|
|
731
|
+
</svg>
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
export function Check({ className, ...p }) {
|
|
736
|
+
return <SvgIcon className={className} {...p}><path d="M20 6 9 17l-5-5" /></SvgIcon>;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
export function X({ className, ...p }) {
|
|
740
|
+
return <SvgIcon className={className} {...p}><path d="M18 6 6 18" /><path d="m6 6 12 12" /></SvgIcon>;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
export function Circle({ className, ...p }) {
|
|
744
|
+
return <SvgIcon className={className} {...p}><circle cx="12" cy="12" r="10" /></SvgIcon>;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
export function CheckCircle({ className, ...p }) {
|
|
748
|
+
return <SvgIcon className={className} {...p}><circle cx="12" cy="12" r="10" /><path d="m9 12 2 2 4-4" /></SvgIcon>;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
export function AlertCircle({ className, ...p }) {
|
|
752
|
+
return <SvgIcon className={className} {...p}><circle cx="12" cy="12" r="10" /><line x1="12" y1="8" x2="12" y2="12" /><line x1="12" y1="16" x2="12.01" y2="16" /></SvgIcon>;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
export function Info({ className, ...p }) {
|
|
756
|
+
return <SvgIcon className={className} {...p}><circle cx="12" cy="12" r="10" /><path d="M12 16v-4" /><path d="M12 8h.01" /></SvgIcon>;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
export function Menu({ className, ...p }) {
|
|
760
|
+
return <SvgIcon className={className} {...p}><line x1="4" x2="20" y1="6" y2="6" /><line x1="4" x2="20" y1="12" y2="12" /><line x1="4" x2="20" y1="18" y2="18" /></SvgIcon>;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
export function Search({ className, ...p }) {
|
|
764
|
+
return <SvgIcon className={className} {...p}><circle cx="11" cy="11" r="8" /><path d="m21 21-4.3-4.3" /></SvgIcon>;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
export function ChevronDown({ className, ...p }) {
|
|
768
|
+
return <SvgIcon className={className} {...p}><path d="m6 9 6 6 6-6" /></SvgIcon>;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
export function ChevronUp({ className, ...p }) {
|
|
772
|
+
return <SvgIcon className={className} {...p}><path d="m18 15-6-6-6 6" /></SvgIcon>;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
export function ChevronRight({ className, ...p }) {
|
|
776
|
+
return <SvgIcon className={className} {...p}><path d="m9 18 6-6-6-6" /></SvgIcon>;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
export function ChevronLeft({ className, ...p }) {
|
|
780
|
+
return <SvgIcon className={className} {...p}><path d="m15 18-6-6 6-6" /></SvgIcon>;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
export function ArrowRight({ className, ...p }) {
|
|
784
|
+
return <SvgIcon className={className} {...p}><path d="M5 12h14" /><path d="m12 5 7 7-7 7" /></SvgIcon>;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
export function ArrowLeft({ className, ...p }) {
|
|
788
|
+
return <SvgIcon className={className} {...p}><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></SvgIcon>;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// Aliases
|
|
792
|
+
export const ChevronDownIcon = ChevronDown;
|
|
793
|
+
export const ChevronLeftIcon = ChevronLeft;
|
|
794
|
+
export const ChevronRightIcon = ChevronRight;
|
|
795
|
+
`);
|
|
796
|
+
|
|
797
|
+
write("src/pages/Home.jsx", `
|
|
798
|
+
import { useState } from "react";
|
|
799
|
+
import { useNavigate } from "react-router-dom";
|
|
674
800
|
import { Button } from "@/components/ui/button";
|
|
675
801
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
676
802
|
import { Input } from "@/components/ui/input";
|
|
@@ -690,24 +816,27 @@ import { Textarea } from "@/components/ui/textarea";
|
|
|
690
816
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
691
817
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
|
692
818
|
import { toast } from "sonner";
|
|
693
|
-
import { Menu, Info, CheckCircle } from "
|
|
694
|
-
import { ApiClient } from "
|
|
695
|
-
import Login from "./pages/auth/Login.jsx";
|
|
696
|
-
import Register from "./pages/auth/Register.jsx";
|
|
697
|
-
import ComponentTest from "./pages/ComponentTest.jsx";
|
|
819
|
+
import { Menu, Info, CheckCircle } from "@/components/ui/icons";
|
|
820
|
+
import { ApiClient } from "@/utils/api.js";
|
|
698
821
|
|
|
699
822
|
const enrollmentData = [
|
|
700
823
|
{ name: "Alex", course: "Web Design Fundamentals", status: "Enrolled" },
|
|
701
824
|
{ name: "Jordan", course: "Advanced Web App Design", status: "Waitlisted" },
|
|
702
|
-
{ name: "Taylor", course: "eSports Strategy", status: "Enrolled" }
|
|
825
|
+
{ name: "Taylor", course: "eSports Strategy", status: "Enrolled" },
|
|
826
|
+
];
|
|
827
|
+
|
|
828
|
+
const navLinks = [
|
|
829
|
+
{ label: "Home", href: "/" },
|
|
830
|
+
{ label: "Login", href: "/login" },
|
|
831
|
+
{ label: "Register", href: "/register" },
|
|
832
|
+
{ label: "Component Test", href: "/component-test" },
|
|
703
833
|
];
|
|
704
834
|
|
|
705
|
-
function
|
|
835
|
+
export default function Home() {
|
|
706
836
|
const [modalOpen, setModalOpen] = useState(false);
|
|
707
837
|
const [posts, setPosts] = useState([]);
|
|
708
838
|
const [loadingPosts, setLoadingPosts] = useState(false);
|
|
709
839
|
const [postsError, setPostsError] = useState("");
|
|
710
|
-
const navigate = useNavigate();
|
|
711
840
|
const client = new ApiClient("https://jsonplaceholder.typicode.com");
|
|
712
841
|
|
|
713
842
|
const fetchPosts = async () => {
|
|
@@ -722,13 +851,6 @@ function Dashboard() {
|
|
|
722
851
|
setLoadingPosts(false);
|
|
723
852
|
};
|
|
724
853
|
|
|
725
|
-
const navLinks = [
|
|
726
|
-
{ label: "Home", href: "/" },
|
|
727
|
-
{ label: "Login", href: "/login" },
|
|
728
|
-
{ label: "Register", href: "/register" },
|
|
729
|
-
{ label: "Component Test", href: "/component-test" }
|
|
730
|
-
];
|
|
731
|
-
|
|
732
854
|
return (
|
|
733
855
|
<div className="flex h-screen overflow-hidden">
|
|
734
856
|
|
|
@@ -749,7 +871,6 @@ function Dashboard() {
|
|
|
749
871
|
|
|
750
872
|
{/* Navbar */}
|
|
751
873
|
<nav className="bg-white border-b px-4 py-3 flex items-center justify-between">
|
|
752
|
-
{/* Mobile sidebar trigger */}
|
|
753
874
|
<Sheet>
|
|
754
875
|
<SheetTrigger asChild>
|
|
755
876
|
<Button variant="ghost" size="icon" className="md:hidden">
|
|
@@ -774,14 +895,10 @@ function Dashboard() {
|
|
|
774
895
|
{/* Page content */}
|
|
775
896
|
<div className="p-6 space-y-6 overflow-auto">
|
|
776
897
|
|
|
777
|
-
{/* BDPA Logo
|
|
898
|
+
{/* BDPA Logo */}
|
|
778
899
|
<Card className="text-center">
|
|
779
900
|
<CardContent className="pt-6">
|
|
780
|
-
<img
|
|
781
|
-
src="/BDPA_edited.png"
|
|
782
|
-
alt="BDPA Logo"
|
|
783
|
-
className="h-32 mx-auto mb-4"
|
|
784
|
-
/>
|
|
901
|
+
<img src="/BDPA_edited.png" alt="BDPA Logo" className="h-32 mx-auto mb-4" />
|
|
785
902
|
<h1 className="text-3xl font-bold text-blue-600">Welcome to BDPA</h1>
|
|
786
903
|
<p className="text-gray-600 mt-2">Black Data Professionals Association</p>
|
|
787
904
|
</CardContent>
|
|
@@ -808,12 +925,14 @@ function Dashboard() {
|
|
|
808
925
|
<AlertDescription>Buttons, Cards, Inputs, Tables, Badges, Selects, and more — all from shadcn/ui.</AlertDescription>
|
|
809
926
|
</Alert>
|
|
810
927
|
</TabsContent>
|
|
811
|
-
<TabsContent value="auth"
|
|
928
|
+
<TabsContent value="auth">
|
|
929
|
+
<p className="mt-2 text-sm">Login + Registration pages included.</p>
|
|
930
|
+
</TabsContent>
|
|
812
931
|
</Tabs>
|
|
813
932
|
|
|
814
933
|
<div className="grid md:grid-cols-2 gap-6">
|
|
815
934
|
|
|
816
|
-
{/* Form
|
|
935
|
+
{/* Sample Form */}
|
|
817
936
|
<Card>
|
|
818
937
|
<CardHeader><CardTitle>Sample Form</CardTitle></CardHeader>
|
|
819
938
|
<CardContent className="space-y-4">
|
|
@@ -836,7 +955,7 @@ function Dashboard() {
|
|
|
836
955
|
</CardContent>
|
|
837
956
|
</Card>
|
|
838
957
|
|
|
839
|
-
{/* Table
|
|
958
|
+
{/* Enrollment Table */}
|
|
840
959
|
<Card>
|
|
841
960
|
<CardHeader><CardTitle>Enrollment Overview</CardTitle></CardHeader>
|
|
842
961
|
<CardContent>
|
|
@@ -882,7 +1001,7 @@ function Dashboard() {
|
|
|
882
1001
|
|
|
883
1002
|
<Separator />
|
|
884
1003
|
|
|
885
|
-
{/*
|
|
1004
|
+
{/* Badges */}
|
|
886
1005
|
<Card>
|
|
887
1006
|
<CardHeader><CardTitle>Badges</CardTitle></CardHeader>
|
|
888
1007
|
<CardContent className="flex flex-wrap gap-2">
|
|
@@ -893,7 +1012,7 @@ function Dashboard() {
|
|
|
893
1012
|
</CardContent>
|
|
894
1013
|
</Card>
|
|
895
1014
|
|
|
896
|
-
{/* Select
|
|
1015
|
+
{/* Select / Checkbox / Switch / Textarea / Progress */}
|
|
897
1016
|
<div className="grid md:grid-cols-2 gap-6">
|
|
898
1017
|
<Card>
|
|
899
1018
|
<CardHeader><CardTitle>Select & Switch</CardTitle></CardHeader>
|
|
@@ -938,7 +1057,7 @@ function Dashboard() {
|
|
|
938
1057
|
</Card>
|
|
939
1058
|
</div>
|
|
940
1059
|
|
|
941
|
-
{/* Skeleton
|
|
1060
|
+
{/* Skeleton */}
|
|
942
1061
|
<Card>
|
|
943
1062
|
<CardHeader><CardTitle>Skeleton Loading State</CardTitle></CardHeader>
|
|
944
1063
|
<CardContent className="space-y-2">
|
|
@@ -973,9 +1092,7 @@ function Dashboard() {
|
|
|
973
1092
|
{/* Dialog + Toast */}
|
|
974
1093
|
<div className="flex gap-4">
|
|
975
1094
|
<Button onClick={() => setModalOpen(true)}>Open Dialog</Button>
|
|
976
|
-
<Button onClick={() => toast.success("This is a toast!")}>
|
|
977
|
-
Show Toast
|
|
978
|
-
</Button>
|
|
1095
|
+
<Button onClick={() => toast.success("This is a toast!")}>Show Toast</Button>
|
|
979
1096
|
</div>
|
|
980
1097
|
|
|
981
1098
|
<Dialog open={modalOpen} onOpenChange={setModalOpen}>
|
|
@@ -993,39 +1110,6 @@ function Dashboard() {
|
|
|
993
1110
|
</div>
|
|
994
1111
|
);
|
|
995
1112
|
}
|
|
996
|
-
|
|
997
|
-
export default function App() {
|
|
998
|
-
const navigate = useNavigate();
|
|
999
|
-
|
|
1000
|
-
return (
|
|
1001
|
-
<Routes>
|
|
1002
|
-
<Route path="/" element={<Dashboard />} />
|
|
1003
|
-
<Route
|
|
1004
|
-
path="/login"
|
|
1005
|
-
element={
|
|
1006
|
-
<Login
|
|
1007
|
-
onSubmit={() => {
|
|
1008
|
-
toast.success("Login submitted!");
|
|
1009
|
-
navigate("/");
|
|
1010
|
-
}}
|
|
1011
|
-
/>
|
|
1012
|
-
}
|
|
1013
|
-
/>
|
|
1014
|
-
<Route
|
|
1015
|
-
path="/register"
|
|
1016
|
-
element={
|
|
1017
|
-
<Register
|
|
1018
|
-
onSubmit={() => {
|
|
1019
|
-
toast.success("Registration submitted!");
|
|
1020
|
-
navigate("/");
|
|
1021
|
-
}}
|
|
1022
|
-
/>
|
|
1023
|
-
}
|
|
1024
|
-
/>
|
|
1025
|
-
<Route path="/component-test" element={<ComponentTest />} />
|
|
1026
|
-
</Routes>
|
|
1027
|
-
);
|
|
1028
|
-
}
|
|
1029
1113
|
`);
|
|
1030
1114
|
|
|
1031
1115
|
// Note: All UI components (Card, Input, Form, Table, Navbar, Tabs, Toast, etc.)
|
|
@@ -1221,10 +1305,9 @@ export default function Register({ onSubmit }) {
|
|
|
1221
1305
|
</p>
|
|
1222
1306
|
</div>
|
|
1223
1307
|
)}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
</Button>
|
|
1308
|
+
<Button type="submit" className="w-full">
|
|
1309
|
+
Register
|
|
1310
|
+
</Button>
|
|
1228
1311
|
</form>
|
|
1229
1312
|
<Separator className="my-4" />
|
|
1230
1313
|
<p className="text-sm text-center text-gray-600">
|
|
@@ -1266,7 +1349,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/comp
|
|
|
1266
1349
|
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
|
|
1267
1350
|
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|
1268
1351
|
import { toast } from "sonner";
|
|
1269
|
-
import { CheckCircle, Info, AlertCircle } from "
|
|
1352
|
+
import { CheckCircle, Info, AlertCircle } from "@/components/ui/icons";
|
|
1270
1353
|
|
|
1271
1354
|
const sampleRows = [
|
|
1272
1355
|
{ id: 1, name: "Ada Lovelace", role: "Student", status: "Active" },
|