modula-ui 1.0.3 → 1.0.4
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/bin/run.js +23 -21
- package/package.json +8 -5
- package/public/google.svg +2 -0
- package/public/logo_cloudsync.png +0 -0
- package/registry.json +11 -13
- package/src/app/globals.css +40 -1
- package/src/app/group-chat/page.jsx +6 -0
- package/src/app/layout.js +10 -5
- package/src/app/login-demo/page.jsx +5 -0
- package/src/app/page.js +1 -1
- package/src/app/video-conference/page.jsx +6 -0
- package/src/components/Header.jsx +1 -1
- package/src/components/Logo.jsx +1 -1
- package/src/components/PreviewCard.jsx +6 -69
- package/src/components/Sidebar.jsx +1 -1
- package/src/components/login-template/google.svg +2 -0
- package/src/components/login-template/index.css +4 -0
- package/src/components/login-template/index.jsx +9 -0
- package/src/components/login-template/page.jsx +99 -0
- package/src/components/login-template/particles-background.jsx +100 -0
- package/src/components/ui/label.jsx +24 -0
- package/src/data/componentData.js +3 -2
- package/src/library/pages/GroupChat/index.jsx +2 -1
- package/src/library/pages/VideoConference/index.jsx +2 -1
package/bin/run.js
CHANGED
|
@@ -125,26 +125,28 @@ if (command === 'add') {
|
|
|
125
125
|
process.exit(1);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// else {
|
|
131
|
+
// // Default behavior: Start the Next.js server
|
|
132
|
+
// const port = 3177;
|
|
133
|
+
// const dev = false;
|
|
134
|
+
// const app = next({ dev, dir: packageRoot });
|
|
135
|
+
// const handle = app.getRequestHandler();
|
|
136
|
+
|
|
137
|
+
// await app.prepare();
|
|
138
|
+
|
|
139
|
+
// createServer((req, res) => {
|
|
140
|
+
// const parsedUrl = parse(req.url, true);
|
|
141
|
+
// handle(req, res, parsedUrl);
|
|
142
|
+
// }).listen(port, () => {
|
|
143
|
+
// console.log(`
|
|
144
|
+
// Your UI Library is LIVE!
|
|
145
|
+
// Open → http://localhost:${port}
|
|
144
146
|
|
|
145
|
-
|
|
147
|
+
// Click any component → Copy code → Paste into your project!
|
|
146
148
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
149
|
+
// Press Ctrl+C to stop
|
|
150
|
+
// `);
|
|
151
|
+
// });
|
|
152
|
+
// }
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modula-ui",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "A library of modern
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"description": "A library of beautiful modern UI blocks and patterns built with Shadcn by Mary Ojo",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tailwind",
|
|
7
7
|
"components",
|
|
@@ -28,15 +28,16 @@
|
|
|
28
28
|
"registry.json"
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
|
-
"dev": "next dev
|
|
31
|
+
"dev": "next dev",
|
|
32
32
|
"build": "next build",
|
|
33
|
-
"start": "next start
|
|
33
|
+
"start": "next start"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@radix-ui/react-avatar": "^1.1.11",
|
|
37
37
|
"@radix-ui/react-checkbox": "^1.3.3",
|
|
38
38
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
39
39
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
40
|
+
"@radix-ui/react-label": "^2.1.8",
|
|
40
41
|
"@radix-ui/react-navigation-menu": "^1.2.14",
|
|
41
42
|
"@radix-ui/react-popover": "^1.1.15",
|
|
42
43
|
"@radix-ui/react-progress": "^1.1.8",
|
|
@@ -46,12 +47,14 @@
|
|
|
46
47
|
"@radix-ui/react-slider": "^1.3.6",
|
|
47
48
|
"@radix-ui/react-slot": "^1.2.4",
|
|
48
49
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
50
|
+
"@tsparticles/react": "^3.0.0",
|
|
51
|
+
"@tsparticles/slim": "^3.9.1",
|
|
49
52
|
"class-variance-authority": "^0.7.1",
|
|
50
53
|
"clsx": "^2.1.1",
|
|
51
54
|
"date-fns": "^4.1.0",
|
|
52
55
|
"framer-motion": "^12.23.24",
|
|
53
56
|
"lucide-react": "^0.553.0",
|
|
54
|
-
"next": "16.0.
|
|
57
|
+
"next": "16.0.10",
|
|
55
58
|
"react": "19.2.0",
|
|
56
59
|
"react-day-picker": "^9.11.2",
|
|
57
60
|
"react-dom": "19.2.0",
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
2
|
+
<svg width="800px" height="800px" viewBox="-3 0 262 262" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M255.878 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45 12.04-9.283 30.172-26.69 42.356l-.244 1.622 38.755 30.023 2.685.268c24.659-22.774 38.875-56.282 38.875-96.027" fill="#4285F4"/><path d="M130.55 261.1c35.248 0 64.839-11.605 86.453-31.622l-41.196-31.913c-11.024 7.688-25.82 13.055-45.257 13.055-34.523 0-63.824-22.773-74.269-54.25l-1.531.13-40.298 31.187-.527 1.465C35.393 231.798 79.49 261.1 130.55 261.1" fill="#34A853"/><path d="M56.281 156.37c-2.756-8.123-4.351-16.827-4.351-25.82 0-8.994 1.595-17.697 4.206-25.82l-.073-1.73L15.26 71.312l-1.335.635C5.077 89.644 0 109.517 0 130.55s5.077 40.905 13.925 58.602l42.356-32.782" fill="#FBBC05"/><path d="M130.55 50.479c24.514 0 41.05 10.589 50.479 19.438l36.844-35.974C195.245 12.91 165.798 0 130.55 0 79.49 0 35.393 29.301 13.925 71.947l42.211 32.783c10.59-31.477 39.891-54.251 74.414-54.251" fill="#EB4335"/></svg>
|
|
Binary file
|
package/registry.json
CHANGED
|
@@ -13,25 +13,23 @@
|
|
|
13
13
|
"avatar"
|
|
14
14
|
]
|
|
15
15
|
},
|
|
16
|
-
"
|
|
17
|
-
"name": "
|
|
18
|
-
"type": "
|
|
19
|
-
"path": "src/
|
|
16
|
+
"login-page-01": {
|
|
17
|
+
"name": "Login Page 01",
|
|
18
|
+
"type": "blocks",
|
|
19
|
+
"path": "src/components/login-template/page.jsx",
|
|
20
20
|
"files": [
|
|
21
|
-
"src/
|
|
22
|
-
"src/
|
|
21
|
+
"src/components/login-template/page.jsx",
|
|
22
|
+
"src/components/login-template/particles-background.jsx"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": [
|
|
25
|
-
"
|
|
25
|
+
"@tsparticles/react",
|
|
26
|
+
"@tsparticles/slim"
|
|
26
27
|
],
|
|
27
28
|
"registryDependencies": [
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"badge",
|
|
31
|
-
"scroll-area",
|
|
32
|
-
"navigation-menu",
|
|
29
|
+
"button",
|
|
30
|
+
"card",
|
|
33
31
|
"input",
|
|
34
|
-
"
|
|
32
|
+
"label"
|
|
35
33
|
]
|
|
36
34
|
}
|
|
37
35
|
}
|
package/src/app/globals.css
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
2
|
@import "tw-animate-css";
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
@custom-variant dark (&:is(.dark *));
|
|
5
6
|
|
|
6
7
|
@theme inline {
|
|
7
8
|
--color-background: var(--background);
|
|
8
9
|
--color-foreground: var(--foreground);
|
|
9
|
-
--font-sans: var(--font-
|
|
10
|
+
--font-sans: var(--font-dm-sans);
|
|
10
11
|
--font-mono: var(--font-geist-mono);
|
|
11
12
|
--color-sidebar-ring: var(--sidebar-ring);
|
|
12
13
|
--color-sidebar-border: var(--sidebar-border);
|
|
@@ -124,3 +125,41 @@
|
|
|
124
125
|
font-family: var(--font-lexend), sans-serif;
|
|
125
126
|
}
|
|
126
127
|
}
|
|
128
|
+
|
|
129
|
+
@layer components {
|
|
130
|
+
.glass {
|
|
131
|
+
/* Semi-transparent background – usually white or light tint */
|
|
132
|
+
background: rgba(255, 255, 255, 0.15); /* 0.1 – 0.25 is most common */
|
|
133
|
+
|
|
134
|
+
/* The magic line – blurs what's behind */
|
|
135
|
+
backdrop-filter: blur(12px);
|
|
136
|
+
-webkit-backdrop-filter: blur(12px); /* Safari support */
|
|
137
|
+
|
|
138
|
+
/* Softer rounded corners */
|
|
139
|
+
border-radius: 16px;
|
|
140
|
+
|
|
141
|
+
/* Subtle border that looks like glass edge */
|
|
142
|
+
border: 1px solid rgba(255, 255, 255, 0.25);
|
|
143
|
+
|
|
144
|
+
/* Optional – adds depth & modern feel */
|
|
145
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
|
|
146
|
+
|
|
147
|
+
/* Important for readability */
|
|
148
|
+
color: white;
|
|
149
|
+
padding: 2rem;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.glass-dark {
|
|
153
|
+
background: rgba(31, 31, 32, 0.75); /* dark tint */
|
|
154
|
+
backdrop-filter: blur(25px);
|
|
155
|
+
-webkit-backdrop-filter: blur(25px);
|
|
156
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
157
|
+
border-radius: 20px;
|
|
158
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4);
|
|
159
|
+
color: #f0f0ff;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
#tsparticles, #tsparticles canvas {
|
|
163
|
+
pointer-events: none !important;
|
|
164
|
+
}
|
|
165
|
+
}
|
package/src/app/layout.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DM_Sans, Geist, Geist_Mono } from "next/font/google";
|
|
2
2
|
import "./globals.css";
|
|
3
3
|
|
|
4
|
-
const
|
|
5
|
-
variable: "--font-
|
|
4
|
+
const dmSans = DM_Sans({
|
|
5
|
+
variable: "--font-dm-sans",
|
|
6
|
+
subsets: ["latin"],
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const geistSans = Geist({
|
|
10
|
+
variable: "--font-geist-sans",
|
|
6
11
|
subsets: ["latin"],
|
|
7
12
|
});
|
|
8
13
|
|
|
@@ -13,14 +18,14 @@ const geistMono = Geist_Mono({
|
|
|
13
18
|
|
|
14
19
|
export const metadata = {
|
|
15
20
|
title: "Modula UI",
|
|
16
|
-
description: "A library of modern
|
|
21
|
+
description: "A library of beautiful modern UI blocks and patterns built with care and Shadcn by Mary Ojo",
|
|
17
22
|
};
|
|
18
23
|
|
|
19
24
|
export default function RootLayout({ children }) {
|
|
20
25
|
return (
|
|
21
26
|
<html lang="en">
|
|
22
27
|
<body
|
|
23
|
-
className={`${
|
|
28
|
+
className={`${dmSans.variable} ${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
24
29
|
>
|
|
25
30
|
{children}
|
|
26
31
|
</body>
|
package/src/app/page.js
CHANGED
|
@@ -9,7 +9,7 @@ export default function Header({ sidebarOpen, toggleSidebar }) {
|
|
|
9
9
|
<div className="mb-8 flex items-center justify-between">
|
|
10
10
|
<div>
|
|
11
11
|
<Logo />
|
|
12
|
-
<p className="text-gray-600">A library of modern
|
|
12
|
+
<p className="text-gray-600">A library of beautiful modern UI blocks and patterns built with care and Shadcn by <a href="https://www.linkedin.com/in/mary-ojo/" className='underline'>Mary (a Design Engineer)</a></p>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
15
|
<button
|
package/src/components/Logo.jsx
CHANGED
|
@@ -1,80 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
import { createPortal } from "react-dom";
|
|
3
|
-
|
|
4
|
-
export default function PreviewCard({ children, title = "Preview" }) {
|
|
5
|
-
const [externalWindow, setExternalWindow] = useState(null);
|
|
6
|
-
const [containerElement, setContainerElement] = useState(null);
|
|
7
|
-
|
|
1
|
+
export default function PreviewCard({ children, title = "Preview", url }) {
|
|
8
2
|
const openFullPreview = () => {
|
|
9
|
-
if (
|
|
10
|
-
|
|
11
|
-
return;
|
|
3
|
+
if (url) {
|
|
4
|
+
window.open(url, "_blank");
|
|
12
5
|
}
|
|
13
|
-
|
|
14
|
-
const newWindow = window.open("", "_blank", "width=1200,height=800,left=200,top=200");
|
|
15
|
-
if (!newWindow) return;
|
|
16
|
-
|
|
17
|
-
const fullPage = `
|
|
18
|
-
<!DOCTYPE html>
|
|
19
|
-
<html lang="en">
|
|
20
|
-
<head>
|
|
21
|
-
<meta charset="utf-8">
|
|
22
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
23
|
-
<title>${title}</title>
|
|
24
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
|
25
|
-
<style>
|
|
26
|
-
body { margin: 0; background: #f9fafb; }
|
|
27
|
-
@media (prefers-color-scheme: dark) { body { background: #111827; } }
|
|
28
|
-
</style>
|
|
29
|
-
</head>
|
|
30
|
-
<body class="min-h-screen flex items-center justify-center">
|
|
31
|
-
<div id="root" class="w-full mx-auto"></div>
|
|
32
|
-
</body>
|
|
33
|
-
</html>
|
|
34
|
-
`;
|
|
35
|
-
|
|
36
|
-
newWindow.document.write(fullPage);
|
|
37
|
-
newWindow.document.close();
|
|
38
|
-
|
|
39
|
-
// Wait for the window to load before trying to access the DOM
|
|
40
|
-
newWindow.onload = () => {
|
|
41
|
-
const container = newWindow.document.getElementById("root");
|
|
42
|
-
setExternalWindow(newWindow);
|
|
43
|
-
setContainerElement(container);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// In case onload fired synchronously or we missed it (rare with open, but good safety)
|
|
47
|
-
if (newWindow.document.readyState === 'complete') {
|
|
48
|
-
const container = newWindow.document.getElementById("root");
|
|
49
|
-
setExternalWindow(newWindow);
|
|
50
|
-
setContainerElement(container);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Handle window close
|
|
54
|
-
newWindow.onbeforeunload = () => {
|
|
55
|
-
setExternalWindow(null);
|
|
56
|
-
setContainerElement(null);
|
|
57
|
-
};
|
|
58
6
|
};
|
|
59
7
|
|
|
60
|
-
// Close external window when component unmounts
|
|
61
|
-
useEffect(() => {
|
|
62
|
-
return () => {
|
|
63
|
-
if (externalWindow) {
|
|
64
|
-
externalWindow.close();
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
}, [externalWindow]);
|
|
68
|
-
|
|
69
8
|
return (
|
|
70
9
|
<div className="w-full bg-white rounded-lg shadow-sm border border-gray-200 p-3">
|
|
71
10
|
<div className="flex items-center justify-between mb-4">
|
|
72
11
|
<h2 className="text-xl font-semibold text-gray-900">{title}</h2>
|
|
73
12
|
|
|
74
13
|
<button
|
|
14
|
+
type="button"
|
|
75
15
|
onClick={openFullPreview}
|
|
76
16
|
className={`flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium rounded-md transition
|
|
77
|
-
text-gray-700 bg-gray-50 hover:bg-gray-100 hover:text-gray-900`}
|
|
17
|
+
text-gray-700 bg-gray-50 hover:bg-gray-100 hover:text-gray-900 cursor-pointer`}
|
|
78
18
|
>
|
|
79
19
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
80
20
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
|
@@ -86,13 +26,10 @@ export default function PreviewCard({ children, title = "Preview" }) {
|
|
|
86
26
|
{/* The preview area in the main window */}
|
|
87
27
|
<div
|
|
88
28
|
id="preview-content"
|
|
89
|
-
className="bg-gray-50 rounded-lg p-4 border border-dashed border-gray-300 min-h-96 w-full"
|
|
29
|
+
className="bg-gray-50 rounded-lg p-4 border border-dashed border-gray-300 min-h-96 max-h-[600px] w-full overflow-hidden"
|
|
90
30
|
>
|
|
91
31
|
{children}
|
|
92
32
|
</div>
|
|
93
|
-
|
|
94
|
-
{/* Render content into the new window if it exists */}
|
|
95
|
-
{containerElement && createPortal(children, containerElement)}
|
|
96
33
|
</div>
|
|
97
34
|
);
|
|
98
35
|
}
|
|
@@ -15,7 +15,7 @@ export default function Sidebar({ selected, onSelect, open, onClose }) {
|
|
|
15
15
|
style={{ top: '1.5rem' }} // matches Header padding
|
|
16
16
|
>
|
|
17
17
|
<div className="flex items-center justify-between mb-4 lg:mb-3">
|
|
18
|
-
<h2 className="font-semibold text-gray-700">
|
|
18
|
+
<h2 className="font-semibold text-gray-700">Blocks</h2>
|
|
19
19
|
<button
|
|
20
20
|
onClick={onClose}
|
|
21
21
|
className="lg:hidden p-1 hover:bg-gray-100 rounded"
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
2
|
+
<svg width="800px" height="800px" viewBox="-3 0 262 262" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M255.878 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45 12.04-9.283 30.172-26.69 42.356l-.244 1.622 38.755 30.023 2.685.268c24.659-22.774 38.875-56.282 38.875-96.027" fill="#4285F4"/><path d="M130.55 261.1c35.248 0 64.839-11.605 86.453-31.622l-41.196-31.913c-11.024 7.688-25.82 13.055-45.257 13.055-34.523 0-63.824-22.773-74.269-54.25l-1.531.13-40.298 31.187-.527 1.465C35.393 231.798 79.49 261.1 130.55 261.1" fill="#34A853"/><path d="M56.281 156.37c-2.756-8.123-4.351-16.827-4.351-25.82 0-8.994 1.595-17.697 4.206-25.82l-.073-1.73L15.26 71.312l-1.335.635C5.077 89.644 0 109.517 0 130.55s5.077 40.905 13.925 58.602l42.356-32.782" fill="#FBBC05"/><path d="M130.55 50.479c24.514 0 41.05 10.589 50.479 19.438l36.844-35.974C195.245 12.91 165.798 0 130.55 0 79.49 0 35.393 29.301 13.925 71.947l42.211 32.783c10.59-31.477 39.891-54.251 74.414-54.251" fill="#EB4335"/></svg>
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Button } from "@/components/ui/button"
|
|
4
|
+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
|
|
5
|
+
import { Input } from "@/components/ui/input"
|
|
6
|
+
import { Label } from "@/components/ui/label"
|
|
7
|
+
import { ParticlesBackground } from "./particles-background"
|
|
8
|
+
import logo from "../../../public/logo_cloudsync.png"
|
|
9
|
+
import google from "../../../public/google.svg"
|
|
10
|
+
import Image from "next/image"
|
|
11
|
+
|
|
12
|
+
export default function LoginPage() {
|
|
13
|
+
return (
|
|
14
|
+
<div className="dark font-sans w-full min-h-screen flex flex-col lg:flex-row items-center justify-center lg:justify-end overflow-hidden bg-background text-foreground">
|
|
15
|
+
<ParticlesBackground />
|
|
16
|
+
|
|
17
|
+
<div className="w-full z-10 px-10 sm:px-6 lg:px-20 py-12 md:py-12 flex flex-col lg:flex-row items-center justify-center gap-8 lg:gap-28">
|
|
18
|
+
<div className="hidden lg:block space-y-4 w-full lg:w-1/2">
|
|
19
|
+
<div className="flex items-center gap-4 mb-4">
|
|
20
|
+
<Image
|
|
21
|
+
src={logo}
|
|
22
|
+
alt="Logo"
|
|
23
|
+
width={65}
|
|
24
|
+
height={65}
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
<h3 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight text-white">Secure, Scalable and Seamless</h3>
|
|
28
|
+
<p className="text-sm sm:text-base md:text-lg text-muted-foreground">Empowering businesses with world-class cloud computing infrastructure and 99.9% uptime. Managed, monitored and optimized for your growth.</p>
|
|
29
|
+
</div>
|
|
30
|
+
<div className="lg:hidden flex justify-center mb-4">
|
|
31
|
+
<Image
|
|
32
|
+
src={logo}
|
|
33
|
+
alt="Logo"
|
|
34
|
+
width={65}
|
|
35
|
+
height={65}
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
<Card className="w-full md:w-[70%] lg:w-1/2 glass-dark">
|
|
39
|
+
<CardHeader className="space-y-1 ">
|
|
40
|
+
<CardTitle className="text-xl sm:text-2xl font-bold tracking-tight">Welcome back</CardTitle>
|
|
41
|
+
<CardDescription className="text-sm sm:text-base text-muted-foreground/80">
|
|
42
|
+
Enter your email to sign in to your account
|
|
43
|
+
</CardDescription>
|
|
44
|
+
</CardHeader>
|
|
45
|
+
<div className="relative my-1">
|
|
46
|
+
<div className="absolute inset-0 flex items-center">
|
|
47
|
+
<span className="w-full border-t border-muted-foreground/20" />
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
<CardContent className="space-y-4">
|
|
51
|
+
<div className="space-y-2">
|
|
52
|
+
<Label htmlFor="email" className="text-sm">Email</Label>
|
|
53
|
+
<Input id="email" placeholder="m@example.com" required type="email" className="bg-white/5 backdrop-blur-sm border-white/10 focus:bg-white/10 focus:border-white/20 transition-all text-sm" />
|
|
54
|
+
</div>
|
|
55
|
+
<div className="space-y-2">
|
|
56
|
+
<Label htmlFor="password" className="text-sm">Password</Label>
|
|
57
|
+
<Input id="password" required placeholder="********" type="password" className="bg-white/5 backdrop-blur-sm border-white/10 focus:bg-white/10 focus:border-white/20 transition-all text-sm" />
|
|
58
|
+
</div>
|
|
59
|
+
<Button className="w-full bg-cyan-500 shadow-lg shadow-primary/20 hover:shadow-primary/40 transition-shadow text-sm sm:text-base" type="submit">
|
|
60
|
+
Sign In
|
|
61
|
+
</Button>
|
|
62
|
+
|
|
63
|
+
<div className="relative my-2 mb-3">
|
|
64
|
+
<div className="absolute inset-0 flex items-center">
|
|
65
|
+
<span className="w-full border-t border-muted-foreground/20" />
|
|
66
|
+
</div>
|
|
67
|
+
<div className="relative flex justify-center text-xs uppercase">
|
|
68
|
+
<span className="bg-transparent px-2 text-muted-foreground">
|
|
69
|
+
Or continue with
|
|
70
|
+
</span>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<Button variant="outline" className="w-full bg-white/5 backdrop-blur-sm border-white/10 hover:bg-white/10 hover:text-white text-sm sm:text-base" onClick={() => { }}>
|
|
75
|
+
<Image
|
|
76
|
+
src={google}
|
|
77
|
+
alt="Google"
|
|
78
|
+
width={16}
|
|
79
|
+
height={16}
|
|
80
|
+
/>
|
|
81
|
+
Google
|
|
82
|
+
</Button>
|
|
83
|
+
</CardContent>
|
|
84
|
+
<CardFooter className="flex flex-col gap-2 text-center text-xs sm:text-sm text-muted-foreground">
|
|
85
|
+
<a href="#" className="hover:text-primary transition-colors hover:underline">
|
|
86
|
+
Forgot your password?
|
|
87
|
+
</a>
|
|
88
|
+
<div className="text-xs">
|
|
89
|
+
Don't have an account?{" "}
|
|
90
|
+
<a href="#" className="font-medium text-primary hover:underline transition-colors">
|
|
91
|
+
Sign up for free
|
|
92
|
+
</a>
|
|
93
|
+
</div>
|
|
94
|
+
</CardFooter>
|
|
95
|
+
</Card>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react"
|
|
4
|
+
import Particles, { initParticlesEngine } from "@tsparticles/react"
|
|
5
|
+
import { loadSlim } from "@tsparticles/slim"
|
|
6
|
+
|
|
7
|
+
export function ParticlesBackground() {
|
|
8
|
+
const [init, setInit] = useState(false)
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
initParticlesEngine(async (engine) => {
|
|
12
|
+
await loadSlim(engine)
|
|
13
|
+
}).then(() => {
|
|
14
|
+
setInit(true)
|
|
15
|
+
})
|
|
16
|
+
}, [])
|
|
17
|
+
|
|
18
|
+
if (!init) {
|
|
19
|
+
return null
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const options = {
|
|
23
|
+
particles: {
|
|
24
|
+
number: {
|
|
25
|
+
value: 30,
|
|
26
|
+
density: {
|
|
27
|
+
enable: true,
|
|
28
|
+
width: 800,
|
|
29
|
+
height: 800
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
color: {
|
|
33
|
+
value: "#FFFEE0"
|
|
34
|
+
},
|
|
35
|
+
shape: {
|
|
36
|
+
type: "circle",
|
|
37
|
+
},
|
|
38
|
+
opacity: {
|
|
39
|
+
value: 0.5,
|
|
40
|
+
animation: {
|
|
41
|
+
enable: false
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
size: {
|
|
45
|
+
value: { min: 1, max: 3 },
|
|
46
|
+
},
|
|
47
|
+
links: {
|
|
48
|
+
enable: true,
|
|
49
|
+
distance: 150,
|
|
50
|
+
color: "#00FFFF",
|
|
51
|
+
opacity: 0.2,
|
|
52
|
+
width: 1
|
|
53
|
+
},
|
|
54
|
+
move: {
|
|
55
|
+
enable: true,
|
|
56
|
+
speed: 0.1,
|
|
57
|
+
direction: "none",
|
|
58
|
+
random: false,
|
|
59
|
+
straight: false,
|
|
60
|
+
outModes: {
|
|
61
|
+
default: "out"
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
interactivity: {
|
|
66
|
+
detectsOn: "canvas",
|
|
67
|
+
events: {
|
|
68
|
+
onHover: {
|
|
69
|
+
enable: false,
|
|
70
|
+
mode: "repulse"
|
|
71
|
+
},
|
|
72
|
+
onClick: {
|
|
73
|
+
enable: false,
|
|
74
|
+
mode: "push"
|
|
75
|
+
},
|
|
76
|
+
resize: {
|
|
77
|
+
enable: false
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
modes: {
|
|
81
|
+
repulse: {
|
|
82
|
+
distance: 100,
|
|
83
|
+
duration: 0.4
|
|
84
|
+
},
|
|
85
|
+
push: {
|
|
86
|
+
quantity: 4
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
retina_detect: true
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<Particles
|
|
95
|
+
id="tsparticles"
|
|
96
|
+
className="pointer-events-none"
|
|
97
|
+
options={options}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as LabelPrimitive from "@radix-ui/react-label"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
function Label({
|
|
9
|
+
className,
|
|
10
|
+
...props
|
|
11
|
+
}) {
|
|
12
|
+
return (
|
|
13
|
+
<LabelPrimitive.Root
|
|
14
|
+
data-slot="label"
|
|
15
|
+
className={cn(
|
|
16
|
+
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { Label }
|
|
@@ -2,11 +2,12 @@ import { VideoConference } from "@/library/pages/VideoConference";
|
|
|
2
2
|
import { ReservationsOverview } from "@/library/pages/ReservationsOverview";
|
|
3
3
|
import { FitnessOverview } from "@/library/pages/FitnessPage";
|
|
4
4
|
import { GroupChat } from "@/library/pages/GroupChat";
|
|
5
|
-
|
|
5
|
+
import { LoginDemo } from "@/components/login-template";
|
|
6
6
|
|
|
7
7
|
export const components = {
|
|
8
8
|
VideoConference,
|
|
9
|
-
GroupChat,
|
|
9
|
+
// GroupChat,
|
|
10
|
+
LoginDemo,
|
|
10
11
|
// ReservationsOverview,
|
|
11
12
|
// FitnessOverview
|
|
12
13
|
};
|