diff --git a/components.json b/components.json
new file mode 100644
index 0000000..ce76ad3
--- /dev/null
+++ b/components.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": true,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.ts",
+ "css": "src/app/globals.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils"
+ }
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 9d242ea..17cb24e 100644
--- a/package.json
+++ b/package.json
@@ -9,17 +9,30 @@
"lint": "next lint"
},
"dependencies": {
+ "@hookform/resolvers": "^3.3.4",
+ "@radix-ui/react-label": "^2.0.2",
+ "@radix-ui/react-slot": "^1.0.2",
+ "class-variance-authority": "^0.7.0",
+ "clsx": "^2.1.0",
+ "embla-carousel-react": "^8.0.0-rc22",
+ "hamburger-react": "^2.5.0",
+ "lucide-react": "^0.320.0",
+ "next": "14.1.0",
"react": "^18",
"react-dom": "^18",
- "next": "14.1.0"
+ "react-fast-marquee": "^1.6.3",
+ "react-hook-form": "^7.50.0",
+ "tailwind-merge": "^2.2.1",
+ "tailwindcss-animate": "^1.0.7",
+ "zod": "^3.22.4"
},
"devDependencies": {
- "typescript": "^5",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10.0.1",
"postcss": "^8",
- "tailwindcss": "^3.3.0"
+ "tailwindcss": "^3.3.0",
+ "typescript": "^5"
}
}
diff --git a/public/VENEU/Veneu1.jpg b/public/VENEU/Veneu1.jpg
new file mode 100644
index 0000000..9ec6c21
Binary files /dev/null and b/public/VENEU/Veneu1.jpg differ
diff --git a/public/VENEU/Veneu10.jpg b/public/VENEU/Veneu10.jpg
new file mode 100644
index 0000000..f0bcaaf
Binary files /dev/null and b/public/VENEU/Veneu10.jpg differ
diff --git a/public/VENEU/Veneu2.jpg b/public/VENEU/Veneu2.jpg
new file mode 100644
index 0000000..710170a
Binary files /dev/null and b/public/VENEU/Veneu2.jpg differ
diff --git a/public/VENEU/Veneu3.jpg b/public/VENEU/Veneu3.jpg
new file mode 100644
index 0000000..809b3b1
Binary files /dev/null and b/public/VENEU/Veneu3.jpg differ
diff --git a/public/VENEU/Veneu4.jpg b/public/VENEU/Veneu4.jpg
new file mode 100644
index 0000000..d42391e
Binary files /dev/null and b/public/VENEU/Veneu4.jpg differ
diff --git a/public/VENEU/Veneu5.jpg b/public/VENEU/Veneu5.jpg
new file mode 100644
index 0000000..17c4bce
Binary files /dev/null and b/public/VENEU/Veneu5.jpg differ
diff --git a/public/VENEU/Veneu6.jpg b/public/VENEU/Veneu6.jpg
new file mode 100644
index 0000000..874810c
Binary files /dev/null and b/public/VENEU/Veneu6.jpg differ
diff --git a/public/VENEU/Veneu7.jpg b/public/VENEU/Veneu7.jpg
new file mode 100644
index 0000000..457e196
Binary files /dev/null and b/public/VENEU/Veneu7.jpg differ
diff --git a/public/VENEU/Veneu8.jpg b/public/VENEU/Veneu8.jpg
new file mode 100644
index 0000000..34f216b
Binary files /dev/null and b/public/VENEU/Veneu8.jpg differ
diff --git a/public/VENEU/Veneu9.jpg b/public/VENEU/Veneu9.jpg
new file mode 100644
index 0000000..d016d81
Binary files /dev/null and b/public/VENEU/Veneu9.jpg differ
diff --git a/public/VENEU/index.tsx b/public/VENEU/index.tsx
new file mode 100644
index 0000000..bad653d
--- /dev/null
+++ b/public/VENEU/index.tsx
@@ -0,0 +1,23 @@
+import Veneu1 from './Veneu1.jpg';
+import Veneu2 from './Veneu2.jpg';
+import Veneu3 from './Veneu3.jpg';
+import Veneu4 from './Veneu4.jpg';
+import Veneu5 from './Veneu5.jpg';
+import Veneu6 from './Veneu6.jpg';
+import Veneu7 from './Veneu7.jpg';
+import Veneu8 from './Veneu8.jpg';
+import Veneu9 from './Veneu9.jpg';
+import Veneu10 from './Veneu10.jpg';
+
+export {
+ Veneu1,
+ Veneu2,
+ Veneu3,
+ Veneu4,
+ Veneu5,
+ Veneu6,
+ Veneu7,
+ Veneu8,
+ Veneu9,
+ Veneu10,
+};
diff --git a/public/folder.png b/public/folder.png
new file mode 100644
index 0000000..3b1e263
Binary files /dev/null and b/public/folder.png differ
diff --git a/public/partner/bpd.png b/public/partner/bpd.png
new file mode 100644
index 0000000..b83ad03
Binary files /dev/null and b/public/partner/bpd.png differ
diff --git a/public/partner/motion.jpg b/public/partner/motion.jpg
new file mode 100644
index 0000000..de9eff3
Binary files /dev/null and b/public/partner/motion.jpg differ
diff --git a/public/partner/pemkabbangli.png b/public/partner/pemkabbangli.png
new file mode 100644
index 0000000..0f051fc
Binary files /dev/null and b/public/partner/pemkabbangli.png differ
diff --git a/public/partner/porserosi.png b/public/partner/porserosi.png
new file mode 100644
index 0000000..d3a7d70
Binary files /dev/null and b/public/partner/porserosi.png differ
diff --git a/public/partner/skateboardingsocial.png b/public/partner/skateboardingsocial.png
new file mode 100644
index 0000000..713195c
Binary files /dev/null and b/public/partner/skateboardingsocial.png differ
diff --git a/public/partner/vase.png b/public/partner/vase.png
new file mode 100644
index 0000000..0e53cab
Binary files /dev/null and b/public/partner/vase.png differ
diff --git a/public/partner/wandering.jpg b/public/partner/wandering.jpg
new file mode 100644
index 0000000..fb10cbf
Binary files /dev/null and b/public/partner/wandering.jpg differ
diff --git a/public/poster.jpeg b/public/poster.jpeg
new file mode 100644
index 0000000..382a779
Binary files /dev/null and b/public/poster.jpeg differ
diff --git a/src/app/globals.css b/src/app/globals.css
index 875c01e..2801bab 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -2,32 +2,85 @@
@tailwind components;
@tailwind utilities;
-:root {
- --foreground-rgb: 0, 0, 0;
- --background-start-rgb: 214, 219, 220;
- --background-end-rgb: 255, 255, 255;
-}
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 0 0% 3.9%;
-@media (prefers-color-scheme: dark) {
- :root {
- --foreground-rgb: 255, 255, 255;
- --background-start-rgb: 0, 0, 0;
- --background-end-rgb: 0, 0, 0;
- }
-}
+ --card: 0 0% 100%;
+ --card-foreground: 0 0% 3.9%;
+
+ --popover: 0 0% 100%;
+ --popover-foreground: 0 0% 3.9%;
+
+ --primary: 0 0% 9%;
+ --primary-foreground: 0 0% 98%;
+
+ --secondary: 0 0% 96.1%;
+ --secondary-foreground: 0 0% 9%;
+
+ --muted: 0 0% 96.1%;
+ --muted-foreground: 0 0% 45.1%;
+
+ --accent: 0 0% 96.1%;
+ --accent-foreground: 0 0% 9%;
+
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 0 0% 98%;
+
+ --border: 0 0% 89.8%;
+ --input: 0 0% 89.8%;
+ --ring: 0 0% 3.9%;
+
+ --radius: 0.5rem;
+ }
-body {
- color: rgb(var(--foreground-rgb));
- background: linear-gradient(
- to bottom,
- transparent,
- rgb(var(--background-end-rgb))
- )
- rgb(var(--background-start-rgb));
+ .dark {
+ --background: 0 0% 3.9%;
+ --foreground: 0 0% 98%;
+
+ --card: 0 0% 3.9%;
+ --card-foreground: 0 0% 98%;
+
+ --popover: 0 0% 3.9%;
+ --popover-foreground: 0 0% 98%;
+
+ --primary: 0 0% 98%;
+ --primary-foreground: 0 0% 9%;
+
+ --secondary: 0 0% 14.9%;
+ --secondary-foreground: 0 0% 98%;
+
+ --muted: 0 0% 14.9%;
+ --muted-foreground: 0 0% 63.9%;
+
+ --accent: 0 0% 14.9%;
+ --accent-foreground: 0 0% 98%;
+
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 0 0% 98%;
+
+ --border: 0 0% 14.9%;
+ --input: 0 0% 14.9%;
+ --ring: 0 0% 83.1%;
+ }
}
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-background text-foreground;
+ background-color: #f2f2f2;
+ }
+}
@layer utilities {
- .text-balance {
- text-wrap: balance;
- }
+ .no-scrollbar ::-webkit-scrollbar {
+ display: none;
+ }
+ .no-scrollbar {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+ }
}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 3314e47..6e9a6ec 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,22 +1,28 @@
-import type { Metadata } from "next";
-import { Inter } from "next/font/google";
-import "./globals.css";
+import type { Metadata } from 'next';
+import { Inter } from 'next/font/google';
+import './globals.css';
+import Navbar from '@/components/Navbar';
+import Footer from '@/components/Footer';
-const inter = Inter({ subsets: ["latin"] });
+const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
+ title: 'Create Next App',
+ description: 'Generated by create next app',
};
export default function RootLayout({
- children,
+ children,
}: Readonly<{
- children: React.ReactNode;
+ children: React.ReactNode;
}>) {
- return (
-
-
{children}
-
- );
+ return (
+
+
+
+ {children}
+
+
+
+ );
}
diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx
new file mode 100644
index 0000000..20c2168
--- /dev/null
+++ b/src/app/login/page.tsx
@@ -0,0 +1,51 @@
+'use client';
+import { Button } from '@/components/ui/button';
+import {
+ Card,
+ CardContent,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from '@/components/ui/card';
+import { Form, FormControl, FormItem, FormLabel } from '@/components/ui/form';
+import { Input } from '@/components/ui/input';
+import { Label } from '@/components/ui/label';
+
+export default function Page() {
+ return (
+
+
+
+
+ LOGIN BUPATI CUP
+ SKATEBOARD COMPETITION II
+
+
+
+
+ email
+
+
+
+ password
+
+
+
+
+
+ Forgot your Password? RESET PASSWORD
+
+ sign in
+
+ sign up
+
+
+ Don't have an account yet? Create Now!
+
+
+
+
+ );
+}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index b81507d..bb3febd 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,113 +1,14 @@
-import Image from "next/image";
-
-export default function Home() {
- return (
-
-
-
- Get started by editing
- src/app/page.tsx
-
-
-
-
-
-
-
-
-
-
- );
+import Gallery from '@/components/Section/Gallery';
+import Hero from '@/components/Section/Hero';
+import Home from '@/components/Section/Home';
+import Thanks from '@/components/Section/Thanks';
+export default function Page() {
+ return (
+
+
+
+
+
+
+ );
}
diff --git a/src/components/Conditional.tsx b/src/components/Conditional.tsx
new file mode 100644
index 0000000..e0a9a34
--- /dev/null
+++ b/src/components/Conditional.tsx
@@ -0,0 +1,10 @@
+import React from 'react';
+interface IFProps {
+ state: boolean;
+ children: React.ReactNode;
+ elseCondition: React.ReactNode;
+}
+const IF: React.FC = ({ state, children, elseCondition }) => {
+ return state ? children : elseCondition;
+};
+export { IF };
diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx
new file mode 100644
index 0000000..5d3c7ad
--- /dev/null
+++ b/src/components/Footer.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+
+const Footer = () => {
+ return (
+
+ );
+};
+
+export default Footer;
diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx
new file mode 100644
index 0000000..e89870a
--- /dev/null
+++ b/src/components/Navbar.tsx
@@ -0,0 +1,29 @@
+import Link from 'next/link';
+import React from 'react';
+
+const Line = () => {
+ return ;
+};
+const Navbar = () => {
+ return (
+
+ );
+};
+
+export default Navbar;
diff --git a/src/components/Section/Gallery.tsx b/src/components/Section/Gallery.tsx
new file mode 100644
index 0000000..e2934ef
--- /dev/null
+++ b/src/components/Section/Gallery.tsx
@@ -0,0 +1,37 @@
+'use client';
+import React from 'react';
+import { Carousel, CarouselContent, CarouselItem } from '../ui/carousel';
+import Image from 'next/image';
+import { IF } from '../Conditional';
+import Terminal from './Terminal';
+const Gallery = () => {
+ const [popUp, setPopUp] = React.useState(false);
+ function popUpModal() {
+ setPopUp((prev) => !prev);
+ }
+ return (
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+ veneu
+
+ ))}
+
+
+
+
+ );
+};
+
+export default Gallery;
diff --git a/src/components/Section/Hero.tsx b/src/components/Section/Hero.tsx
new file mode 100644
index 0000000..1303f69
--- /dev/null
+++ b/src/components/Section/Hero.tsx
@@ -0,0 +1,16 @@
+import Image from 'next/image';
+import React from 'react';
+import HomeMarquee from './HomeMarquee';
+
+const Hero = () => {
+ const date = new Date();
+
+ return (
+
+ Prologue
+ {date.toUTCString()}
+
+ );
+};
+
+export default Hero;
diff --git a/src/components/Section/Home.tsx b/src/components/Section/Home.tsx
new file mode 100644
index 0000000..356fc6f
--- /dev/null
+++ b/src/components/Section/Home.tsx
@@ -0,0 +1,50 @@
+import React from 'react';
+import Image from 'next/image';
+import Marquee from 'react-fast-marquee';
+import HomeMarquee from './HomeMarquee';
+import Link from 'next/link';
+const text = {
+ one: 'We are part of the PSB (Persatuan Skateboarders Bali), an official organization that accommodates the skateboard community in the Bangli area (PSB Bangli) under the auspices of PSB, which accommodates all skateboard communities in Bali. PSB Bangli was formed and built by people who have a passion and a strong desire to develop extreme sports in the Bangli area, especially skateboarding, so that the potential of young people who love skateboarding can be channeled better and directed, so that the existing potential can be developed into achievements that will later make the name of the region, nation, and country proud in this field of sports.',
+ two: 'With the success of the Bupati Cup Competition I event last year, we want to continue this positive event as an annual event that is always eagerly awaited by the entire skateboard community in Bali in general. With a sustainable event, our hope as regional managers is to be able to grow and develop skateboarding as a new alternative sport for the young generation of Bangli and Bali in carrying out their creative activities towards achievements where skateboarding has been recognized by the world as a sport of achievement that has entered official competitions both from Extreme Games, SEA Games, ASIAN Games and Olympiad. The support that has been given to our activities is the spirit that drives us to remain active and strive to give our best to build potential for successful skateboard athletes who can bring pride and honor to Kabupaten Bangli in local, national, and even international events as our biggest target to achieve in the future.',
+};
+const Home = () => {
+ return (
+
+
+
+ Bupati Cup Skateboard Competition
+
+ II
+
+
+ Bangli, Bali, Indonesia
+
+
+ Agust 25 - 27, 2023
+
+
+ -8.462643, 115.353366
+
+
+ L
+
+
+
+
+ background
+
+
+ {text.one}
+ {text.two}
+
+
+
+
+
+
+ );
+};
+
+export default Home;
diff --git a/src/components/Section/HomeMarquee.tsx b/src/components/Section/HomeMarquee.tsx
new file mode 100644
index 0000000..8aece41
--- /dev/null
+++ b/src/components/Section/HomeMarquee.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import Marquee from 'react-fast-marquee';
+interface Props {
+ direction?: 'left' | 'right' | 'up' | 'down';
+}
+const HomeMarquee: React.FC = ({ direction = 'right' }) => {
+ return (
+
+ bupati cup#2
+ skateboard competition ii
+ Bangli, Bali, Indonesia
+ August 25 - 27, 2023
+ bupati cup#2
+
+ );
+};
+
+export default HomeMarquee;
diff --git a/src/components/Section/Terminal.tsx b/src/components/Section/Terminal.tsx
new file mode 100644
index 0000000..03dbaac
--- /dev/null
+++ b/src/components/Section/Terminal.tsx
@@ -0,0 +1,129 @@
+import Image from 'next/image';
+import React from 'react';
+interface Props {
+ popUpModal: () => void;
+}
+const Terminal: React.FC = ({ popUpModal }) => {
+ const buttonHeaderRef = React.useRef(null);
+ const [miniMize, setMiniMize] = React.useState(false);
+ function miniMizePopUo() {
+ setMiniMize((prev) => !prev);
+ }
+ return (
+
+
+
+
+
+ bangli skatepark
+
+
+
+
+
+
+ bupati cup skateboard competition i
+
+
+ Lorem ipsum dolor sit, amet consectetur adipisicing elit.
+ Perferendis commodi velit quos doloribus error autem
+ architecto unde officiis distinctio eaque, excepturi amet
+ reiciendis explicabo. Aliquam est perspiciatis reprehenderit
+ consectetur enim. Reiciendis minus aliquam aliquid, cumque
+ molestiae esse mollitia nam numquam quia cum ex eum
+ similique a hic natus rerum omnis temporibus optio accusamus
+ nesciunt architecto illo! Dolore totam sint amet.
+ Necessitatibus, eos quam totam officia, sapiente illum
+ corrupti dolor, mollitia fuga amet obcaecati ab distinctio
+ eaque quos odio. Vel quasi commodi dignissimos voluptatem
+ voluptatibus magni aperiam earum facilis fugiat veniam.
+ Consequuntur in voluptatibus reiciendis doloribus, totam ad
+ dolores magni facere voluptates ratione aliquam odio illum,
+ optio voluptatum, quidem ipsa laborum similique a at nihil!
+ Esse, minima molestias? Magni, natus facilis? Soluta
+ voluptates architecto explicabo dolorum corrupti recusandae
+ incidunt tenetur quam maxime provident eius consectetur
+ delectus laborum iusto quae veniam nam non officiis culpa
+ voluptas, sunt repudiandae esse odit facilis? Cum? Inventore
+ veniam pariatur sequi voluptates asperiores aliquam rem
+ eligendi hic consequatur molestias, excepturi cum alias iure
+ eos iste impedit totam nostrum quidem? Obcaecati alias earum
+ eum velit autem molestiae quod? Praesentium cumque aliquam
+ aut suscipit, ab ad consequatur hic, doloribus vero,
+ cupiditate deserunt porro dicta quasi voluptatem iste et.
+ Ratione, laborum accusamus. Excepturi, corporis provident
+ doloribus aliquam ex illum incidunt. Optio magnam
+ exercitationem qui a nesciunt ullam odio sit minus nisi! Ab
+ natus minus amet voluptatem incidunt voluptates voluptatibus
+ delectus omnis quae perferendis doloribus placeat eveniet,
+ neque illo id nam. Reprehenderit ratione adipisci quisquam,
+ minus esse optio similique et ipsum quos nesciunt cumque.
+ Temporibus cumque deserunt labore accusamus amet. Voluptates
+ repellat sint ex consectetur minima voluptatem possimus
+ consequuntur sapiente sunt. Perspiciatis, officiis.
+ Doloribus nam labore consectetur eius, perspiciatis
+ architecto non! Totam sunt et facere vitae exercitationem
+ odio similique ad eius ipsum. Repudiandae asperiores
+ adipisci sunt! Voluptates cum ratione dolores nulla! Iusto
+ tempore blanditiis placeat maiores expedita omnis dolor
+ neque odio sit provident aut quibusdam cum dignissimos,
+ odit, impedit voluptatibus atque aspernatur illum fugit
+ explicabo repellat dicta? Dicta harum doloremque fugit! Quam
+ temporibus est quaerat. Aut officiis, culpa quisquam
+ laboriosam consequuntur quae at vero temporibus! Nihil,
+ dignissimos! Provident aliquam quisquam obcaecati. Officiis
+ a soluta dolorem voluptate molestiae animi? Dicta, ratione.
+ Rem. Facere repellendus delectus obcaecati quod voluptates
+ suscipit fuga, pariatur quidem enim debitis aliquam adipisci
+ rem omnis repudiandae vitae reprehenderit totam? Nostrum
+ tenetur beatae vitae, nobis in modi assumenda illo ab.
+ Tenetur, adipisci consequatur consectetur magni amet
+ perspiciatis totam? Beatae provident qui alias! Iusto amet
+ deleniti temporibus quae, magnam illo officiis accusantium
+ reprehenderit molestiae quos est accusamus ratione! Dicta,
+ id amet! Ab officiis aliquam facere, deserunt eveniet dolore
+ architecto debitis tempora esse voluptate molestias
+ perspiciatis quibusdam, aperiam minus! Placeat praesentium
+ repellat aliquid reiciendis quisquam tempora aspernatur,
+ sequi perspiciatis ratione consequuntur cumque. At sit
+ laborum in, ratione pariatur molestiae odit magni sed dolore
+ fugit consectetur praesentium soluta fuga tempora esse
+ placeat nostrum ipsam laboriosam debitis? Eveniet error
+ laboriosam, deleniti numquam harum labore. Ut neque ipsa
+ deserunt quod mollitia laboriosam magnam, ea, placeat
+ dolores aut ex beatae quisquam cum praesentium eligendi
+ porro atque, suscipit natus est perspiciatis! Nostrum sit
+ culpa voluptas consectetur totam? Soluta illo aliquid
+ laborum consectetur sint ex voluptates labore obcaecati
+ voluptatibus, perferendis molestiae itaque maxime amet
+ beatae mollitia quasi nesciunt modi! Qui animi
+ exercitationem, dolores omnis aliquam beatae accusamus
+ quidem. Explicabo nulla magni, voluptatum labore ea totam
+ qui aliquid architecto ipsam quis quae recusandae ullam quam
+ consequuntur, atque, impedit fugiat eius eveniet vero illo
+ libero veritatis corporis? Fugiat, neque ad! Sunt
+ reprehenderit minus provident dicta voluptas. Fugiat aliquam
+ illum voluptas eos atque iusto. Sit, libero? Natus ad quae
+ aperiam explicabo modi, tempora corporis illum repudiandae
+ architecto ut perspiciatis quisquam nemo.
+
+
+
+ );
+};
+
+export default Terminal;
diff --git a/src/components/Section/Thanks.tsx b/src/components/Section/Thanks.tsx
new file mode 100644
index 0000000..e8c19a0
--- /dev/null
+++ b/src/components/Section/Thanks.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+
+const Thanks = () => {
+ return (
+
+ Thanks to our partner
+ Thanks to our media
+
+ );
+};
+
+export default Thanks;
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx
new file mode 100644
index 0000000..0ba4277
--- /dev/null
+++ b/src/components/ui/button.tsx
@@ -0,0 +1,56 @@
+import * as React from "react"
+import { Slot } from "@radix-ui/react-slot"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline:
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-10 px-4 py-2",
+ sm: "h-9 rounded-md px-3",
+ lg: "h-11 rounded-md px-8",
+ icon: "h-10 w-10",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button"
+ return (
+
+ )
+ }
+)
+Button.displayName = "Button"
+
+export { Button, buttonVariants }
diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx
new file mode 100644
index 0000000..afa13ec
--- /dev/null
+++ b/src/components/ui/card.tsx
@@ -0,0 +1,79 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+Card.displayName = "Card"
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardHeader.displayName = "CardHeader"
+
+const CardTitle = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardTitle.displayName = "CardTitle"
+
+const CardDescription = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardDescription.displayName = "CardDescription"
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardContent.displayName = "CardContent"
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardFooter.displayName = "CardFooter"
+
+export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
diff --git a/src/components/ui/carousel.tsx b/src/components/ui/carousel.tsx
new file mode 100644
index 0000000..ec505d0
--- /dev/null
+++ b/src/components/ui/carousel.tsx
@@ -0,0 +1,262 @@
+"use client"
+
+import * as React from "react"
+import useEmblaCarousel, {
+ type UseEmblaCarouselType,
+} from "embla-carousel-react"
+import { ArrowLeft, ArrowRight } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+import { Button } from "@/components/ui/button"
+
+type CarouselApi = UseEmblaCarouselType[1]
+type UseCarouselParameters = Parameters
+type CarouselOptions = UseCarouselParameters[0]
+type CarouselPlugin = UseCarouselParameters[1]
+
+type CarouselProps = {
+ opts?: CarouselOptions
+ plugins?: CarouselPlugin
+ orientation?: "horizontal" | "vertical"
+ setApi?: (api: CarouselApi) => void
+}
+
+type CarouselContextProps = {
+ carouselRef: ReturnType[0]
+ api: ReturnType[1]
+ scrollPrev: () => void
+ scrollNext: () => void
+ canScrollPrev: boolean
+ canScrollNext: boolean
+} & CarouselProps
+
+const CarouselContext = React.createContext(null)
+
+function useCarousel() {
+ const context = React.useContext(CarouselContext)
+
+ if (!context) {
+ throw new Error("useCarousel must be used within a ")
+ }
+
+ return context
+}
+
+const Carousel = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes & CarouselProps
+>(
+ (
+ {
+ orientation = "horizontal",
+ opts,
+ setApi,
+ plugins,
+ className,
+ children,
+ ...props
+ },
+ ref
+ ) => {
+ const [carouselRef, api] = useEmblaCarousel(
+ {
+ ...opts,
+ axis: orientation === "horizontal" ? "x" : "y",
+ },
+ plugins
+ )
+ const [canScrollPrev, setCanScrollPrev] = React.useState(false)
+ const [canScrollNext, setCanScrollNext] = React.useState(false)
+
+ const onSelect = React.useCallback((api: CarouselApi) => {
+ if (!api) {
+ return
+ }
+
+ setCanScrollPrev(api.canScrollPrev())
+ setCanScrollNext(api.canScrollNext())
+ }, [])
+
+ const scrollPrev = React.useCallback(() => {
+ api?.scrollPrev()
+ }, [api])
+
+ const scrollNext = React.useCallback(() => {
+ api?.scrollNext()
+ }, [api])
+
+ const handleKeyDown = React.useCallback(
+ (event: React.KeyboardEvent) => {
+ if (event.key === "ArrowLeft") {
+ event.preventDefault()
+ scrollPrev()
+ } else if (event.key === "ArrowRight") {
+ event.preventDefault()
+ scrollNext()
+ }
+ },
+ [scrollPrev, scrollNext]
+ )
+
+ React.useEffect(() => {
+ if (!api || !setApi) {
+ return
+ }
+
+ setApi(api)
+ }, [api, setApi])
+
+ React.useEffect(() => {
+ if (!api) {
+ return
+ }
+
+ onSelect(api)
+ api.on("reInit", onSelect)
+ api.on("select", onSelect)
+
+ return () => {
+ api?.off("select", onSelect)
+ }
+ }, [api, onSelect])
+
+ return (
+
+
+ {children}
+
+
+ )
+ }
+)
+Carousel.displayName = "Carousel"
+
+const CarouselContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => {
+ const { carouselRef, orientation } = useCarousel()
+
+ return (
+
+ )
+})
+CarouselContent.displayName = "CarouselContent"
+
+const CarouselItem = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => {
+ const { orientation } = useCarousel()
+
+ return (
+
+ )
+})
+CarouselItem.displayName = "CarouselItem"
+
+const CarouselPrevious = React.forwardRef<
+ HTMLButtonElement,
+ React.ComponentProps
+>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
+ const { orientation, scrollPrev, canScrollPrev } = useCarousel()
+
+ return (
+
+
+ Previous slide
+
+ )
+})
+CarouselPrevious.displayName = "CarouselPrevious"
+
+const CarouselNext = React.forwardRef<
+ HTMLButtonElement,
+ React.ComponentProps
+>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
+ const { orientation, scrollNext, canScrollNext } = useCarousel()
+
+ return (
+
+
+ Next slide
+
+ )
+})
+CarouselNext.displayName = "CarouselNext"
+
+export {
+ type CarouselApi,
+ Carousel,
+ CarouselContent,
+ CarouselItem,
+ CarouselPrevious,
+ CarouselNext,
+}
diff --git a/src/components/ui/form.tsx b/src/components/ui/form.tsx
new file mode 100644
index 0000000..4603f8b
--- /dev/null
+++ b/src/components/ui/form.tsx
@@ -0,0 +1,176 @@
+import * as React from "react"
+import * as LabelPrimitive from "@radix-ui/react-label"
+import { Slot } from "@radix-ui/react-slot"
+import {
+ Controller,
+ ControllerProps,
+ FieldPath,
+ FieldValues,
+ FormProvider,
+ useFormContext,
+} from "react-hook-form"
+
+import { cn } from "@/lib/utils"
+import { Label } from "@/components/ui/label"
+
+const Form = FormProvider
+
+type FormFieldContextValue<
+ TFieldValues extends FieldValues = FieldValues,
+ TName extends FieldPath = FieldPath
+> = {
+ name: TName
+}
+
+const FormFieldContext = React.createContext(
+ {} as FormFieldContextValue
+)
+
+const FormField = <
+ TFieldValues extends FieldValues = FieldValues,
+ TName extends FieldPath = FieldPath
+>({
+ ...props
+}: ControllerProps) => {
+ return (
+
+
+
+ )
+}
+
+const useFormField = () => {
+ const fieldContext = React.useContext(FormFieldContext)
+ const itemContext = React.useContext(FormItemContext)
+ const { getFieldState, formState } = useFormContext()
+
+ const fieldState = getFieldState(fieldContext.name, formState)
+
+ if (!fieldContext) {
+ throw new Error("useFormField should be used within ")
+ }
+
+ const { id } = itemContext
+
+ return {
+ id,
+ name: fieldContext.name,
+ formItemId: `${id}-form-item`,
+ formDescriptionId: `${id}-form-item-description`,
+ formMessageId: `${id}-form-item-message`,
+ ...fieldState,
+ }
+}
+
+type FormItemContextValue = {
+ id: string
+}
+
+const FormItemContext = React.createContext(
+ {} as FormItemContextValue
+)
+
+const FormItem = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => {
+ const id = React.useId()
+
+ return (
+
+
+
+ )
+})
+FormItem.displayName = "FormItem"
+
+const FormLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => {
+ const { error, formItemId } = useFormField()
+
+ return (
+
+ )
+})
+FormLabel.displayName = "FormLabel"
+
+const FormControl = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ ...props }, ref) => {
+ const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
+
+ return (
+
+ )
+})
+FormControl.displayName = "FormControl"
+
+const FormDescription = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => {
+ const { formDescriptionId } = useFormField()
+
+ return (
+
+ )
+})
+FormDescription.displayName = "FormDescription"
+
+const FormMessage = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, children, ...props }, ref) => {
+ const { error, formMessageId } = useFormField()
+ const body = error ? String(error?.message) : children
+
+ if (!body) {
+ return null
+ }
+
+ return (
+
+ {body}
+
+ )
+})
+FormMessage.displayName = "FormMessage"
+
+export {
+ useFormField,
+ Form,
+ FormItem,
+ FormLabel,
+ FormControl,
+ FormDescription,
+ FormMessage,
+ FormField,
+}
diff --git a/src/components/ui/input-label.tsx b/src/components/ui/input-label.tsx
new file mode 100644
index 0000000..40b4fd5
--- /dev/null
+++ b/src/components/ui/input-label.tsx
@@ -0,0 +1,13 @@
+import { Input } from './input';
+import { Label } from './label';
+
+const InputLabel = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default InputLabel;
diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx
new file mode 100644
index 0000000..1286716
--- /dev/null
+++ b/src/components/ui/input.tsx
@@ -0,0 +1,25 @@
+import * as React from 'react';
+
+import { cn } from '@/lib/utils';
+
+export interface InputProps
+ extends React.InputHTMLAttributes {}
+
+const Input = React.forwardRef(
+ ({ className, type, ...props }, ref) => {
+ return (
+
+ );
+ }
+);
+Input.displayName = 'Input';
+
+export { Input };
diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx
new file mode 100644
index 0000000..5341821
--- /dev/null
+++ b/src/components/ui/label.tsx
@@ -0,0 +1,26 @@
+"use client"
+
+import * as React from "react"
+import * as LabelPrimitive from "@radix-ui/react-label"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const labelVariants = cva(
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
+)
+
+const Label = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef &
+ VariantProps
+>(({ className, ...props }, ref) => (
+
+))
+Label.displayName = LabelPrimitive.Root.displayName
+
+export { Label }
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
new file mode 100644
index 0000000..d084cca
--- /dev/null
+++ b/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { type ClassValue, clsx } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}
diff --git a/tailwind.config.ts b/tailwind.config.ts
index e9a0944..84287e8 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -1,20 +1,80 @@
-import type { Config } from "tailwindcss";
+import type { Config } from "tailwindcss"
-const config: Config = {
+const config = {
+ darkMode: ["class"],
content: [
- "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
- "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
- "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
- ],
+ './pages/**/*.{ts,tsx}',
+ './components/**/*.{ts,tsx}',
+ './app/**/*.{ts,tsx}',
+ './src/**/*.{ts,tsx}',
+ ],
+ prefix: "",
theme: {
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
+ },
extend: {
- backgroundImage: {
- "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
- "gradient-conic":
- "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
+ colors: {
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
+ primary: {
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))",
+ },
+ },
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ keyframes: {
+ "accordion-down": {
+ from: { height: "0" },
+ to: { height: "var(--radix-accordion-content-height)" },
+ },
+ "accordion-up": {
+ from: { height: "var(--radix-accordion-content-height)" },
+ to: { height: "0" },
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
},
},
},
- plugins: [],
-};
-export default config;
+ plugins: [require("tailwindcss-animate")],
+} satisfies Config
+
+export default config
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 5e798b6..7c81b92 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7,6 +7,18 @@
resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
+"@babel/runtime@^7.13.10", "@babel/runtime@^7.23.7":
+ version "7.23.9"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7"
+ integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
+"@hookform/resolvers@^3.3.4":
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-3.3.4.tgz#de9b668c2835eb06892290192de6e2a5c906229b"
+ integrity sha512-o5cgpGOuJYrd+iMKvkttOclgwRW86EsWJZZRC23prf0uU2i48Htq4PuT73AVb9ionFyZrwYEITuOFGF+BydEtQ==
+
"@isaacs/cliui@^8.0.2":
version "8.0.2"
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
@@ -127,6 +139,37 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
+"@radix-ui/react-compose-refs@1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989"
+ integrity sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+
+"@radix-ui/react-label@^2.0.2":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.0.2.tgz#9c72f1d334aac996fdc27b48a8bdddd82108fb6d"
+ integrity sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/react-primitive" "1.0.3"
+
+"@radix-ui/react-primitive@1.0.3":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0"
+ integrity sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/react-slot" "1.0.2"
+
+"@radix-ui/react-slot@1.0.2", "@radix-ui/react-slot@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab"
+ integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/react-compose-refs" "1.0.1"
+
"@swc/helpers@0.5.2":
version "0.5.2"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d"
@@ -285,11 +328,28 @@ chokidar@^3.5.3:
optionalDependencies:
fsevents "~2.3.2"
+class-variance-authority@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522"
+ integrity sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==
+ dependencies:
+ clsx "2.0.0"
+
client-only@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
+clsx@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b"
+ integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==
+
+clsx@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb"
+ integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==
+
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
@@ -346,6 +406,24 @@ electron-to-chromium@^1.4.648:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz#c7b46c9010752c37bb4322739d6d2dd82354fbe4"
integrity sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==
+embla-carousel-react@^8.0.0-rc22:
+ version "8.0.0-rc22"
+ resolved "https://registry.yarnpkg.com/embla-carousel-react/-/embla-carousel-react-8.0.0-rc22.tgz#cc017e5c370663a9517fa46fba55ea7ad1df5e17"
+ integrity sha512-NwmISV0Cw9XVo76Vquz3hJaeZe7qoCRtrzStxlEY7qfZD8WR/f4JlQAso35URTs1BeYVhcuClflelioo+Zmidg==
+ dependencies:
+ embla-carousel "8.0.0-rc22"
+ embla-carousel-reactive-utils "8.0.0-rc22"
+
+embla-carousel-reactive-utils@8.0.0-rc22:
+ version "8.0.0-rc22"
+ resolved "https://registry.yarnpkg.com/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.0.0-rc22.tgz#de40e32d684487b4635bd9cdef23b3c5c7c599d6"
+ integrity sha512-K4b8QhQGXYW5wr4l+U6XryhafsFV5c/IyohDnZN3MGoYIB9xY7qpjUWAcs5bTDjAD+qCZPOuXre0D3IVa28mqw==
+
+embla-carousel@8.0.0-rc22:
+ version "8.0.0-rc22"
+ resolved "https://registry.yarnpkg.com/embla-carousel/-/embla-carousel-8.0.0-rc22.tgz#f5e4447636dce317ae066138a45abe77e08bae4a"
+ integrity sha512-MeXnPT1LShfgAu8qXj3CskayV0R6OkHx7w3cPTx+Q5ZWKyShKpIuu7qVQJ5BoFegalE4n6yxqoQaRuGFbK9pYw==
+
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
@@ -439,6 +517,11 @@ graceful-fs@^4.2.11:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+hamburger-react@^2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/hamburger-react/-/hamburger-react-2.5.0.tgz#7c0148af8f02f3b693564d69e590d02db8ffc221"
+ integrity sha512-5GSXe+ucxTPJ0SkhIsPQ/PRDweZPIKya1lfahAuExx31SdheeUA4uOPfQIAirbKona8hvo79VDr5LJQzPXsdpw==
+
hasown@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c"
@@ -533,6 +616,11 @@ loose-envify@^1.1.0:
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3"
integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==
+lucide-react@^0.320.0:
+ version "0.320.0"
+ resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.320.0.tgz#c0be9134bd01619bdbea7d426e4312cc7187aefb"
+ integrity sha512-HuMmfmFiWwctDkN27wklKVZr8UpwP2TTekLZ3xiLCEjx/STG1k0KLWMbBfIJ/lnNJQDfSjztDZSVU316xA+AQg==
+
merge2@^1.3.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
@@ -733,6 +821,16 @@ react-dom@^18:
loose-envify "^1.1.0"
scheduler "^0.23.0"
+react-fast-marquee@^1.6.3:
+ version "1.6.3"
+ resolved "https://registry.yarnpkg.com/react-fast-marquee/-/react-fast-marquee-1.6.3.tgz#a1f3a0ce3b298c395766d19051aa8fa3af9f1a1c"
+ integrity sha512-oEISmNElv6lua/4i4uPYIteUKDxU0hAKKjH/tY2icje4GCns1rX6pIrkwVhjX0FMCIepUVqeyCchvqkiO/s2vw==
+
+react-hook-form@^7.50.0:
+ version "7.50.0"
+ resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.50.0.tgz#379802d85c7b78e0056229c53607946d34f99a36"
+ integrity sha512-AOhuzM3RdP09ZCnq+Z0yvKGHK25yiOX5phwxjV9L7U6HMla10ezkBnvQ+Pk4GTuDfsC5P2zza3k8mawFwFLVuQ==
+
react@^18:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
@@ -754,6 +852,11 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"
+regenerator-runtime@^0.14.0:
+ version "0.14.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
+ integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
+
resolve@^1.1.7, resolve@^1.22.2:
version "1.22.8"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
@@ -810,6 +913,7 @@ streamsearch@^1.1.0:
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
+ name string-width-cjs
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -828,6 +932,7 @@ string-width@^5.0.1, string-width@^5.1.2:
strip-ansi "^7.0.1"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ name strip-ansi-cjs
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -866,6 +971,18 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+tailwind-merge@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.2.1.tgz#3f10f296a2dba1d88769de8244fafd95c3324aeb"
+ integrity sha512-o+2GTLkthfa5YUt4JxPfzMIpQzZ3adD1vLVkvKE1Twl9UAhGsEbIZhHHZVRttyW177S8PDJI3bTQNaebyofK3Q==
+ dependencies:
+ "@babel/runtime" "^7.23.7"
+
+tailwindcss-animate@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4"
+ integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==
+
tailwindcss@^3.3.0:
version "3.4.1"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.1.tgz#f512ca5d1dd4c9503c7d3d28a968f1ad8f5c839d"
@@ -977,3 +1094,8 @@ yaml@^2.3.4:
version "2.3.4"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2"
integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==
+
+zod@^3.22.4:
+ version "3.22.4"
+ resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"
+ integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==