ikramhussainsiyam-create-my-project 1.2.1 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- package/cli.js +2 -2
- package/package.json +1 -1
- package/templates/NextJS/JavaScript/.eslintrc.json +3 -0
- package/templates/NextJS/JavaScript/README.md +36 -0
- package/templates/NextJS/JavaScript/gitignore-template +38 -0
- package/templates/NextJS/JavaScript/jsconfig.json +7 -0
- package/templates/NextJS/JavaScript/next.config.mjs +4 -0
- package/templates/NextJS/JavaScript/package-lock.json +5188 -0
- package/templates/NextJS/JavaScript/package.json +30 -0
- package/templates/NextJS/JavaScript/postcss.config.mjs +8 -0
- package/templates/NextJS/JavaScript/src/app/favicon.ico +0 -0
- package/templates/NextJS/JavaScript/src/app/globals.css +30 -0
- package/templates/NextJS/JavaScript/src/app/layout.jsx +26 -0
- package/templates/NextJS/JavaScript/src/app/page.jsx +3 -0
- package/templates/NextJS/JavaScript/src/components/Navlink.jsx +28 -0
- package/templates/NextJS/JavaScript/src/components/ToastContainer.jsx +84 -0
- package/templates/NextJS/JavaScript/src/components/ui/Alert.jsx +48 -0
- package/templates/NextJS/JavaScript/src/components/ui/Button.jsx +58 -0
- package/templates/NextJS/JavaScript/src/components/ui/Skeleton.jsx +14 -0
- package/templates/NextJS/JavaScript/src/lib/utils.js +24 -0
- package/templates/NextJS/JavaScript/tailwind.config.js +20 -0
- package/templates/ViteJS/JavaScript/README.md +3 -0
- package/templates/ViteJS/JavaScript/eslint.config.js +1 -4
- package/templates/ViteJS/JavaScript/gitignore-template +1 -0
- package/templates/ViteJS/JavaScript/src/index.css +13 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
{
|
2
|
+
"name": "module-7-introduction-to-nextjs",
|
3
|
+
"version": "0.1.0",
|
4
|
+
"private": true,
|
5
|
+
"scripts": {
|
6
|
+
"dev": "next dev",
|
7
|
+
"build": "next build",
|
8
|
+
"start": "next start",
|
9
|
+
"lint": "next lint"
|
10
|
+
},
|
11
|
+
"dependencies": {
|
12
|
+
"@tailwindcss/aspect-ratio": "^0.4.2",
|
13
|
+
"@tailwindcss/forms": "^0.5.9",
|
14
|
+
"clsx": "^2.1.1",
|
15
|
+
"next": "14.2.18",
|
16
|
+
"react": "^18",
|
17
|
+
"react-dom": "^18",
|
18
|
+
"react-hook-form": "^7.53.2",
|
19
|
+
"react-icons": "^5.3.0",
|
20
|
+
"sonner": "^1.7.0",
|
21
|
+
"tailwind-merge": "^2.5.4",
|
22
|
+
"use-immer": "^0.10.0"
|
23
|
+
},
|
24
|
+
"devDependencies": {
|
25
|
+
"eslint": "^8",
|
26
|
+
"eslint-config-next": "14.2.18",
|
27
|
+
"postcss": "^8",
|
28
|
+
"tailwindcss": "^3.4.1"
|
29
|
+
}
|
30
|
+
}
|
Binary file
|
@@ -0,0 +1,30 @@
|
|
1
|
+
@tailwind base;
|
2
|
+
@tailwind components;
|
3
|
+
@tailwind utilities;
|
4
|
+
|
5
|
+
@layer base {
|
6
|
+
body {
|
7
|
+
@apply antialiased bg-white font-sans;
|
8
|
+
}
|
9
|
+
/* scroll bar styling */
|
10
|
+
::-webkit-scrollbar {
|
11
|
+
width: 12px;
|
12
|
+
height: 12px;
|
13
|
+
}
|
14
|
+
::-webkit-scrollbar-thumb {
|
15
|
+
background: #e2e2e2;
|
16
|
+
border-radius: 10px;
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
@layer components {
|
21
|
+
.btn {
|
22
|
+
@apply px-2 py-1 border rounded hover:bg-zinc-100 active:bg-white active:scale-95;
|
23
|
+
}
|
24
|
+
.container {
|
25
|
+
@apply px-4;
|
26
|
+
}
|
27
|
+
.input {
|
28
|
+
@apply px-3 py-2 border rounded;
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import ToastContainer from "@/components/ToastContainer";
|
2
|
+
import { Inter } from "next/font/google";
|
3
|
+
import "./globals.css";
|
4
|
+
|
5
|
+
const fontSans = Inter({
|
6
|
+
subsets: ["latin"],
|
7
|
+
variable: "--font-sans",
|
8
|
+
display: "swap",
|
9
|
+
});
|
10
|
+
|
11
|
+
export const metadata = {
|
12
|
+
title: "Project Title",
|
13
|
+
description: "Project Description",
|
14
|
+
};
|
15
|
+
|
16
|
+
export default function RootLayout({ children }) {
|
17
|
+
return (
|
18
|
+
<html lang="en">
|
19
|
+
<body className={fontSans.variable}>
|
20
|
+
<main>{children}</main>
|
21
|
+
|
22
|
+
<ToastContainer />
|
23
|
+
</body>
|
24
|
+
</html>
|
25
|
+
);
|
26
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"use client";
|
2
|
+
import Link from "next/link";
|
3
|
+
import { usePathname } from "next/navigation";
|
4
|
+
import { forwardRef } from "react";
|
5
|
+
|
6
|
+
function Navlink({ href, className, children, ...props }, ref) {
|
7
|
+
const pathname = usePathname();
|
8
|
+
const isActive = href === pathname;
|
9
|
+
|
10
|
+
return (
|
11
|
+
<Link
|
12
|
+
href={href}
|
13
|
+
{...props}
|
14
|
+
className={
|
15
|
+
isActive && className
|
16
|
+
? `underline ${className}`
|
17
|
+
: isActive
|
18
|
+
? "underline"
|
19
|
+
: className
|
20
|
+
}
|
21
|
+
ref={ref}
|
22
|
+
>
|
23
|
+
{children}
|
24
|
+
</Link>
|
25
|
+
);
|
26
|
+
}
|
27
|
+
|
28
|
+
export default forwardRef(Navlink);
|
@@ -0,0 +1,84 @@
|
|
1
|
+
"use client";
|
2
|
+
|
3
|
+
import {
|
4
|
+
FaCircleCheck,
|
5
|
+
FaCircleExclamation,
|
6
|
+
FaCircleInfo,
|
7
|
+
FaCircleXmark,
|
8
|
+
} from "react-icons/fa6";
|
9
|
+
import { LiaSpinnerSolid } from "react-icons/lia";
|
10
|
+
import { Toaster } from "sonner";
|
11
|
+
|
12
|
+
const ToastContainer = ({ type = "iconic", ...props }) => {
|
13
|
+
const icons = () => {
|
14
|
+
switch (type) {
|
15
|
+
case "neutral":
|
16
|
+
return {
|
17
|
+
success: <FaCircleCheck className="text-xl" />,
|
18
|
+
error: <FaCircleXmark className="text-xl" />,
|
19
|
+
info: <FaCircleInfo className="text-xl" />,
|
20
|
+
warning: <FaCircleExclamation className="text-xl" />,
|
21
|
+
loading: <LiaSpinnerSolid className="text-2xl animate-spin" />,
|
22
|
+
};
|
23
|
+
|
24
|
+
case "iconic":
|
25
|
+
return {
|
26
|
+
success: <FaCircleCheck className="text-xl text-lime-500" />,
|
27
|
+
error: <FaCircleXmark className="text-xl text-rose-500" />,
|
28
|
+
info: <FaCircleInfo className="text-xl text-sky-500" />,
|
29
|
+
warning: <FaCircleExclamation className="text-xl text-amber-500" />,
|
30
|
+
loading: <LiaSpinnerSolid className="text-2xl animate-spin" />,
|
31
|
+
};
|
32
|
+
|
33
|
+
case "colored":
|
34
|
+
return {
|
35
|
+
success: <FaCircleCheck className="text-xl text-lime-700" />,
|
36
|
+
error: <FaCircleXmark className="text-xl text-rose-700" />,
|
37
|
+
info: <FaCircleInfo className="text-xl text-sky-700" />,
|
38
|
+
warning: <FaCircleExclamation className="text-xl text-amber-700" />,
|
39
|
+
loading: <LiaSpinnerSolid className="text-2xl animate-spin" />,
|
40
|
+
};
|
41
|
+
}
|
42
|
+
};
|
43
|
+
|
44
|
+
return (
|
45
|
+
<Toaster
|
46
|
+
{...props}
|
47
|
+
toastOptions={{
|
48
|
+
classNames: {
|
49
|
+
toast: `group toast bg-background text-foreground font-sans gap-3 items-start ${
|
50
|
+
type === "colored" ? "shadow-lg" : ""
|
51
|
+
}`,
|
52
|
+
title: "text-base font-semibold",
|
53
|
+
description: `text-sm ${
|
54
|
+
type === "colored" ? "" : "text-muted-foreground"
|
55
|
+
}`,
|
56
|
+
icon: "text-center text-foreground mt-[4.3px]",
|
57
|
+
success:
|
58
|
+
type === "colored"
|
59
|
+
? "bg-lime-200 text-lime-700 shadow-lime-600/20 border-transparent"
|
60
|
+
: "",
|
61
|
+
error:
|
62
|
+
type === "colored"
|
63
|
+
? "bg-rose-200 text-rose-700 shadow-rose-600/20 border-transparent"
|
64
|
+
: "",
|
65
|
+
info:
|
66
|
+
type === "colored"
|
67
|
+
? "bg-sky-200 text-sky-700 shadow-sky-600/20 border-transparent"
|
68
|
+
: "",
|
69
|
+
warning:
|
70
|
+
type === "colored"
|
71
|
+
? "bg-amber-200 text-amber-700 shadow-amber-600/20 border-transparent"
|
72
|
+
: "",
|
73
|
+
actionButton:
|
74
|
+
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
|
75
|
+
cancelButton:
|
76
|
+
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
|
77
|
+
},
|
78
|
+
}}
|
79
|
+
icons={icons()}
|
80
|
+
/>
|
81
|
+
);
|
82
|
+
};
|
83
|
+
|
84
|
+
export default ToastContainer;
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { cn } from "@/lib/utils";
|
2
|
+
|
3
|
+
export default function Alert({ type, title, description, className }) {
|
4
|
+
return (
|
5
|
+
<div
|
6
|
+
className={cn(
|
7
|
+
`flex p-4 gap-3 text-sm rounded-lg border border-transparent ${alertType(
|
8
|
+
type
|
9
|
+
)}`,
|
10
|
+
className
|
11
|
+
)}
|
12
|
+
role="alert"
|
13
|
+
>
|
14
|
+
<svg
|
15
|
+
className={"w-4 h-4 mt-0.5"}
|
16
|
+
aria-hidden="true"
|
17
|
+
xmlns="http://www.w3.org/2000/svg"
|
18
|
+
fill="currentColor"
|
19
|
+
viewBox="0 0 20 20"
|
20
|
+
>
|
21
|
+
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z" />
|
22
|
+
</svg>
|
23
|
+
<span className="sr-only">Danger</span>
|
24
|
+
<div className="space-y-0.5">
|
25
|
+
<div>
|
26
|
+
<span className="font-semibold capitalize">{type || "Alert"}</span>:{" "}
|
27
|
+
{title}
|
28
|
+
</div>
|
29
|
+
<div>{description}</div>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
);
|
33
|
+
}
|
34
|
+
|
35
|
+
function alertType(type) {
|
36
|
+
switch (type) {
|
37
|
+
case "success":
|
38
|
+
return "text-lime-800 bg-lime-100 border-lime-300";
|
39
|
+
case "warning":
|
40
|
+
return "text-amber-800 bg-amber-100 border-amber-300";
|
41
|
+
case "error":
|
42
|
+
return "text-rose-800 bg-rose-100 border-rose-300";
|
43
|
+
case "info":
|
44
|
+
return "text-sky-800 bg-sky-100 border-sky-300";
|
45
|
+
default:
|
46
|
+
return "text-gray-800 bg-gray-100 border-gray-300";
|
47
|
+
}
|
48
|
+
}
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import { cn } from "@/lib/utils";
|
2
|
+
|
3
|
+
export default function Button({
|
4
|
+
size = "md",
|
5
|
+
color = "blue",
|
6
|
+
rounded = "lg",
|
7
|
+
children,
|
8
|
+
onClick,
|
9
|
+
className,
|
10
|
+
...props
|
11
|
+
}) {
|
12
|
+
return (
|
13
|
+
<button
|
14
|
+
{...props}
|
15
|
+
onClick={onClick}
|
16
|
+
className={cn(
|
17
|
+
`focus:ring-4 text-center font-medium focus:outline-none border border-transparent flex items-center gap-2.5 active:scale-[.97] transition duration-100 ${buttonStyles.color[color]} ${buttonStyles.size[size]} ${buttonStyles.rounded[rounded]}`,
|
18
|
+
className
|
19
|
+
)}
|
20
|
+
>
|
21
|
+
{children}
|
22
|
+
</button>
|
23
|
+
);
|
24
|
+
}
|
25
|
+
|
26
|
+
const buttonStyles = {
|
27
|
+
color: {
|
28
|
+
blue: "text-white bg-blue-700 hover:bg-blue-800 focus:ring-blue-300",
|
29
|
+
dark: "text-white bg-zinc-800 hover:bg-zinc-900 focus:ring-zinc-300",
|
30
|
+
outline:
|
31
|
+
"text-zinc-900 bg-white border-zinc-300 hover:bg-zinc-100 focus:ring-zinc-100",
|
32
|
+
ghost:
|
33
|
+
"text-zinc-900 bg-zinc-100 hover:bg-zinc-200/70 active:bg-zinc-100 focus:ring-zinc-100",
|
34
|
+
green: "text-white bg-green-700 hover:bg-green-800 focus:ring-green-300",
|
35
|
+
red: "text-white bg-red-700 hover:bg-red-800 focus:ring-red-300",
|
36
|
+
indigo:
|
37
|
+
"text-white bg-indigo-700 hover:bg-indigo-800 focus:ring-indigo-300",
|
38
|
+
amber: "text-white bg-amber-400 hover:bg-amber-500 focus:ring-amber-300",
|
39
|
+
"gradient-lime":
|
40
|
+
"text-zinc-900 bg-gradient-to-r from-teal-200 to-lime-200 hover:bg-gradient-to-l hover:from-teal-200 hover:to-lime-200 focus:ring-lime-200",
|
41
|
+
"gradient-blue":
|
42
|
+
"text-white bg-gradient-to-br from-purple-600 to-blue-500 hover:bg-gradient-to-bl focus:ring-blue-300",
|
43
|
+
},
|
44
|
+
size: {
|
45
|
+
sm: "text-sm px-3.5 py-1.5",
|
46
|
+
md: "text-sm px-5 py-2.5",
|
47
|
+
lg: "text-base px-5 py-2.5",
|
48
|
+
xl: "text-lg px-5 py-2.5",
|
49
|
+
},
|
50
|
+
rounded: {
|
51
|
+
sm: "rounded-sm",
|
52
|
+
md: "rounded-md",
|
53
|
+
lg: "rounded-lg",
|
54
|
+
xl: "rounded-xl",
|
55
|
+
full: "rounded-full",
|
56
|
+
none: "rounded-none",
|
57
|
+
},
|
58
|
+
};
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { cn } from "@/lib/utils/utils";
|
2
|
+
|
3
|
+
export default function Skeleton({ className, children }) {
|
4
|
+
return (
|
5
|
+
<div
|
6
|
+
className={cn(
|
7
|
+
"bg-zinc-200 animate-none animate-pulse rounded-md w-full h-full",
|
8
|
+
className
|
9
|
+
)}
|
10
|
+
>
|
11
|
+
{children}
|
12
|
+
</div>
|
13
|
+
);
|
14
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import clsx from "clsx";
|
2
|
+
import { toast } from "sonner";
|
3
|
+
import { twMerge } from "tailwind-merge";
|
4
|
+
|
5
|
+
export function cn(...classes) {
|
6
|
+
return twMerge(clsx(classes));
|
7
|
+
}
|
8
|
+
|
9
|
+
export function getRandomID() {
|
10
|
+
return Math.random().toString(36).substring(2, 9);
|
11
|
+
}
|
12
|
+
|
13
|
+
export const showToast = (
|
14
|
+
type, // "success" | "error" | "info" | "warning" | "loading"
|
15
|
+
message,
|
16
|
+
options
|
17
|
+
) => {
|
18
|
+
toast[type](message, {
|
19
|
+
position: options?.position || "top-center",
|
20
|
+
id: options?.id,
|
21
|
+
duration: options?.duration || 2000,
|
22
|
+
description: options?.description,
|
23
|
+
});
|
24
|
+
};
|
@@ -0,0 +1,20 @@
|
|
1
|
+
/** @type {import('tailwindcss').Config} */
|
2
|
+
import aspectRatio from "@tailwindcss/aspect-ratio";
|
3
|
+
import forms from "@tailwindcss/forms";
|
4
|
+
|
5
|
+
module.exports = {
|
6
|
+
content: [
|
7
|
+
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
|
8
|
+
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
|
9
|
+
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
|
10
|
+
],
|
11
|
+
|
12
|
+
theme: {
|
13
|
+
extend: {
|
14
|
+
fontFamily: {
|
15
|
+
sans: ["var(--font-sans)", "sans-serif"],
|
16
|
+
},
|
17
|
+
},
|
18
|
+
},
|
19
|
+
plugins: [forms, aspectRatio],
|
20
|
+
};
|
@@ -6,3 +6,6 @@ Currently, two official plugins are available:
|
|
6
6
|
|
7
7
|
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
8
8
|
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
9
|
+
|
10
|
+
<!-- TODO 1: add some most used components -->
|
11
|
+
<!-- TODO 2: add some most used utils / hooks / configs -->
|
@@ -35,10 +35,7 @@ export default [
|
|
35
35
|
],
|
36
36
|
"react/prop-types": "off",
|
37
37
|
"react/no-unescaped-entities": "off",
|
38
|
-
"react-refresh/only-export-components":
|
39
|
-
"warn",
|
40
|
-
{ allowConstantExport: true },
|
41
|
-
],
|
38
|
+
"react-refresh/only-export-components": "off",
|
42
39
|
},
|
43
40
|
},
|
44
41
|
];
|
@@ -23,4 +23,17 @@
|
|
23
23
|
.btn {
|
24
24
|
@apply px-2 py-1 border rounded hover:bg-zinc-100 active:bg-white active:scale-95;
|
25
25
|
}
|
26
|
+
/* TODO: remove 👇 these classes if you don't need them. */
|
27
|
+
.flex-c {
|
28
|
+
@apply flex justify-center items-center gap-2;
|
29
|
+
}
|
30
|
+
.flex-y {
|
31
|
+
@apply flex flex-col gap-2 items-center;
|
32
|
+
}
|
33
|
+
.flex-x {
|
34
|
+
@apply flex flex-row gap-2 items-center;
|
35
|
+
}
|
36
|
+
.title {
|
37
|
+
@apply text-2xl font-semibold mb-6;
|
38
|
+
}
|
26
39
|
}
|