@promakeai/cli 0.0.5 → 0.0.6
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/dist/index.js +214 -135
- package/dist/registry/about-page.json +1 -1
- package/dist/registry/about-section.json +1 -1
- package/dist/registry/api.json +55 -0
- package/dist/registry/auth.json +70 -0
- package/dist/registry/bento-grid-section.json +1 -1
- package/dist/registry/blog-list-page.json +1 -1
- package/dist/registry/blog-section.json +1 -1
- package/dist/registry/cart-drawer.json +1 -1
- package/dist/registry/cart-page.json +3 -2
- package/dist/registry/category-section.json +1 -1
- package/dist/registry/checkout-page.json +3 -2
- package/dist/registry/contact-info-grid.json +1 -1
- package/dist/registry/contact-page-centered.json +1 -1
- package/dist/registry/contact-page-map-overlay.json +1 -1
- package/dist/registry/contact-page.json +1 -1
- package/dist/registry/cookies-page.json +1 -1
- package/dist/registry/cta-section.json +1 -1
- package/dist/registry/db.json +129 -0
- package/dist/registry/docs/cart-page.md +1 -0
- package/dist/registry/docs/checkout-page.md +1 -0
- package/dist/registry/docs/forgot-password-page.md +37 -0
- package/dist/registry/docs/header-ecommerce.md +1 -0
- package/dist/registry/docs/products-page.md +1 -0
- package/dist/registry/docs/register-page.md +39 -0
- package/dist/registry/ecommerce-core.json +1 -1
- package/dist/registry/empty-page.json +1 -1
- package/dist/registry/faq-categorized.json +1 -1
- package/dist/registry/faq-simple.json +1 -1
- package/dist/registry/favorites-blog-block.json +1 -1
- package/dist/registry/favorites-ecommerce-block.json +1 -1
- package/dist/registry/feature-section.json +1 -1
- package/dist/registry/featured-products.json +1 -1
- package/dist/registry/footer-detailed.json +1 -1
- package/dist/registry/footer-minimal.json +3 -3
- package/dist/registry/footer.json +1 -1
- package/dist/registry/forgot-password-page.json +49 -0
- package/dist/registry/header-ecommerce.json +3 -2
- package/dist/registry/header-mega.json +1 -1
- package/dist/registry/header-minimal.json +1 -1
- package/dist/registry/header-simple.json +1 -1
- package/dist/registry/hero-cta.json +1 -1
- package/dist/registry/hero-gradient.json +1 -1
- package/dist/registry/hero-profile.json +1 -1
- package/dist/registry/hero.json +1 -1
- package/dist/registry/index.json +3 -0
- package/dist/registry/orders-list-block.json +1 -1
- package/dist/registry/payment-success-block.json +1 -1
- package/dist/registry/post-detail-block.json +1 -1
- package/dist/registry/pricing-section.json +1 -1
- package/dist/registry/privacy-page.json +1 -1
- package/dist/registry/products-page.json +3 -2
- package/dist/registry/register-page.json +49 -0
- package/dist/registry/related-posts-block.json +1 -1
- package/dist/registry/terms-page.json +1 -1
- package/dist/registry/testimonials-carousel.json +1 -1
- package/dist/registry/testimonials-grid.json +1 -1
- package/package.json +1 -1
- package/template/src/App.tsx +3 -24
- package/template/src/components/Layout.tsx +0 -4
- package/template/src/index.css +1 -0
- package/template/src/lang/en/index.json +1 -28
- package/template/src/lang/tr/index.json +1 -28
- package/template/src/pages/Index.tsx +1 -102
- package/template/src/components/Footer.tsx +0 -100
- package/template/src/components/Header.tsx +0 -79
- package/template/src/components/Hero.tsx +0 -69
- package/template/src/modules/api/USAGE.md +0 -515
- package/template/src/modules/api/customer-client.ts +0 -20
- package/template/src/modules/api/get-error-message.ts +0 -18
- package/template/src/modules/api/validation/en.json +0 -29
- package/template/src/modules/api/validation/tr.json +0 -29
- package/template/src/modules/auth/USAGE.md +0 -248
- package/template/src/modules/auth/auth-header-menu.tsx +0 -123
- package/template/src/modules/auth/auth-store.ts +0 -57
- package/template/src/modules/auth/forgot-password-page.tsx +0 -371
- package/template/src/modules/auth/login-page.tsx +0 -183
- package/template/src/modules/auth/register-page.tsx +0 -252
- package/template/src/modules/auth/use-auth.ts +0 -273
- package/template/src/modules/db/adapters/IDataAdapter.ts +0 -26
- package/template/src/modules/db/adapters/SqliteAdapter.ts +0 -364
- package/template/src/modules/db/adapters/index.ts +0 -2
- package/template/src/modules/db/config.ts +0 -59
- package/template/src/modules/db/core/DataManager.ts +0 -125
- package/template/src/modules/db/core/types.ts +0 -101
- package/template/src/modules/db/index.ts +0 -42
- package/template/src/modules/db/react/QueryProvider.tsx +0 -16
- package/template/src/modules/db/react/index.ts +0 -23
- package/template/src/modules/db/react/queryClient.ts +0 -64
- package/template/src/modules/db/react/useRepository.ts +0 -400
- package/template/src/modules/db/utils/parsers.ts +0 -96
|
@@ -16,19 +16,19 @@
|
|
|
16
16
|
"path": "footer-minimal/footer-minimal.tsx",
|
|
17
17
|
"type": "registry:component",
|
|
18
18
|
"target": "$modules$/footer-minimal/footer-minimal.tsx",
|
|
19
|
-
"content": "import { useMemo } from \"react\";\nimport { Link } from \"react-router\";\nimport { Facebook, Twitter, Instagram, Linkedin } from \"lucide-react\";\nimport constants from \"@/constants/constants.json\";\nimport { useTranslation } from \"react-i18next\";\n\nconst socialIcons: Record<string, React.ElementType> = {\n facebook: Facebook,\n twitter: Twitter,\n instagram: Instagram,\n linkedin: Linkedin,\n};\n\nexport function FooterMinimal() {\n const { t } = useTranslation(\"footer-minimal\");\n\n const socialLinks = useMemo(() => {\n const socialMedia = constants.socialMedia as Record<string, string> | undefined;\n if (!socialMedia) return [];\n return Object.entries(socialMedia)\n .filter(([platform, url]) => url && socialIcons[platform])\n .map(([platform, url]) => ({ platform, url, Icon: socialIcons[platform] }));\n }, []);\n\n const currentYear = new Date().getFullYear();\n\n return (\n <footer className=\"border-t bg-muted/20\">\n <div className=\"container mx-auto px-4 py-6\">\n <div className=\"flex flex-col md:flex-row items-center justify-between gap-4\">\n {/* Copyright */}\n <p className=\"text-sm text-muted-foreground\">\n © {currentYear} {constants.site.name}\n </p>\n\n {/* Legal Links */}\n <div className=\"flex items-center gap-6\">\n <Link to=\"/privacy\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"privacy\", \"Privacy\")}\n </Link>\n <Link to=\"/terms\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"terms\", \"Terms\")}\n </Link>\n </div>\n\n {/* Social Links */}\n {socialLinks.length > 0 && (\n <div className=\"flex gap-1\">\n {socialLinks.map(({ platform, url, Icon }) => (\n <a\n key={platform}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"h-8 w-8 flex items-center justify-center rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted transition-colors\"\n >\n <Icon className=\"h-4 w-4\" />\n </a>\n ))}\n </div>\n )}\n </div>\n </div>\n </footer>\n );\n}\n"
|
|
19
|
+
"content": "import { useMemo } from \"react\";\nimport { Link } from \"react-router\";\nimport { Facebook, Twitter, Instagram, Linkedin } from \"lucide-react\";\nimport constants from \"@/constants/constants.json\";\nimport { useTranslation } from \"react-i18next\";\n\nconst socialIcons: Record<string, React.ElementType> = {\n facebook: Facebook,\n twitter: Twitter,\n instagram: Instagram,\n linkedin: Linkedin,\n};\n\nexport function FooterMinimal() {\n const { t } = useTranslation(\"footer-minimal\");\n\n const socialLinks = useMemo(() => {\n const socialMedia = constants.socialMedia as Record<string, string> | undefined;\n if (!socialMedia) return [];\n return Object.entries(socialMedia)\n .filter(([platform, url]) => url && socialIcons[platform])\n .map(([platform, url]) => ({ platform, url, Icon: socialIcons[platform] }));\n }, []);\n\n const currentYear = new Date().getFullYear();\n\n return (\n <footer className=\"border-t bg-muted/20\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4 py-6\">\n <div className=\"flex flex-col md:flex-row items-center justify-between gap-4\">\n {/* Copyright */}\n <p className=\"text-sm text-muted-foreground\">\n © {currentYear} {constants.site.name}. {t(\"allRightsReserved\", \"All rights reserved.\")}\n </p>\n\n {/* Legal Links */}\n <div className=\"flex items-center gap-6\">\n <Link to=\"/privacy\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"privacy\", \"Privacy\")}\n </Link>\n <Link to=\"/terms\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"terms\", \"Terms\")}\n </Link>\n </div>\n\n {/* Social Links */}\n {socialLinks.length > 0 && (\n <div className=\"flex gap-1\">\n {socialLinks.map(({ platform, url, Icon }) => (\n <a\n key={platform}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"h-8 w-8 flex items-center justify-center rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted transition-colors\"\n >\n <Icon className=\"h-4 w-4\" />\n </a>\n ))}\n </div>\n )}\n </div>\n </div>\n </footer>\n );\n}\n"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"path": "footer-minimal/lang/en.json",
|
|
23
23
|
"type": "registry:lang",
|
|
24
24
|
"target": "$modules$/footer-minimal/lang/en.json",
|
|
25
|
-
"content": "{\r\n \"privacy\": \"Privacy\",\r\n \"terms\": \"Terms\"\r\n}\r\n"
|
|
25
|
+
"content": "{\r\n \"privacy\": \"Privacy\",\r\n \"terms\": \"Terms\",\r\n \"allRightsReserved\": \"All rights reserved.\"\r\n}\r\n"
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"path": "footer-minimal/lang/tr.json",
|
|
29
29
|
"type": "registry:lang",
|
|
30
30
|
"target": "$modules$/footer-minimal/lang/tr.json",
|
|
31
|
-
"content": "{\r\n \"privacy\": \"Gizlilik\",\r\n \"terms\": \"Şartlar\"\r\n}\r\n"
|
|
31
|
+
"content": "{\r\n \"privacy\": \"Gizlilik\",\r\n \"terms\": \"Şartlar\",\r\n \"allRightsReserved\": \"Tüm hakları saklıdır.\"\r\n}\r\n"
|
|
32
32
|
}
|
|
33
33
|
],
|
|
34
34
|
"exports": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"path": "footer/footer.tsx",
|
|
17
17
|
"type": "registry:component",
|
|
18
18
|
"target": "$modules$/footer/footer.tsx",
|
|
19
|
-
"content": "import { useMemo } from \"react\";\nimport { Link } from \"react-router\";\nimport { Mail, Phone, MapPin, Facebook, Twitter, Instagram, Linkedin } from \"lucide-react\";\nimport { Logo } from \"@/components/Logo\";\nimport constants from \"@/constants/constants.json\";\nimport { useTranslation } from \"react-i18next\";\n\nconst socialIcons: Record<string, React.ElementType> = {\n facebook: Facebook,\n twitter: Twitter,\n instagram: Instagram,\n linkedin: Linkedin,\n};\n\nexport function Footer() {\n const { t } = useTranslation(\"footer\");\n\n const socialLinks = useMemo(() => {\n const socialMedia = constants.socialMedia as Record<string, string> | undefined;\n if (!socialMedia) return [];\n return Object.entries(socialMedia)\n .filter(([platform, url]) => url && socialIcons[platform])\n .map(([platform, url]) => ({ platform, url, Icon: socialIcons[platform] }));\n }, []);\n\n const currentYear = new Date().getFullYear();\n\n return (\n <footer className=\"border-t bg-muted/20\">\n <div className=\"container mx-auto px-4 py-12 lg:py-16\">\n <div className=\"grid grid-cols-1 gap-10 md:grid-cols-2 lg:grid-cols-4\">\n {/* Brand */}\n <div className=\"space-y-4\">\n <Logo size=\"md\" />\n <p className=\"text-sm text-muted-foreground leading-relaxed\">\n {t(\"description\", \"Quality products and exceptional service for our valued customers.\")}\n </p>\n {socialLinks.length > 0 && (\n <div className=\"flex gap-1\">\n {socialLinks.map(({ platform, url, Icon }) => (\n <a\n key={platform}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"h-9 w-9 flex items-center justify-center rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted transition-colors\"\n >\n <Icon className=\"h-4 w-4\" />\n </a>\n ))}\n </div>\n )}\n </div>\n\n {/* Quick Links */}\n <div className=\"space-y-4\">\n <h4 className=\"font-semibold\">{t(\"quickLinks\", \"Quick Links\")}</h4>\n <ul className=\"space-y-2.5\">\n <li>\n <Link to=\"/about\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"about\", \"About\")}\n </Link>\n </li>\n <li>\n <Link to=\"/contact\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"contact\", \"Contact\")}\n </Link>\n </li>\n </ul>\n </div>\n\n {/* Legal */}\n <div className=\"space-y-4\">\n <h4 className=\"font-semibold\">{t(\"legal\", \"Legal\")}</h4>\n <ul className=\"space-y-2.5\">\n <li>\n <Link to=\"/privacy\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"privacy\", \"Privacy Policy\")}\n </Link>\n </li>\n <li>\n <Link to=\"/terms\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"terms\", \"Terms of Service\")}\n </Link>\n </li>\n <li>\n <Link to=\"/cookies\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"cookies\", \"Cookie Policy\")}\n </Link>\n </li>\n </ul>\n </div>\n\n {/* Contact */}\n <div className=\"space-y-4\">\n <h4 className=\"font-semibold\">{t(\"contactTitle\", \"Contact\")}</h4>\n <ul className=\"space-y-3\">\n <li className=\"flex items-center gap-3 text-sm text-muted-foreground\">\n <Phone className=\"h-4 w-4 shrink-0\" />\n <span>{constants.phone}</span>\n </li>\n <li className=\"flex items-center gap-3 text-sm text-muted-foreground\">\n <Mail className=\"h-4 w-4 shrink-0\" />\n <span>{constants.email}</span>\n </li>\n <li className=\"flex items-start gap-3 text-sm text-muted-foreground\">\n <MapPin className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>\n {constants.address.city}, {constants.address.state}\n </span>\n </li>\n </ul>\n </div>\n </div>\n\n {/* Bottom */}\n <div className=\"mt-12 pt-6 border-t\">\n <p className=\"text-sm text-muted-foreground text-center\">\n © {currentYear} {constants.site.name}. {t(\"allRightsReserved\", \"All rights reserved.\")}\n </p>\n </div>\n </div>\n </footer>\n );\n}\n"
|
|
19
|
+
"content": "import { useMemo } from \"react\";\nimport { Link } from \"react-router\";\nimport { Mail, Phone, MapPin, Facebook, Twitter, Instagram, Linkedin } from \"lucide-react\";\nimport { Logo } from \"@/components/Logo\";\nimport constants from \"@/constants/constants.json\";\nimport { useTranslation } from \"react-i18next\";\n\nconst socialIcons: Record<string, React.ElementType> = {\n facebook: Facebook,\n twitter: Twitter,\n instagram: Instagram,\n linkedin: Linkedin,\n};\n\nexport function Footer() {\n const { t } = useTranslation(\"footer\");\n\n const socialLinks = useMemo(() => {\n const socialMedia = constants.socialMedia as Record<string, string> | undefined;\n if (!socialMedia) return [];\n return Object.entries(socialMedia)\n .filter(([platform, url]) => url && socialIcons[platform])\n .map(([platform, url]) => ({ platform, url, Icon: socialIcons[platform] }));\n }, []);\n\n const currentYear = new Date().getFullYear();\n\n return (\n <footer className=\"border-t bg-muted/20\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4 py-12 lg:py-16\">\n <div className=\"grid grid-cols-1 gap-10 md:grid-cols-2 lg:grid-cols-4\">\n {/* Brand */}\n <div className=\"space-y-4\">\n <Logo size=\"md\" />\n <p className=\"text-sm text-muted-foreground leading-relaxed\">\n {t(\"description\", \"Quality products and exceptional service for our valued customers.\")}\n </p>\n {socialLinks.length > 0 && (\n <div className=\"flex gap-1\">\n {socialLinks.map(({ platform, url, Icon }) => (\n <a\n key={platform}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"h-9 w-9 flex items-center justify-center rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted transition-colors\"\n >\n <Icon className=\"h-4 w-4\" />\n </a>\n ))}\n </div>\n )}\n </div>\n\n {/* Quick Links */}\n <div className=\"space-y-4\">\n <h4 className=\"font-semibold\">{t(\"quickLinks\", \"Quick Links\")}</h4>\n <ul className=\"space-y-2.5\">\n <li>\n <Link to=\"/about\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"about\", \"About\")}\n </Link>\n </li>\n <li>\n <Link to=\"/contact\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"contact\", \"Contact\")}\n </Link>\n </li>\n </ul>\n </div>\n\n {/* Legal */}\n <div className=\"space-y-4\">\n <h4 className=\"font-semibold\">{t(\"legal\", \"Legal\")}</h4>\n <ul className=\"space-y-2.5\">\n <li>\n <Link to=\"/privacy\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"privacy\", \"Privacy Policy\")}\n </Link>\n </li>\n <li>\n <Link to=\"/terms\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"terms\", \"Terms of Service\")}\n </Link>\n </li>\n <li>\n <Link to=\"/cookies\" className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\">\n {t(\"cookies\", \"Cookie Policy\")}\n </Link>\n </li>\n </ul>\n </div>\n\n {/* Contact */}\n <div className=\"space-y-4\">\n <h4 className=\"font-semibold\">{t(\"contactTitle\", \"Contact\")}</h4>\n <ul className=\"space-y-3\">\n <li className=\"flex items-center gap-3 text-sm text-muted-foreground\">\n <Phone className=\"h-4 w-4 shrink-0\" />\n <span>{constants.phone}</span>\n </li>\n <li className=\"flex items-center gap-3 text-sm text-muted-foreground\">\n <Mail className=\"h-4 w-4 shrink-0\" />\n <span>{constants.email}</span>\n </li>\n <li className=\"flex items-start gap-3 text-sm text-muted-foreground\">\n <MapPin className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>\n {constants.address.city}, {constants.address.state}\n </span>\n </li>\n </ul>\n </div>\n </div>\n\n {/* Bottom */}\n <div className=\"mt-12 pt-6 border-t\">\n <p className=\"text-sm text-muted-foreground text-center\">\n © {currentYear} {constants.site.name}. {t(\"allRightsReserved\", \"All rights reserved.\")}\n </p>\n </div>\n </div>\n </footer>\n );\n}\n"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"path": "footer/lang/en.json",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "forgot-password-page",
|
|
3
|
+
"type": "registry:page",
|
|
4
|
+
"title": "Forgot Password Page",
|
|
5
|
+
"description": "Password recovery page with email form and sign in link. Centered card layout with responsive design.",
|
|
6
|
+
"registryDependencies": [
|
|
7
|
+
"button",
|
|
8
|
+
"input",
|
|
9
|
+
"label"
|
|
10
|
+
],
|
|
11
|
+
"usage": "import ForgotPasswordPage from '@/modules/forgot-password-page';\n\n<ForgotPasswordPage\n onSubmit={(email) => console.log(email)}\n/>",
|
|
12
|
+
"route": {
|
|
13
|
+
"path": "/forgot-password",
|
|
14
|
+
"componentName": "ForgotPasswordPage"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
{
|
|
18
|
+
"path": "forgot-password-page/index.ts",
|
|
19
|
+
"type": "registry:index",
|
|
20
|
+
"target": "$modules$/forgot-password-page/index.ts",
|
|
21
|
+
"content": "export { default } from './forgot-password-page';\r\nexport { default as ForgotPasswordPage } from './forgot-password-page';\r\n"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "forgot-password-page/forgot-password-page.tsx",
|
|
25
|
+
"type": "registry:page",
|
|
26
|
+
"target": "$modules$/forgot-password-page/forgot-password-page.tsx",
|
|
27
|
+
"content": "import { useState } from \"react\";\r\nimport { Link } from \"react-router\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport { Logo } from \"@/components/Logo\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\ninterface ForgotPasswordPageProps {\r\n onSubmit?: (email: string) => void;\r\n className?: string;\r\n}\r\n\r\nexport default function ForgotPasswordPage({\r\n onSubmit,\r\n className,\r\n}: ForgotPasswordPageProps) {\r\n const { t } = useTranslation(\"forgot-password-page\");\r\n const [email, setEmail] = useState(\"\");\r\n\r\n const handleSubmit = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n onSubmit?.(email);\r\n };\r\n\r\n return (\r\n <section className={cn(\"flex min-h-screen bg-muted/30 px-4 py-16 md:py-32\", className)}>\r\n <form\r\n onSubmit={handleSubmit}\r\n className=\"bg-muted m-auto h-fit w-full max-w-sm overflow-hidden rounded-xl border shadow-md\"\r\n >\r\n <div className=\"bg-card -m-px rounded-xl border p-8 pb-6\">\r\n <div className=\"text-center\">\r\n <Link to=\"/\" aria-label=\"go home\" className=\"mx-auto block w-fit\">\r\n <Logo size=\"sm\" />\r\n </Link>\r\n <h1 className=\"mb-1 mt-4 text-xl font-semibold\">\r\n {t(\"title\", \"Forgot Password\")}\r\n </h1>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {t(\"subtitle\", \"Enter your email to reset your password\")}\r\n </p>\r\n </div>\r\n\r\n <div className=\"mt-6 space-y-6\">\r\n <div className=\"space-y-2\">\r\n <Label htmlFor=\"email\" className=\"block text-sm\">\r\n {t(\"email\", \"Email\")}\r\n </Label>\r\n <Input\r\n type=\"email\"\r\n required\r\n name=\"email\"\r\n id=\"email\"\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n placeholder={t(\"emailPlaceholder\", \"you@example.com\")}\r\n />\r\n </div>\r\n\r\n <Button type=\"submit\" className=\"w-full\">\r\n {t(\"sendLink\", \"Send Reset Link\")}\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n <div className=\"p-3\">\r\n <p className=\"text-center text-sm text-muted-foreground\">\r\n {t(\"rememberPassword\", \"Remember your password?\")}\r\n <Button asChild variant=\"link\" className=\"px-2\">\r\n <Link to=\"/login\">{t(\"signIn\", \"Sign in\")}</Link>\r\n </Button>\r\n </p>\r\n </div>\r\n </form>\r\n </section>\r\n );\r\n}\r\n"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"path": "forgot-password-page/lang/en.json",
|
|
31
|
+
"type": "registry:lang",
|
|
32
|
+
"target": "$modules$/forgot-password-page/lang/en.json",
|
|
33
|
+
"content": "{\r\n \"title\": \"Forgot Password\",\r\n \"subtitle\": \"Enter your email to reset your password\",\r\n \"email\": \"Email\",\r\n \"emailPlaceholder\": \"you@example.com\",\r\n \"sendLink\": \"Send Reset Link\",\r\n \"rememberPassword\": \"Remember your password?\",\r\n \"signIn\": \"Sign in\"\r\n}\r\n"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"path": "forgot-password-page/lang/tr.json",
|
|
37
|
+
"type": "registry:lang",
|
|
38
|
+
"target": "$modules$/forgot-password-page/lang/tr.json",
|
|
39
|
+
"content": "{\r\n \"title\": \"Şifremi Unuttum\",\r\n \"subtitle\": \"Şifrenizi sıfırlamak için e-postanızı girin\",\r\n \"email\": \"E-posta\",\r\n \"emailPlaceholder\": \"ornek@email.com\",\r\n \"sendLink\": \"Sıfırlama Linki Gönder\",\r\n \"rememberPassword\": \"Şifrenizi hatırladınız mı?\",\r\n \"signIn\": \"Giriş yap\"\r\n}\r\n"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"exports": {
|
|
43
|
+
"types": [],
|
|
44
|
+
"variables": [
|
|
45
|
+
"ForgotPasswordPage",
|
|
46
|
+
"default"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
"title": "E-commerce Header",
|
|
5
5
|
"description": "Full-featured e-commerce header with logo, main navigation, search bar with autocomplete dropdown, favorites icon with count badge, shopping cart icon with item count, user account dropdown menu, and mobile hamburger menu. Includes sticky positioning, language switcher, and responsive breakpoints. Dark mode support included.",
|
|
6
6
|
"registryDependencies": [
|
|
7
|
-
"ecommerce-core"
|
|
7
|
+
"ecommerce-core",
|
|
8
|
+
"cart-drawer"
|
|
8
9
|
],
|
|
9
10
|
"usage": "import { Header } from '@/modules/header-ecommerce';\n\n<Header />\n\n• Component is installed at: src/modules/header-ecommerce/\n• Customize navigation links in: src/modules/header-ecommerce/lang/*.json\n• Uses useCart and useFavorites from ecommerce-core for badges\n• Includes search, cart, favorites, and mobile menu",
|
|
10
11
|
"files": [
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
"path": "header-ecommerce/header-ecommerce.tsx",
|
|
19
20
|
"type": "registry:component",
|
|
20
21
|
"target": "$modules$/header-ecommerce/header-ecommerce.tsx",
|
|
21
|
-
"content": "import { useState } from \"react\";\nimport { Link, useNavigate } from \"react-router\";\nimport { ShoppingCart, Menu, Search, Heart, Package } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Badge } from \"@/components/ui/badge\";\nimport {\n Sheet,\n SheetHeader,\n SheetTitle,\n SheetContent,\n SheetTrigger,\n} from \"@/components/ui/sheet\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { DropdownMenuItem } from \"@/components/ui/dropdown-menu\";\nimport { Logo } from \"@/components/Logo\";\nimport { AuthHeaderMenu } from \"@/modules/auth/auth-header-menu\";\nimport { useTranslation } from \"react-i18next\";\nimport constants from \"@/constants/constants.json\";\nimport type { Product } from \"@/modules/ecommerce-core/types\";\nimport {\n useCart,\n useFavorites,\n useSearch,\n formatPrice,\n} from \"@/modules/ecommerce-core\";\n\nexport function HeaderEcommerce() {\n const [mobileMenuOpen, setMobileMenuOpen] = useState(false);\n const [mobileSearchOpen, setMobileSearchOpen] = useState(false);\n const [desktopSearchOpen, setDesktopSearchOpen] = useState(false);\n const [showResults, setShowResults] = useState(false);\n const { itemCount, state } = useCart();\n const { favoriteCount } = useFavorites();\n const navigate = useNavigate();\n const { t } = useTranslation(\"header-ecommerce\");\n\n const {\n searchTerm,\n setSearchTerm,\n results: searchResults,\n clearSearch,\n } = useSearch();\n\n const handleSearchSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (searchTerm.trim()) {\n navigate(`/products?search=${encodeURIComponent(searchTerm)}`);\n setShowResults(false);\n setDesktopSearchOpen(false);\n clearSearch();\n }\n };\n\n const handleSearchFocus = () => {\n setShowResults(true);\n };\n\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearchTerm(e.target.value);\n setShowResults(true);\n };\n\n const navigation = [\n { name: t(\"home\"), href: \"/\" },\n { name: t(\"products\"), href: \"/products\" },\n { name: t(\"about\"), href: \"/about\" },\n { name: t(\"contact\"), href: \"/contact\" },\n ];\n\n return (\n <header className=\"sticky top-0 z-50 w-full border-b border-border/20 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60\">\n <div className=\"container mx-auto px-3 sm:px-4 lg:px-8\">\n <div className=\"flex h-14 sm:h-16 md:h-20 items-center justify-between gap-2\">\n {/* Logo */}\n <div className=\"flex-shrink-0 min-w-0\">\n <Logo size=\"sm\" className=\"text-base sm:text-xl lg:text-2xl\" />\n </div>\n\n {/* Desktop Navigation - Centered */}\n <nav className=\"hidden lg:flex items-center space-x-12 absolute left-1/2 transform -translate-x-1/2\">\n {navigation.map((item) => (\n <Link\n key={item.name}\n to={item.href}\n className=\"text-base font-medium transition-colors hover:text-primary relative group py-2\"\n >\n {item.name}\n <span className=\"absolute -bottom-1 left-0 w-0 h-0.5 bg-primary transition-all duration-300 group-hover:w-full\"></span>\n </Link>\n ))}\n </nav>\n\n {/* Search & Actions - Right Aligned */}\n <div className=\"flex items-center space-x-1 sm:space-x-2 lg:space-x-4 flex-shrink-0\">\n {/* Desktop Search - Modal */}\n <Dialog\n open={desktopSearchOpen}\n onOpenChange={setDesktopSearchOpen}\n >\n <DialogTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"hidden lg:flex h-10 w-10\"\n >\n <Search className=\"h-5 w-5\" />\n </Button>\n </DialogTrigger>\n <DialogContent className=\"sm:max-w-2xl\">\n <DialogHeader>\n <DialogTitle>\n {t(\"searchProducts\", \"Search Products\")}\n </DialogTitle>\n </DialogHeader>\n <div className=\"space-y-4\">\n <form onSubmit={handleSearchSubmit}>\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-5 w-5\" />\n <Input\n type=\"search\"\n placeholder={t(\n \"searchPlaceholder\",\n \"Search for products...\"\n )}\n value={searchTerm}\n onChange={handleSearchChange}\n className=\"pl-11 h-12 text-base\"\n autoFocus\n />\n </div>\n </form>\n\n {/* Desktop Search Results */}\n {searchTerm.trim() && (\n <div className=\"max-h-[400px] overflow-y-auto rounded-lg border bg-card\">\n {searchResults.length > 0 ? (\n <div className=\"divide-y\">\n <div className=\"px-4 py-3 bg-muted/50\">\n <p className=\"text-sm font-medium text-muted-foreground\">\n {searchResults.length}{\" \"}\n {searchResults.length === 1\n ? \"result\"\n : \"results\"}{\" \"}\n found\n </p>\n </div>\n {searchResults.slice(0, 8).map((product: Product) => (\n <Link\n key={product.id}\n to={`/products/${product.slug}`}\n onClick={() => {\n setDesktopSearchOpen(false);\n clearSearch();\n }}\n className=\"flex items-center gap-4 p-4 hover:bg-muted/50 transition-colors\"\n >\n <img\n src={\n product.images[0] || \"/images/placeholder.png\"\n }\n alt={product.name}\n className=\"w-16 h-16 object-cover rounded flex-shrink-0\"\n />\n <div className=\"flex-1 min-w-0\">\n <h4 className=\"font-medium text-base line-clamp-1\">\n {product.name}\n </h4>\n <p className=\"text-sm text-muted-foreground capitalize\">\n {product.category}\n </p>\n <p className=\"text-base font-semibold text-primary mt-1\">\n {formatPrice(\n product.price,\n constants.site.currency\n )}\n </p>\n </div>\n </Link>\n ))}\n {searchResults.length > 8 && (\n <div className=\"px-4 py-3 bg-muted/30 text-center\">\n <button\n onClick={() => {\n navigate(\n `/products?search=${encodeURIComponent(\n searchTerm\n )}`\n );\n setDesktopSearchOpen(false);\n clearSearch();\n }}\n className=\"text-sm font-medium text-primary hover:underline\"\n >\n {t(\n \"viewAllResults\",\n `View all ${searchResults.length} results`\n )}\n </button>\n </div>\n )}\n </div>\n ) : (\n <div className=\"p-8 text-center\">\n <Search className=\"h-12 w-12 text-muted-foreground mx-auto mb-3 opacity-50\" />\n <p className=\"text-base text-muted-foreground\">\n {t(\"noResults\", \"No products found\")}\n </p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {t(\n \"tryDifferentKeywords\",\n \"Try different keywords\"\n )}\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n </DialogContent>\n </Dialog>\n\n {/* Search - Mobile (Hidden - moved to hamburger menu) */}\n <Dialog open={mobileSearchOpen} onOpenChange={setMobileSearchOpen}>\n <DialogTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"hidden\">\n <Search className=\"h-4 w-4 sm:h-5 sm:w-5\" />\n </Button>\n </DialogTrigger>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>{t(\"searchProducts\")}</DialogTitle>\n </DialogHeader>\n <form\n onSubmit={(e) => {\n e.preventDefault();\n if (searchTerm.trim()) {\n navigate(\n `/products?search=${encodeURIComponent(searchTerm)}`\n );\n setMobileSearchOpen(false);\n clearSearch();\n }\n }}\n className=\"space-y-4\"\n >\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-4 w-4\" />\n <Input\n type=\"search\"\n placeholder={t(\"searchPlaceholder\")}\n value={searchTerm}\n onChange={(e) => setSearchTerm(e.target.value)}\n className=\"pl-10\"\n autoFocus\n />\n </div>\n <div className=\"flex gap-2\">\n <Button type=\"submit\" className=\"flex-1\">\n {t(\"searchButton\", \"Search\")}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n clearSearch();\n setMobileSearchOpen(false);\n }}\n >\n {t(\"cancel\", \"Cancel\")}\n </Button>\n </div>\n </form>\n\n {/* Mobile Search Results */}\n {searchTerm.trim() && (\n <div className=\"mt-4 max-h-64 overflow-y-auto\">\n {searchResults.length > 0 ? (\n <div className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground mb-2\">\n {searchResults.length} result\n {searchResults.length !== 1 ? \"s\" : \"\"} found\n </p>\n {searchResults.slice(0, 5).map((product: Product) => (\n <Link\n key={product.id}\n to={`/products/${product.slug}`}\n onClick={() => {\n setMobileSearchOpen(false);\n clearSearch();\n }}\n className=\"block p-2 rounded hover:bg-muted/50 transition-colors\"\n >\n <div className=\"flex items-center gap-3\">\n <img\n src={\n product.images[0] || \"/images/placeholder.png\"\n }\n alt={product.name}\n className=\"w-10 h-10 object-cover rounded\"\n />\n <div className=\"flex-1\">\n <h4 className=\"font-medium text-sm\">\n {product.name}\n </h4>\n <p className=\"text-xs text-muted-foreground\">\n {product.category}\n </p>\n <p className=\"text-sm font-medium\">\n {formatPrice(\n product.price,\n constants.site.currency\n )}\n </p>\n </div>\n </div>\n </Link>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n {t(\"noResults\")}\n </p>\n )}\n </div>\n )}\n </DialogContent>\n </Dialog>\n\n {/* Wishlist - Desktop Only */}\n <Link to=\"/favorites\" className=\"hidden lg:block\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"relative h-10 w-10\"\n >\n <Heart className=\"h-5 w-5\" />\n {favoriteCount > 0 && (\n <Badge\n variant=\"destructive\"\n className=\"absolute -top-1 -right-1 h-4 w-4 flex items-center justify-center p-0 text-[10px]\"\n >\n {favoriteCount}\n </Badge>\n )}\n </Button>\n </Link>\n\n {/* Cart - Desktop Only */}\n <Link to=\"/cart\" className=\"hidden lg:block\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"relative h-10 w-10\"\n >\n <ShoppingCart className=\"h-5 w-5\" />\n {itemCount > 0 && (\n <Badge\n variant=\"destructive\"\n className=\"absolute -top-1 -right-1 h-4 w-4 flex items-center justify-center p-0 text-[10px]\"\n >\n {itemCount}\n </Badge>\n )}\n </Button>\n </Link>\n\n {/* Auth - Desktop Only */}\n <div className=\"hidden lg:flex\">\n <AuthHeaderMenu variant=\"desktop\">\n <DropdownMenuItem asChild className=\"cursor-pointer\">\n <Link to=\"/orders\" className=\"flex items-center\">\n <Package className=\"mr-2 h-4 w-4\" />\n {t(\"myOrders\", \"My Orders\")}\n </Link>\n </DropdownMenuItem>\n </AuthHeaderMenu>\n </div>\n\n {/* Mobile Menu */}\n <Sheet open={mobileMenuOpen} onOpenChange={setMobileMenuOpen}>\n <SheetTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"lg:hidden h-8 w-8 sm:h-10 sm:w-10\"\n >\n <Menu className=\"h-4 w-4 sm:h-5 sm:w-5\" />\n </Button>\n </SheetTrigger>\n <SheetContent side=\"right\" className=\"w-[300px] sm:w-[400px] px-6\">\n <SheetHeader>\n <SheetTitle>{t(\"menu\")}</SheetTitle>\n </SheetHeader>\n\n {/* Mobile Search in Hamburger */}\n <div className=\"mt-6 pb-4 border-b\">\n <form onSubmit={handleSearchSubmit}>\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-4 w-4\" />\n <Input\n type=\"search\"\n placeholder={t(\"searchPlaceholder\")}\n value={searchTerm}\n onChange={handleSearchChange}\n onFocus={handleSearchFocus}\n className=\"pl-10 h-11\"\n />\n </div>\n </form>\n\n {/* Search Results in Hamburger */}\n {showResults && searchTerm && (\n <div className=\"mt-3 max-h-[300px] overflow-y-auto rounded-lg border bg-card\">\n {searchResults.length > 0 ? (\n <div className=\"divide-y\">\n <div className=\"px-3 py-2 bg-muted/50\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n {searchResults.length}{\" \"}\n {searchResults.length === 1\n ? \"result\"\n : \"results\"}\n </p>\n </div>\n {searchResults.slice(0, 5).map((product: Product) => (\n <Link\n key={product.id}\n to={`/products/${product.slug}`}\n onClick={() => {\n setMobileMenuOpen(false);\n clearSearch();\n setShowResults(false);\n }}\n className=\"flex items-center gap-3 p-3 hover:bg-muted/50 transition-colors\"\n >\n <img\n src={\n product.images[0] || \"/images/placeholder.png\"\n }\n alt={product.name}\n className=\"w-14 h-14 object-cover rounded flex-shrink-0\"\n />\n <div className=\"flex-1 min-w-0\">\n <h4 className=\"font-medium text-sm line-clamp-1\">\n {product.name}\n </h4>\n <p className=\"text-xs text-muted-foreground capitalize\">\n {product.category}\n </p>\n <p className=\"text-sm font-semibold text-primary mt-1\">\n {formatPrice(\n product.price,\n constants.site.currency\n )}\n </p>\n </div>\n </Link>\n ))}\n {searchResults.length > 5 && (\n <div className=\"px-3 py-2 bg-muted/30 text-center\">\n <button\n onClick={() => {\n navigate(\n `/products?search=${encodeURIComponent(\n searchTerm\n )}`\n );\n setMobileMenuOpen(false);\n clearSearch();\n setShowResults(false);\n }}\n className=\"text-xs font-medium text-primary hover:underline\"\n >\n {t(\n \"viewAllResults\",\n `View all ${searchResults.length} results`\n )}\n </button>\n </div>\n )}\n </div>\n ) : (\n <div className=\"p-6 text-center\">\n <Search className=\"h-8 w-8 text-muted-foreground mx-auto mb-2 opacity-50\" />\n <p className=\"text-sm text-muted-foreground\">\n {t(\"noResults\", \"No results found\")}\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"flex flex-col space-y-4 mt-6\">\n {navigation.map((item) => (\n <Link\n key={item.name}\n to={item.href}\n className=\"text-lg font-medium hover:text-primary transition-colors\"\n onClick={() => setMobileMenuOpen(false)}\n >\n {item.name}\n </Link>\n ))}\n <div className=\"border-t pt-4 space-y-4\">\n <Link\n to=\"/favorites\"\n className=\"flex items-center justify-between text-lg font-medium hover:text-primary transition-colors\"\n onClick={() => setMobileMenuOpen(false)}\n >\n <div className=\"flex items-center space-x-2\">\n <Heart className=\"h-5 w-5\" />\n <span>{t(\"favorites\")}</span>\n </div>\n <Badge variant=\"secondary\">{favoriteCount}</Badge>\n </Link>\n <Link\n to=\"/cart\"\n className=\"flex items-center justify-between text-lg font-medium hover:text-primary transition-colors\"\n onClick={() => setMobileMenuOpen(false)}\n >\n <div className=\"flex items-center space-x-2\">\n <ShoppingCart className=\"h-5 w-5\" />\n <span>{t(\"cart\")}</span>\n </div>\n <div className=\"flex flex-col items-end\">\n <Badge variant=\"secondary\">{itemCount}</Badge>\n <span className=\"text-xs text-muted-foreground\">\n {formatPrice(state.total, constants.site.currency)}\n </span>\n </div>\n </Link>\n\n {/* Auth - Mobile */}\n <AuthHeaderMenu\n variant=\"mobile\"\n onMenuClose={() => setMobileMenuOpen(false)}\n >\n <Link\n to=\"/orders\"\n className=\"flex items-center space-x-2 text-lg font-medium hover:text-primary transition-colors\"\n onClick={() => setMobileMenuOpen(false)}\n >\n <Package className=\"h-5 w-5\" />\n <span>{t(\"myOrders\", \"My Orders\")}</span>\n </Link>\n </AuthHeaderMenu>\n </div>\n </div>\n </SheetContent>\n </Sheet>\n </div>\n </div>\n </div>\n </header>\n );\n}\n"
|
|
22
|
+
"content": "import { useState } from \"react\";\nimport { Link, useNavigate } from \"react-router\";\nimport { ShoppingCart, Menu, Search, Heart, Package } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Badge } from \"@/components/ui/badge\";\nimport {\n Sheet,\n SheetHeader,\n SheetTitle,\n SheetContent,\n SheetTrigger,\n} from \"@/components/ui/sheet\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { DropdownMenuItem } from \"@/components/ui/dropdown-menu\";\nimport { Logo } from \"@/components/Logo\";\nimport { AuthHeaderMenu } from \"@/modules/auth/auth-header-menu\";\nimport { CartDrawer } from \"@/modules/cart-drawer\";\nimport { useTranslation } from \"react-i18next\";\nimport constants from \"@/constants/constants.json\";\nimport type { Product } from \"@/modules/ecommerce-core/types\";\nimport {\n useCart,\n useFavorites,\n useSearch,\n formatPrice,\n} from \"@/modules/ecommerce-core\";\n\nexport function HeaderEcommerce() {\n const [mobileMenuOpen, setMobileMenuOpen] = useState(false);\n const [mobileSearchOpen, setMobileSearchOpen] = useState(false);\n const [desktopSearchOpen, setDesktopSearchOpen] = useState(false);\n const [showResults, setShowResults] = useState(false);\n const { itemCount, state, removeItem, isDrawerOpen, setDrawerOpen } = useCart();\n const { favoriteCount } = useFavorites();\n const navigate = useNavigate();\n const { t } = useTranslation(\"header-ecommerce\");\n\n const {\n searchTerm,\n setSearchTerm,\n results: searchResults,\n clearSearch,\n } = useSearch();\n\n const handleSearchSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (searchTerm.trim()) {\n navigate(`/products?search=${encodeURIComponent(searchTerm)}`);\n setShowResults(false);\n setDesktopSearchOpen(false);\n clearSearch();\n }\n };\n\n const handleSearchFocus = () => {\n setShowResults(true);\n };\n\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearchTerm(e.target.value);\n setShowResults(true);\n };\n\n const navigation = [\n { name: t(\"home\"), href: \"/\" },\n { name: t(\"products\"), href: \"/products\" },\n { name: t(\"about\"), href: \"/about\" },\n { name: t(\"contact\"), href: \"/contact\" },\n ];\n\n return (\n <header className=\"sticky top-0 z-50 w-full border-b border-border/20 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-3 sm:px-4 lg:px-8\">\n <div className=\"flex h-14 sm:h-16 md:h-20 items-center justify-between gap-2\">\n {/* Logo */}\n <div className=\"flex-shrink-0 min-w-0\">\n <Logo size=\"sm\" className=\"text-base sm:text-xl lg:text-2xl\" />\n </div>\n\n {/* Desktop Navigation - Centered */}\n <nav className=\"hidden lg:flex items-center space-x-12 absolute left-1/2 transform -translate-x-1/2\">\n {navigation.map((item) => (\n <Link\n key={item.name}\n to={item.href}\n className=\"text-base font-medium transition-colors hover:text-primary relative group py-2\"\n >\n {item.name}\n <span className=\"absolute -bottom-1 left-0 w-0 h-0.5 bg-primary transition-all duration-300 group-hover:w-full\"></span>\n </Link>\n ))}\n </nav>\n\n {/* Search & Actions - Right Aligned */}\n <div className=\"flex items-center space-x-1 sm:space-x-2 lg:space-x-4 flex-shrink-0\">\n {/* Desktop Search - Modal */}\n <Dialog\n open={desktopSearchOpen}\n onOpenChange={setDesktopSearchOpen}\n >\n <DialogTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"hidden lg:flex h-10 w-10\"\n >\n <Search className=\"h-5 w-5\" />\n </Button>\n </DialogTrigger>\n <DialogContent className=\"sm:max-w-2xl\">\n <DialogHeader>\n <DialogTitle>\n {t(\"searchProducts\", \"Search Products\")}\n </DialogTitle>\n </DialogHeader>\n <div className=\"space-y-4\">\n <form onSubmit={handleSearchSubmit}>\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-5 w-5\" />\n <Input\n type=\"search\"\n placeholder={t(\n \"searchPlaceholder\",\n \"Search for products...\"\n )}\n value={searchTerm}\n onChange={handleSearchChange}\n className=\"pl-11 h-12 text-base\"\n autoFocus\n />\n </div>\n </form>\n\n {/* Desktop Search Results */}\n {searchTerm.trim() && (\n <div className=\"max-h-[400px] overflow-y-auto rounded-lg border bg-card\">\n {searchResults.length > 0 ? (\n <div className=\"divide-y\">\n <div className=\"px-4 py-3 bg-muted/50\">\n <p className=\"text-sm font-medium text-muted-foreground\">\n {searchResults.length}{\" \"}\n {searchResults.length === 1\n ? \"result\"\n : \"results\"}{\" \"}\n found\n </p>\n </div>\n {searchResults.slice(0, 8).map((product: Product) => (\n <Link\n key={product.id}\n to={`/products/${product.slug}`}\n onClick={() => {\n setDesktopSearchOpen(false);\n clearSearch();\n }}\n className=\"flex items-center gap-4 p-4 hover:bg-muted/50 transition-colors\"\n >\n <img\n src={\n product.images[0] || \"/images/placeholder.png\"\n }\n alt={product.name}\n className=\"w-16 h-16 object-cover rounded flex-shrink-0\"\n />\n <div className=\"flex-1 min-w-0\">\n <h4 className=\"font-medium text-base line-clamp-1\">\n {product.name}\n </h4>\n <p className=\"text-sm text-muted-foreground capitalize\">\n {product.category}\n </p>\n <p className=\"text-base font-semibold text-primary mt-1\">\n {formatPrice(\n product.price,\n constants.site.currency\n )}\n </p>\n </div>\n </Link>\n ))}\n {searchResults.length > 8 && (\n <div className=\"px-4 py-3 bg-muted/30 text-center\">\n <button\n onClick={() => {\n navigate(\n `/products?search=${encodeURIComponent(\n searchTerm\n )}`\n );\n setDesktopSearchOpen(false);\n clearSearch();\n }}\n className=\"text-sm font-medium text-primary hover:underline\"\n >\n {t(\n \"viewAllResults\",\n `View all ${searchResults.length} results`\n )}\n </button>\n </div>\n )}\n </div>\n ) : (\n <div className=\"p-8 text-center\">\n <Search className=\"h-12 w-12 text-muted-foreground mx-auto mb-3 opacity-50\" />\n <p className=\"text-base text-muted-foreground\">\n {t(\"noResults\", \"No products found\")}\n </p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {t(\n \"tryDifferentKeywords\",\n \"Try different keywords\"\n )}\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n </DialogContent>\n </Dialog>\n\n {/* Search - Mobile (Hidden - moved to hamburger menu) */}\n <Dialog open={mobileSearchOpen} onOpenChange={setMobileSearchOpen}>\n <DialogTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"hidden\">\n <Search className=\"h-4 w-4 sm:h-5 sm:w-5\" />\n </Button>\n </DialogTrigger>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>{t(\"searchProducts\")}</DialogTitle>\n </DialogHeader>\n <form\n onSubmit={(e) => {\n e.preventDefault();\n if (searchTerm.trim()) {\n navigate(\n `/products?search=${encodeURIComponent(searchTerm)}`\n );\n setMobileSearchOpen(false);\n clearSearch();\n }\n }}\n className=\"space-y-4\"\n >\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-4 w-4\" />\n <Input\n type=\"search\"\n placeholder={t(\"searchPlaceholder\")}\n value={searchTerm}\n onChange={(e) => setSearchTerm(e.target.value)}\n className=\"pl-10\"\n autoFocus\n />\n </div>\n <div className=\"flex gap-2\">\n <Button type=\"submit\" className=\"flex-1\">\n {t(\"searchButton\", \"Search\")}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n clearSearch();\n setMobileSearchOpen(false);\n }}\n >\n {t(\"cancel\", \"Cancel\")}\n </Button>\n </div>\n </form>\n\n {/* Mobile Search Results */}\n {searchTerm.trim() && (\n <div className=\"mt-4 max-h-64 overflow-y-auto\">\n {searchResults.length > 0 ? (\n <div className=\"space-y-2\">\n <p className=\"text-sm text-muted-foreground mb-2\">\n {searchResults.length} result\n {searchResults.length !== 1 ? \"s\" : \"\"} found\n </p>\n {searchResults.slice(0, 5).map((product: Product) => (\n <Link\n key={product.id}\n to={`/products/${product.slug}`}\n onClick={() => {\n setMobileSearchOpen(false);\n clearSearch();\n }}\n className=\"block p-2 rounded hover:bg-muted/50 transition-colors\"\n >\n <div className=\"flex items-center gap-3\">\n <img\n src={\n product.images[0] || \"/images/placeholder.png\"\n }\n alt={product.name}\n className=\"w-10 h-10 object-cover rounded\"\n />\n <div className=\"flex-1\">\n <h4 className=\"font-medium text-sm\">\n {product.name}\n </h4>\n <p className=\"text-xs text-muted-foreground\">\n {product.category}\n </p>\n <p className=\"text-sm font-medium\">\n {formatPrice(\n product.price,\n constants.site.currency\n )}\n </p>\n </div>\n </div>\n </Link>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n {t(\"noResults\")}\n </p>\n )}\n </div>\n )}\n </DialogContent>\n </Dialog>\n\n {/* Wishlist - Desktop Only */}\n <Link to=\"/favorites\" className=\"hidden lg:block\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"relative h-10 w-10\"\n >\n <Heart className=\"h-5 w-5\" />\n {favoriteCount > 0 && (\n <Badge\n variant=\"destructive\"\n className=\"absolute -top-1 -right-1 h-4 w-4 flex items-center justify-center p-0 text-[10px]\"\n >\n {favoriteCount}\n </Badge>\n )}\n </Button>\n </Link>\n\n {/* Cart - Desktop Only */}\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"relative h-10 w-10 hidden lg:flex\"\n asChild\n >\n <Link to=\"/cart\">\n <ShoppingCart className=\"h-5 w-5\" />\n {itemCount > 0 && (\n <Badge\n variant=\"destructive\"\n className=\"absolute -top-1 -right-1 h-4 w-4 flex items-center justify-center p-0 text-[10px]\"\n >\n {itemCount}\n </Badge>\n )}\n </Link>\n </Button>\n\n {/* Auth - Desktop Only */}\n <div className=\"hidden lg:flex\">\n <AuthHeaderMenu variant=\"desktop\">\n <DropdownMenuItem asChild className=\"cursor-pointer\">\n <Link to=\"/orders\" className=\"flex items-center\">\n <Package className=\"mr-2 h-4 w-4\" />\n {t(\"myOrders\", \"My Orders\")}\n </Link>\n </DropdownMenuItem>\n </AuthHeaderMenu>\n </div>\n\n {/* Mobile Menu */}\n <Sheet open={mobileMenuOpen} onOpenChange={setMobileMenuOpen}>\n <SheetTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"lg:hidden h-8 w-8 sm:h-10 sm:w-10\"\n >\n <Menu className=\"h-4 w-4 sm:h-5 sm:w-5\" />\n </Button>\n </SheetTrigger>\n <SheetContent side=\"right\" className=\"w-[300px] sm:w-[400px] px-6\">\n <SheetHeader>\n <SheetTitle>{t(\"menu\")}</SheetTitle>\n </SheetHeader>\n\n {/* Mobile Search in Hamburger */}\n <div className=\"mt-6 pb-4 border-b\">\n <form onSubmit={handleSearchSubmit}>\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-4 w-4\" />\n <Input\n type=\"search\"\n placeholder={t(\"searchPlaceholder\")}\n value={searchTerm}\n onChange={handleSearchChange}\n onFocus={handleSearchFocus}\n className=\"pl-10 h-11\"\n />\n </div>\n </form>\n\n {/* Search Results in Hamburger */}\n {showResults && searchTerm && (\n <div className=\"mt-3 max-h-[300px] overflow-y-auto rounded-lg border bg-card\">\n {searchResults.length > 0 ? (\n <div className=\"divide-y\">\n <div className=\"px-3 py-2 bg-muted/50\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n {searchResults.length}{\" \"}\n {searchResults.length === 1\n ? \"result\"\n : \"results\"}\n </p>\n </div>\n {searchResults.slice(0, 5).map((product: Product) => (\n <Link\n key={product.id}\n to={`/products/${product.slug}`}\n onClick={() => {\n setMobileMenuOpen(false);\n clearSearch();\n setShowResults(false);\n }}\n className=\"flex items-center gap-3 p-3 hover:bg-muted/50 transition-colors\"\n >\n <img\n src={\n product.images[0] || \"/images/placeholder.png\"\n }\n alt={product.name}\n className=\"w-14 h-14 object-cover rounded flex-shrink-0\"\n />\n <div className=\"flex-1 min-w-0\">\n <h4 className=\"font-medium text-sm line-clamp-1\">\n {product.name}\n </h4>\n <p className=\"text-xs text-muted-foreground capitalize\">\n {product.category}\n </p>\n <p className=\"text-sm font-semibold text-primary mt-1\">\n {formatPrice(\n product.price,\n constants.site.currency\n )}\n </p>\n </div>\n </Link>\n ))}\n {searchResults.length > 5 && (\n <div className=\"px-3 py-2 bg-muted/30 text-center\">\n <button\n onClick={() => {\n navigate(\n `/products?search=${encodeURIComponent(\n searchTerm\n )}`\n );\n setMobileMenuOpen(false);\n clearSearch();\n setShowResults(false);\n }}\n className=\"text-xs font-medium text-primary hover:underline\"\n >\n {t(\n \"viewAllResults\",\n `View all ${searchResults.length} results`\n )}\n </button>\n </div>\n )}\n </div>\n ) : (\n <div className=\"p-6 text-center\">\n <Search className=\"h-8 w-8 text-muted-foreground mx-auto mb-2 opacity-50\" />\n <p className=\"text-sm text-muted-foreground\">\n {t(\"noResults\", \"No results found\")}\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n\n <div className=\"flex flex-col space-y-4 mt-6\">\n {navigation.map((item) => (\n <Link\n key={item.name}\n to={item.href}\n className=\"text-lg font-medium hover:text-primary transition-colors\"\n onClick={() => setMobileMenuOpen(false)}\n >\n {item.name}\n </Link>\n ))}\n <div className=\"border-t pt-4 space-y-4\">\n <Link\n to=\"/favorites\"\n className=\"flex items-center justify-between text-lg font-medium hover:text-primary transition-colors\"\n onClick={() => setMobileMenuOpen(false)}\n >\n <div className=\"flex items-center space-x-2\">\n <Heart className=\"h-5 w-5\" />\n <span>{t(\"favorites\")}</span>\n </div>\n <Badge variant=\"secondary\">{favoriteCount}</Badge>\n </Link>\n <Link\n to=\"/cart\"\n className=\"flex items-center justify-between w-full text-lg font-medium hover:text-primary transition-colors\"\n onClick={() => setMobileMenuOpen(false)}\n >\n <div className=\"flex items-center space-x-2\">\n <ShoppingCart className=\"h-5 w-5\" />\n <span>{t(\"cart\")}</span>\n </div>\n <div className=\"flex flex-col items-end\">\n <Badge variant=\"secondary\">{itemCount}</Badge>\n <span className=\"text-xs text-muted-foreground\">\n {formatPrice(state.total, constants.site.currency)}\n </span>\n </div>\n </Link>\n\n {/* Auth - Mobile */}\n <AuthHeaderMenu\n variant=\"mobile\"\n onMenuClose={() => setMobileMenuOpen(false)}\n >\n <Link\n to=\"/orders\"\n className=\"flex items-center space-x-2 text-lg font-medium hover:text-primary transition-colors\"\n onClick={() => setMobileMenuOpen(false)}\n >\n <Package className=\"h-5 w-5\" />\n <span>{t(\"myOrders\", \"My Orders\")}</span>\n </Link>\n </AuthHeaderMenu>\n </div>\n </div>\n </SheetContent>\n </Sheet>\n </div>\n </div>\n </div>\n {/* Cart Drawer */}\n <CartDrawer\n open={isDrawerOpen}\n onOpenChange={setDrawerOpen}\n items={state.items.map((item) => ({\n id: item.id,\n name: item.product.name,\n href: `/products/${item.product.slug}`,\n price: item.product.on_sale && item.product.sale_price\n ? item.product.sale_price\n : item.product.price,\n quantity: item.quantity,\n image: item.product.images[0] || \"/images/placeholder.png\",\n imageAlt: item.product.name,\n }))}\n currency={constants.site.currency}\n onRemove={(id) => removeItem(id)}\n />\n </header>\n );\n}\n"
|
|
22
23
|
},
|
|
23
24
|
{
|
|
24
25
|
"path": "header-ecommerce/lang/en.json",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"path": "header-mega/header-mega.tsx",
|
|
24
24
|
"type": "registry:component",
|
|
25
25
|
"target": "$modules$/header-mega/header-mega.tsx",
|
|
26
|
-
"content": "import { Link } from \"react-router\";\r\nimport { Book, Menu, Sunset, Trees, Zap } from \"lucide-react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport {\r\n Accordion,\r\n AccordionContent,\r\n AccordionItem,\r\n AccordionTrigger,\r\n} from \"@/components/ui/accordion\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport {\r\n NavigationMenu,\r\n NavigationMenuContent,\r\n NavigationMenuItem,\r\n NavigationMenuLink,\r\n NavigationMenuList,\r\n NavigationMenuTrigger,\r\n} from \"@/components/ui/navigation-menu\";\r\nimport {\r\n Sheet,\r\n SheetContent,\r\n SheetHeader,\r\n SheetTitle,\r\n SheetTrigger,\r\n} from \"@/components/ui/sheet\";\r\nimport constants from \"@/constants/constants.json\";\r\n\r\ninterface MenuItem {\r\n title: string;\r\n url: string;\r\n description?: string;\r\n icon?: React.ReactNode;\r\n items?: MenuItem[];\r\n}\r\n\r\ninterface HeaderMegaProps {\r\n className?: string;\r\n}\r\n\r\nexport function HeaderMega({ className }: HeaderMegaProps) {\r\n const { t } = useTranslation(\"header-mega\");\r\n\r\n const menu: MenuItem[] = [\r\n { title: t(\"home\", \"Home\"), url: \"/\" },\r\n {\r\n title: t(\"products\", \"Products\"),\r\n url: \"/products\",\r\n items: [\r\n {\r\n title: t(\"allProducts\", \"All Products\"),\r\n description: t(\r\n \"allProductsDesc\",\r\n \"Browse our complete product catalog\"\r\n ),\r\n icon: <Book className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/products\",\r\n },\r\n {\r\n title: t(\"featured\", \"Featured\"),\r\n description: t(\r\n \"featuredDesc\",\r\n \"Our handpicked selection of top products\"\r\n ),\r\n icon: <Trees className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/products?featured=true\",\r\n },\r\n {\r\n title: t(\"newArrivals\", \"New Arrivals\"),\r\n description: t(\"newArrivalsDesc\", \"Check out the latest additions\"),\r\n icon: <Sunset className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/products?is_new=true\",\r\n },\r\n {\r\n title: t(\"onSale\", \"On Sale\"),\r\n description: t(\"onSaleDesc\", \"Great deals and special offers\"),\r\n icon: <Zap className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/products?on_sale=true\",\r\n },\r\n ],\r\n },\r\n {\r\n title: t(\"company\", \"Company\"),\r\n url: \"#\",\r\n items: [\r\n {\r\n title: t(\"aboutUs\", \"About Us\"),\r\n description: t(\r\n \"aboutUsDesc\",\r\n \"Learn more about our story and mission\"\r\n ),\r\n icon: <Trees className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/about\",\r\n },\r\n {\r\n title: t(\"contact\", \"Contact\"),\r\n description: t(\"contactDesc\", \"Get in touch with our team\"),\r\n icon: <Sunset className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/contact\",\r\n },\r\n {\r\n title: t(\"blog\", \"Blog\"),\r\n description: t(\"blogDesc\", \"Read our latest articles and updates\"),\r\n icon: <Book className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/blog\",\r\n },\r\n ],\r\n },\r\n ];\r\n\r\n const renderMenuItem = (item: MenuItem) => {\r\n if (item.items) {\r\n return (\r\n <NavigationMenuItem key={item.title}>\r\n <NavigationMenuTrigger>{item.title}</NavigationMenuTrigger>\r\n <NavigationMenuContent className=\"z-50 bg-popover text-popover-foreground\">\r\n {item.items.map((subItem) => (\r\n <NavigationMenuLink asChild key={subItem.title} className=\"w-80\">\r\n <SubMenuLink item={subItem} />\r\n </NavigationMenuLink>\r\n ))}\r\n </NavigationMenuContent>\r\n </NavigationMenuItem>\r\n );\r\n }\r\n\r\n return (\r\n <NavigationMenuItem key={item.title}>\r\n <NavigationMenuLink asChild>\r\n <Link\r\n to={item.url}\r\n className=\"group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-muted hover:text-accent-foreground\"\r\n >\r\n {item.title}\r\n </Link>\r\n </NavigationMenuLink>\r\n </NavigationMenuItem>\r\n );\r\n };\r\n\r\n const renderMobileMenuItem = (item: MenuItem) => {\r\n if (item.items) {\r\n return (\r\n <AccordionItem\r\n key={item.title}\r\n value={item.title}\r\n className=\"border-b-0\"\r\n >\r\n <AccordionTrigger className=\"text-md py-0 font-semibold hover:no-underline\">\r\n {item.title}\r\n </AccordionTrigger>\r\n <AccordionContent className=\"mt-2\">\r\n {item.items.map((subItem) => (\r\n <SubMenuLink key={subItem.title} item={subItem} />\r\n ))}\r\n </AccordionContent>\r\n </AccordionItem>\r\n );\r\n }\r\n\r\n return (\r\n <Link key={item.title} to={item.url} className=\"text-md font-semibold\">\r\n {item.title}\r\n </Link>\r\n );\r\n };\r\n\r\n return (\r\n <header\r\n className={cn(\r\n \"relative z-40 py-4 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60\",\r\n className\r\n )}\r\n >\r\n <div className=\"container mx-auto px-4\">\r\n {/* Desktop Menu */}\r\n <nav className=\"hidden items-center justify-between lg:flex\">\r\n <div className=\"flex items-center gap-6\">\r\n {/* Logo */}\r\n <Link to=\"/\" className=\"flex items-center gap-2\">\r\n <img\r\n src=\"/images/logo.png\"\r\n className=\"h-8 w-auto\"\r\n alt={constants.site.name}\r\n onError={(e) => {\r\n e.currentTarget.style.display = \"none\";\r\n }}\r\n />\r\n <span className=\"text-lg font-semibold tracking-tight\">\r\n {constants.site.name}\r\n </span>\r\n </Link>\r\n <div className=\"flex items-center\">\r\n <NavigationMenu>\r\n <NavigationMenuList>\r\n {menu.map((item) => renderMenuItem(item))}\r\n </NavigationMenuList>\r\n </NavigationMenu>\r\n </div>\r\n </div>\r\n <div className=\"flex gap-2\">\r\n <Button asChild variant=\"outline\" size=\"sm\">\r\n <Link to=\"/login\">{t(\"login\", \"Login\")}</Link>\r\n </Button>\r\n <Button asChild size=\"sm\">\r\n <Link to=\"/register\">{t(\"signup\", \"Sign up\")}</Link>\r\n </Button>\r\n </div>\r\n </nav>\r\n\r\n {/* Mobile Menu */}\r\n <div className=\"block lg:hidden\">\r\n <div className=\"flex items-center justify-between\">\r\n {/* Logo */}\r\n <Link to=\"/\" className=\"flex items-center gap-2\">\r\n <img\r\n src=\"/images/logo.png\"\r\n className=\"h-8 w-auto\"\r\n alt={constants.site.name}\r\n onError={(e) => {\r\n e.currentTarget.style.display = \"none\";\r\n }}\r\n />\r\n <span className=\"text-lg font-semibold tracking-tight\">\r\n {constants.site.name}\r\n </span>\r\n </Link>\r\n <Sheet>\r\n <SheetTrigger asChild>\r\n <Button variant=\"outline\" size=\"icon\">\r\n <Menu className=\"h-4 w-4\" />\r\n </Button>\r\n </SheetTrigger>\r\n <SheetContent className=\"z-50 overflow-y-auto px-6\">\r\n <SheetHeader>\r\n <SheetTitle>\r\n <Link to=\"/\" className=\"flex items-center gap-2\">\r\n <img\r\n src=\"/images/logo.png\"\r\n className=\"h-8 w-auto\"\r\n alt={constants.site.name}\r\n onError={(e) => {\r\n e.currentTarget.style.display = \"none\";\r\n }}\r\n />\r\n </Link>\r\n </SheetTitle>\r\n </SheetHeader>\r\n <div className=\"flex flex-col gap-6 p-4\">\r\n <Accordion\r\n type=\"single\"\r\n collapsible\r\n className=\"flex w-full flex-col gap-4\"\r\n >\r\n {menu.map((item) => renderMobileMenuItem(item))}\r\n </Accordion>\r\n\r\n <div className=\"flex flex-col gap-3\">\r\n <Button asChild variant=\"outline\">\r\n <Link to=\"/login\">{t(\"login\", \"Login\")}</Link>\r\n </Button>\r\n <Button asChild>\r\n <Link to=\"/register\">{t(\"signup\", \"Sign up\")}</Link>\r\n </Button>\r\n </div>\r\n </div>\r\n </SheetContent>\r\n </Sheet>\r\n </div>\r\n </div>\r\n </div>\r\n </header>\r\n );\r\n}\r\n\r\nfunction SubMenuLink({ item }: { item: MenuItem }) {\r\n return (\r\n <Link\r\n to={item.url}\r\n className=\"flex min-w-80 flex-row gap-4 rounded-md p-3 leading-none no-underline transition-colors outline-none select-none hover:bg-muted hover:text-accent-foreground\"\r\n >\r\n <div className=\"text-foreground\">{item.icon}</div>\r\n <div>\r\n <div className=\"text-sm font-semibold\">{item.title}</div>\r\n {item.description && (\r\n <p className=\"text-sm leading-snug text-muted-foreground\">\r\n {item.description}\r\n </p>\r\n )}\r\n </div>\r\n </Link>\r\n );\r\n}\r\n"
|
|
26
|
+
"content": "import { Link } from \"react-router\";\r\nimport { Book, Menu, Sunset, Trees, Zap } from \"lucide-react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport {\r\n Accordion,\r\n AccordionContent,\r\n AccordionItem,\r\n AccordionTrigger,\r\n} from \"@/components/ui/accordion\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport {\r\n NavigationMenu,\r\n NavigationMenuContent,\r\n NavigationMenuItem,\r\n NavigationMenuLink,\r\n NavigationMenuList,\r\n NavigationMenuTrigger,\r\n} from \"@/components/ui/navigation-menu\";\r\nimport {\r\n Sheet,\r\n SheetContent,\r\n SheetHeader,\r\n SheetTitle,\r\n SheetTrigger,\r\n} from \"@/components/ui/sheet\";\r\nimport constants from \"@/constants/constants.json\";\r\n\r\ninterface MenuItem {\r\n title: string;\r\n url: string;\r\n description?: string;\r\n icon?: React.ReactNode;\r\n items?: MenuItem[];\r\n}\r\n\r\ninterface HeaderMegaProps {\r\n className?: string;\r\n}\r\n\r\nexport function HeaderMega({ className }: HeaderMegaProps) {\r\n const { t } = useTranslation(\"header-mega\");\r\n\r\n const menu: MenuItem[] = [\r\n { title: t(\"home\", \"Home\"), url: \"/\" },\r\n {\r\n title: t(\"products\", \"Products\"),\r\n url: \"/products\",\r\n items: [\r\n {\r\n title: t(\"allProducts\", \"All Products\"),\r\n description: t(\r\n \"allProductsDesc\",\r\n \"Browse our complete product catalog\"\r\n ),\r\n icon: <Book className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/products\",\r\n },\r\n {\r\n title: t(\"featured\", \"Featured\"),\r\n description: t(\r\n \"featuredDesc\",\r\n \"Our handpicked selection of top products\"\r\n ),\r\n icon: <Trees className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/products?featured=true\",\r\n },\r\n {\r\n title: t(\"newArrivals\", \"New Arrivals\"),\r\n description: t(\"newArrivalsDesc\", \"Check out the latest additions\"),\r\n icon: <Sunset className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/products?is_new=true\",\r\n },\r\n {\r\n title: t(\"onSale\", \"On Sale\"),\r\n description: t(\"onSaleDesc\", \"Great deals and special offers\"),\r\n icon: <Zap className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/products?on_sale=true\",\r\n },\r\n ],\r\n },\r\n {\r\n title: t(\"company\", \"Company\"),\r\n url: \"#\",\r\n items: [\r\n {\r\n title: t(\"aboutUs\", \"About Us\"),\r\n description: t(\r\n \"aboutUsDesc\",\r\n \"Learn more about our story and mission\"\r\n ),\r\n icon: <Trees className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/about\",\r\n },\r\n {\r\n title: t(\"contact\", \"Contact\"),\r\n description: t(\"contactDesc\", \"Get in touch with our team\"),\r\n icon: <Sunset className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/contact\",\r\n },\r\n {\r\n title: t(\"blog\", \"Blog\"),\r\n description: t(\"blogDesc\", \"Read our latest articles and updates\"),\r\n icon: <Book className=\"h-5 w-5 shrink-0\" />,\r\n url: \"/blog\",\r\n },\r\n ],\r\n },\r\n ];\r\n\r\n const renderMenuItem = (item: MenuItem) => {\r\n if (item.items) {\r\n return (\r\n <NavigationMenuItem key={item.title}>\r\n <NavigationMenuTrigger>{item.title}</NavigationMenuTrigger>\r\n <NavigationMenuContent className=\"z-50 bg-popover text-popover-foreground\">\r\n {item.items.map((subItem) => (\r\n <NavigationMenuLink asChild key={subItem.title} className=\"w-80\">\r\n <SubMenuLink item={subItem} />\r\n </NavigationMenuLink>\r\n ))}\r\n </NavigationMenuContent>\r\n </NavigationMenuItem>\r\n );\r\n }\r\n\r\n return (\r\n <NavigationMenuItem key={item.title}>\r\n <NavigationMenuLink asChild>\r\n <Link\r\n to={item.url}\r\n className=\"group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-muted hover:text-accent-foreground\"\r\n >\r\n {item.title}\r\n </Link>\r\n </NavigationMenuLink>\r\n </NavigationMenuItem>\r\n );\r\n };\r\n\r\n const renderMobileMenuItem = (item: MenuItem) => {\r\n if (item.items) {\r\n return (\r\n <AccordionItem\r\n key={item.title}\r\n value={item.title}\r\n className=\"border-b-0\"\r\n >\r\n <AccordionTrigger className=\"text-md py-0 font-semibold hover:no-underline\">\r\n {item.title}\r\n </AccordionTrigger>\r\n <AccordionContent className=\"mt-2\">\r\n {item.items.map((subItem) => (\r\n <SubMenuLink key={subItem.title} item={subItem} />\r\n ))}\r\n </AccordionContent>\r\n </AccordionItem>\r\n );\r\n }\r\n\r\n return (\r\n <Link key={item.title} to={item.url} className=\"text-md font-semibold\">\r\n {item.title}\r\n </Link>\r\n );\r\n };\r\n\r\n return (\r\n <header\r\n className={cn(\r\n \"relative z-50 py-4 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60\",\r\n className\r\n )}\r\n >\r\n <div className=\"container max-w-7xl mx-auto px-4\">\r\n {/* Desktop Menu */}\r\n <nav className=\"hidden items-center justify-between lg:flex\">\r\n <div className=\"flex items-center gap-6\">\r\n {/* Logo */}\r\n <Link to=\"/\" className=\"flex items-center gap-2\">\r\n <img\r\n src=\"/images/logo.png\"\r\n className=\"h-8 w-auto\"\r\n alt={constants.site.name}\r\n onError={(e) => {\r\n e.currentTarget.style.display = \"none\";\r\n }}\r\n />\r\n <span className=\"text-lg font-semibold tracking-tight\">\r\n {constants.site.name}\r\n </span>\r\n </Link>\r\n <div className=\"flex items-center\">\r\n <NavigationMenu>\r\n <NavigationMenuList>\r\n {menu.map((item) => renderMenuItem(item))}\r\n </NavigationMenuList>\r\n </NavigationMenu>\r\n </div>\r\n </div>\r\n <div className=\"flex gap-2\">\r\n <Button asChild variant=\"outline\" size=\"sm\">\r\n <Link to=\"/login\">{t(\"login\", \"Login\")}</Link>\r\n </Button>\r\n <Button asChild size=\"sm\">\r\n <Link to=\"/register\">{t(\"signup\", \"Sign up\")}</Link>\r\n </Button>\r\n </div>\r\n </nav>\r\n\r\n {/* Mobile Menu */}\r\n <div className=\"block lg:hidden\">\r\n <div className=\"flex items-center justify-between\">\r\n {/* Logo */}\r\n <Link to=\"/\" className=\"flex items-center gap-2\">\r\n <img\r\n src=\"/images/logo.png\"\r\n className=\"h-8 w-auto\"\r\n alt={constants.site.name}\r\n onError={(e) => {\r\n e.currentTarget.style.display = \"none\";\r\n }}\r\n />\r\n <span className=\"text-lg font-semibold tracking-tight\">\r\n {constants.site.name}\r\n </span>\r\n </Link>\r\n <Sheet>\r\n <SheetTrigger asChild>\r\n <Button variant=\"outline\" size=\"icon\">\r\n <Menu className=\"h-4 w-4\" />\r\n </Button>\r\n </SheetTrigger>\r\n <SheetContent className=\"z-50 overflow-y-auto px-6\">\r\n <SheetHeader>\r\n <SheetTitle>\r\n <Link to=\"/\" className=\"flex items-center gap-2\">\r\n <img\r\n src=\"/images/logo.png\"\r\n className=\"h-8 w-auto\"\r\n alt={constants.site.name}\r\n onError={(e) => {\r\n e.currentTarget.style.display = \"none\";\r\n }}\r\n />\r\n </Link>\r\n </SheetTitle>\r\n </SheetHeader>\r\n <div className=\"flex flex-col gap-6 p-4\">\r\n <Accordion\r\n type=\"single\"\r\n collapsible\r\n className=\"flex w-full flex-col gap-4\"\r\n >\r\n {menu.map((item) => renderMobileMenuItem(item))}\r\n </Accordion>\r\n\r\n <div className=\"flex flex-col gap-3\">\r\n <Button asChild variant=\"outline\">\r\n <Link to=\"/login\">{t(\"login\", \"Login\")}</Link>\r\n </Button>\r\n <Button asChild>\r\n <Link to=\"/register\">{t(\"signup\", \"Sign up\")}</Link>\r\n </Button>\r\n </div>\r\n </div>\r\n </SheetContent>\r\n </Sheet>\r\n </div>\r\n </div>\r\n </div>\r\n </header>\r\n );\r\n}\r\n\r\nfunction SubMenuLink({ item }: { item: MenuItem }) {\r\n return (\r\n <Link\r\n to={item.url}\r\n className=\"flex min-w-80 flex-row gap-4 rounded-md p-3 leading-none no-underline transition-colors outline-none select-none hover:bg-muted hover:text-accent-foreground\"\r\n >\r\n <div className=\"text-foreground\">{item.icon}</div>\r\n <div>\r\n <div className=\"text-sm font-semibold\">{item.title}</div>\r\n {item.description && (\r\n <p className=\"text-sm leading-snug text-muted-foreground\">\r\n {item.description}\r\n </p>\r\n )}\r\n </div>\r\n </Link>\r\n );\r\n}\r\n"
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
"path": "header-mega/lang/en.json",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"path": "header-minimal/header-minimal.tsx",
|
|
22
22
|
"type": "registry:component",
|
|
23
23
|
"target": "$modules$/header-minimal/header-minimal.tsx",
|
|
24
|
-
"content": "import { Link } from \"react-router\";\r\nimport { Menu } from \"lucide-react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport {\r\n Sheet,\r\n SheetContent,\r\n SheetHeader,\r\n SheetTitle,\r\n SheetTrigger,\r\n} from \"@/components/ui/sheet\";\r\nimport constants from \"@/constants/constants.json\";\r\n\r\ninterface HeaderMinimalProps {\r\n className?: string;\r\n}\r\n\r\nexport function HeaderMinimal({ className }: HeaderMinimalProps) {\r\n const { t } = useTranslation(\"header-minimal\");\r\n\r\n const links = [\r\n { title: t(\"home\", \"Home\"), url: \"/\" },\r\n { title: t(\"about\", \"About\"), url: \"/about\" },\r\n ];\r\n\r\n return (\r\n <header className={cn(\"py-4 border-b bg-background\", className)}>\r\n <div className=\"container mx-auto px-4\">\r\n <nav className=\"flex items-center justify-between\">\r\n {/* Logo */}\r\n <Link to=\"/\" className=\"flex items-center gap-2\">\r\n <img\r\n src=\"/images/logo.png\"\r\n className=\"h-8 w-auto\"\r\n alt={constants.site.name}\r\n onError={(e) => {\r\n e.currentTarget.style.display = \"none\";\r\n }}\r\n />\r\n <span className=\"text-xl font-bold tracking-tight\">\r\n {constants.site.name}\r\n </span>\r\n </Link>\r\n\r\n {/* Desktop Links */}\r\n <div className=\"hidden md:flex items-center gap-8\">\r\n {links.map((link) => (\r\n <Link\r\n key={link.title}\r\n to={link.url}\r\n className=\"text-sm font-medium text-muted-foreground hover:text-foreground transition-colors\"\r\n >\r\n {link.title}\r\n </Link>\r\n ))}\r\n </div>\r\n\r\n {/* CTA Button - Desktop */}\r\n <div className=\"hidden md:block\">\r\n <Button asChild>\r\n <Link to=\"/contact\">{t(\"cta\", \"Contact\")}</Link>\r\n </Button>\r\n </div>\r\n\r\n {/* Mobile Menu */}\r\n <div className=\"md:hidden\">\r\n <Sheet>\r\n <SheetTrigger asChild>\r\n <Button variant=\"ghost\" size=\"icon\">\r\n <Menu className=\"h-5 w-5\" />\r\n </Button>\r\n </SheetTrigger>\r\n <SheetContent side=\"right\" className=\"px-6\">\r\n <SheetHeader>\r\n <SheetTitle>\r\n <Link to=\"/\" className=\"flex items-center gap-2\">\r\n <span className=\"text-xl font-bold\">\r\n {constants.site.name}\r\n </span>\r\n </Link>\r\n </SheetTitle>\r\n </SheetHeader>\r\n <div className=\"flex flex-col gap-4 mt-8\">\r\n {links.map((link) => (\r\n <Link\r\n key={link.title}\r\n to={link.url}\r\n className=\"text-lg font-medium hover:text-primary transition-colors\"\r\n >\r\n {link.title}\r\n </Link>\r\n ))}\r\n <Button asChild className=\"mt-4\">\r\n <Link to=\"/contact\">{t(\"cta\", \"Contact\")}</Link>\r\n </Button>\r\n </div>\r\n </SheetContent>\r\n </Sheet>\r\n </div>\r\n </nav>\r\n </div>\r\n </header>\r\n );\r\n}\r\n"
|
|
24
|
+
"content": "import { Link } from \"react-router\";\r\nimport { Menu } from \"lucide-react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport {\r\n Sheet,\r\n SheetContent,\r\n SheetHeader,\r\n SheetTitle,\r\n SheetTrigger,\r\n} from \"@/components/ui/sheet\";\r\nimport constants from \"@/constants/constants.json\";\r\n\r\ninterface HeaderMinimalProps {\r\n className?: string;\r\n}\r\n\r\nexport function HeaderMinimal({ className }: HeaderMinimalProps) {\r\n const { t } = useTranslation(\"header-minimal\");\r\n\r\n const links = [\r\n { title: t(\"home\", \"Home\"), url: \"/\" },\r\n { title: t(\"about\", \"About\"), url: \"/about\" },\r\n ];\r\n\r\n return (\r\n <header className={cn(\"py-4 border-b bg-background\", className)}>\r\n <div className=\"container max-w-7xl mx-auto px-4\">\r\n <nav className=\"flex items-center justify-between\">\r\n {/* Logo */}\r\n <Link to=\"/\" className=\"flex items-center gap-2\">\r\n <img\r\n src=\"/images/logo.png\"\r\n className=\"h-8 w-auto\"\r\n alt={constants.site.name}\r\n onError={(e) => {\r\n e.currentTarget.style.display = \"none\";\r\n }}\r\n />\r\n <span className=\"text-xl font-bold tracking-tight\">\r\n {constants.site.name}\r\n </span>\r\n </Link>\r\n\r\n {/* Desktop Links */}\r\n <div className=\"hidden md:flex items-center gap-8\">\r\n {links.map((link) => (\r\n <Link\r\n key={link.title}\r\n to={link.url}\r\n className=\"text-sm font-medium text-muted-foreground hover:text-foreground transition-colors\"\r\n >\r\n {link.title}\r\n </Link>\r\n ))}\r\n </div>\r\n\r\n {/* CTA Button - Desktop */}\r\n <div className=\"hidden md:block\">\r\n <Button asChild>\r\n <Link to=\"/contact\">{t(\"cta\", \"Contact\")}</Link>\r\n </Button>\r\n </div>\r\n\r\n {/* Mobile Menu */}\r\n <div className=\"md:hidden\">\r\n <Sheet>\r\n <SheetTrigger asChild>\r\n <Button variant=\"ghost\" size=\"icon\">\r\n <Menu className=\"h-5 w-5\" />\r\n </Button>\r\n </SheetTrigger>\r\n <SheetContent side=\"right\" className=\"px-6\">\r\n <SheetHeader>\r\n <SheetTitle>\r\n <Link to=\"/\" className=\"flex items-center gap-2\">\r\n <span className=\"text-xl font-bold\">\r\n {constants.site.name}\r\n </span>\r\n </Link>\r\n </SheetTitle>\r\n </SheetHeader>\r\n <div className=\"flex flex-col gap-4 mt-8\">\r\n {links.map((link) => (\r\n <Link\r\n key={link.title}\r\n to={link.url}\r\n className=\"text-lg font-medium hover:text-primary transition-colors\"\r\n >\r\n {link.title}\r\n </Link>\r\n ))}\r\n <Button asChild className=\"mt-4\">\r\n <Link to=\"/contact\">{t(\"cta\", \"Contact\")}</Link>\r\n </Button>\r\n </div>\r\n </SheetContent>\r\n </Sheet>\r\n </div>\r\n </nav>\r\n </div>\r\n </header>\r\n );\r\n}\r\n"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"path": "header-minimal/lang/en.json",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"path": "header-simple/header-simple.tsx",
|
|
20
20
|
"type": "registry:component",
|
|
21
21
|
"target": "$modules$/header-simple/header-simple.tsx",
|
|
22
|
-
"content": "import { useState } from \"react\";\nimport { Link } from \"react-router\";\nimport { Menu } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Sheet,\n SheetHeader,\n SheetTitle,\n SheetContent,\n SheetTrigger,\n} from \"@/components/ui/sheet\";\nimport { Logo } from \"@/components/Logo\";\nimport { useTranslation } from \"react-i18next\";\n\nexport function HeaderSimple() {\n const [mobileMenuOpen, setMobileMenuOpen] = useState(false);\n const { t } = useTranslation(\"header-simple\");\n\n\n\n const navigation = [\n { name: t('home', 'Home'), href: \"/\" },\n { name: t('about', 'About'), href: \"/about\" },\n { name: t('contact', 'Contact'), href: \"/contact\" },\n ];\n\n return (\n <header className=\"sticky top-0 z-50 w-full border-b border-border/20 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60\">\n <div className=\"container mx-auto px-4 lg:px-8\">\n <div className=\"flex h-16 sm:h-20 items-center justify-between\">\n {/* Logo */}\n <div className=\"flex-shrink-0 min-w-0\">\n <Logo size=\"sm\" className=\"text-base sm:text-xl lg:text-2xl\" />\n </div>\n\n {/* Desktop Navigation - Right Aligned */}\n <nav className=\"hidden lg:flex items-center space-x-8\">\n {navigation.map((item) => (\n <Link\n key={item.name}\n to={item.href}\n className=\"text-base font-medium transition-colors hover:text-primary relative group py-2\"\n >\n {item.name}\n <span className=\"absolute -bottom-1 left-0 w-0 h-0.5 bg-primary transition-all duration-300 group-hover:w-full\"></span>\n </Link>\n ))}\n </nav>\n\n {/* Mobile Menu - Right Aligned */}\n <div className=\"lg:hidden flex-shrink-0\">\n <Sheet open={mobileMenuOpen} onOpenChange={setMobileMenuOpen}>\n <SheetTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\">\n <Menu className=\"h-5 w-5\" />\n </Button>\n </SheetTrigger>\n <SheetContent side=\"right\" className=\"w-[300px] sm:w-[400px] px-6\">\n <SheetHeader>\n <SheetTitle>{t('menu')}</SheetTitle>\n </SheetHeader>\n <div className=\"flex flex-col space-y-4 mt-8\">\n {navigation.map((item) => (\n <Link\n key={item.name}\n to={item.href}\n className=\"text-lg font-medium hover:text-primary transition-colors\"\n onClick={() => setMobileMenuOpen(false)}\n >\n {item.name}\n </Link>\n ))}\n </div>\n </SheetContent>\n </Sheet>\n </div>\n </div>\n </div>\n </header>\n );\n}\n"
|
|
22
|
+
"content": "import { useState } from \"react\";\nimport { Link } from \"react-router\";\nimport { Menu } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Sheet,\n SheetHeader,\n SheetTitle,\n SheetContent,\n SheetTrigger,\n} from \"@/components/ui/sheet\";\nimport { Logo } from \"@/components/Logo\";\nimport { useTranslation } from \"react-i18next\";\n\nexport function HeaderSimple() {\n const [mobileMenuOpen, setMobileMenuOpen] = useState(false);\n const { t } = useTranslation(\"header-simple\");\n\n\n\n const navigation = [\n { name: t('home', 'Home'), href: \"/\" },\n { name: t('about', 'About'), href: \"/about\" },\n { name: t('contact', 'Contact'), href: \"/contact\" },\n ];\n\n return (\n <header className=\"sticky top-0 z-50 w-full border-b border-border/20 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60\">\n <div className=\"container max-w-7xl mx-auto px-4 lg:px-8\">\n <div className=\"flex h-16 sm:h-20 items-center justify-between\">\n {/* Logo */}\n <div className=\"flex-shrink-0 min-w-0\">\n <Logo size=\"sm\" className=\"text-base sm:text-xl lg:text-2xl\" />\n </div>\n\n {/* Desktop Navigation - Right Aligned */}\n <nav className=\"hidden lg:flex items-center space-x-8\">\n {navigation.map((item) => (\n <Link\n key={item.name}\n to={item.href}\n className=\"text-base font-medium transition-colors hover:text-primary relative group py-2\"\n >\n {item.name}\n <span className=\"absolute -bottom-1 left-0 w-0 h-0.5 bg-primary transition-all duration-300 group-hover:w-full\"></span>\n </Link>\n ))}\n </nav>\n\n {/* Mobile Menu - Right Aligned */}\n <div className=\"lg:hidden flex-shrink-0\">\n <Sheet open={mobileMenuOpen} onOpenChange={setMobileMenuOpen}>\n <SheetTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\">\n <Menu className=\"h-5 w-5\" />\n </Button>\n </SheetTrigger>\n <SheetContent side=\"right\" className=\"w-[300px] sm:w-[400px] px-6\">\n <SheetHeader>\n <SheetTitle>{t('menu')}</SheetTitle>\n </SheetHeader>\n <div className=\"flex flex-col space-y-4 mt-8\">\n {navigation.map((item) => (\n <Link\n key={item.name}\n to={item.href}\n className=\"text-lg font-medium hover:text-primary transition-colors\"\n onClick={() => setMobileMenuOpen(false)}\n >\n {item.name}\n </Link>\n ))}\n </div>\n </SheetContent>\n </Sheet>\n </div>\n </div>\n </div>\n </header>\n );\n}\n"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"path": "header-simple/lang/en.json",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"path": "hero-cta/hero-cta.tsx",
|
|
19
19
|
"type": "registry:component",
|
|
20
20
|
"target": "$modules$/hero-cta/hero-cta.tsx",
|
|
21
|
-
"content": "import { Link } from \"react-router\";\r\nimport { ArrowRight, Star } from \"lucide-react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { Avatar, AvatarImage, AvatarFallback } from \"@/components/ui/avatar\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\ninterface HeroCtaProps {\r\n className?: string;\r\n}\r\n\r\nexport function HeroCta({ className }: HeroCtaProps) {\r\n const { t } = useTranslation(\"hero-cta\");\r\n\r\n const avatars = [\r\n { src: \"/images/placeholder.png\", alt: \"User 1\", fallback: \"U1\" },\r\n { src: \"/images/placeholder.png\", alt: \"User 2\", fallback: \"U2\" },\r\n { src: \"/images/placeholder.png\", alt: \"User 3\", fallback: \"U3\" },\r\n { src: \"/images/placeholder.png\", alt: \"User 4\", fallback: \"U4\" },\r\n { src: \"/images/placeholder.png\", alt: \"User 5\", fallback: \"U5\" },\r\n ];\r\n\r\n return (\r\n <section className={cn(\"py-16 md:py-24 lg:py-32\", className)}>\r\n <div className=\"container mx-auto px-4\">\r\n <div className=\"grid items-center gap-10 lg:grid-cols-2 lg:gap-16\">\r\n {/* Content Column */}\r\n <div className=\"flex flex-col items-center text-center lg:items-start lg:text-left\">\r\n <h1 className=\"mb-6 text-3xl font-bold text-pretty sm:text-4xl lg:text-5xl xl:text-6xl leading-tight\">\r\n {t(\"heading\", \"Build something amazing with our platform\")}\r\n </h1>\r\n <p className=\"mb-8 max-w-xl text-muted-foreground text-base lg:text-lg\">\r\n {t(\"description\", \"Create beautiful, responsive applications with ease. Our tools help you ship faster and build better products.\")}\r\n </p>\r\n\r\n {/* Social Proof */}\r\n <div className=\"mb-10 flex flex-col items-center gap-4 sm:flex-row lg:items-start\">\r\n <div className=\"flex -space-x-3\">\r\n {avatars.map((avatar, index) => (\r\n <Avatar key={index} className=\"h-10 w-10 border-2 border-background\">\r\n <AvatarImage src={avatar.src} alt={avatar.alt} />\r\n <AvatarFallback className=\"text-xs\">{avatar.fallback}</AvatarFallback>\r\n </Avatar>\r\n ))}\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-1\">\r\n {[...Array(5)].map((_, index) => (\r\n <Star\r\n key={index}\r\n className=\"h-4 w-4 fill-yellow-400 text-yellow-400\"\r\n />\r\n ))}\r\n <span className=\"ml-1 font-semibold text-sm\">5.0</span>\r\n </div>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {t(\"reviews\", \"from 200+ happy users\")}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {/* CTA Buttons */}\r\n <div className=\"flex w-full flex-col gap-3 sm:flex-row sm:w-auto\">\r\n <Button asChild size=\"lg\" className=\"w-full sm:w-auto\">\r\n <Link to=\"/register\">\r\n {t(\"primaryCta\", \"Get Started Free\")}\r\n </Link>\r\n </Button>\r\n <Button asChild variant=\"outline\" size=\"lg\" className=\"w-full sm:w-auto\">\r\n <Link to=\"/about\">\r\n {t(\"secondaryCta\", \"Learn More\")}\r\n <ArrowRight className=\"ml-2 h-4 w-4\" />\r\n </Link>\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n {/* Image Column */}\r\n <div className=\"relative order-first lg:order-last\">\r\n <div className=\"aspect-[4/3] overflow-hidden rounded-2xl bg-muted\">\r\n <img\r\n src=\"/images/placeholder.png\"\r\n alt={t(\"imageAlt\", \"Hero image\")}\r\n className=\"h-full w-full object-cover\"\r\n onError={(e) => {\r\n e.currentTarget.style.display = \"none\";\r\n }}\r\n />\r\n </div>\r\n {/* Decorative gradient blur */}\r\n <div className=\"absolute -z-10 -bottom-4 -right-4 h-72 w-72 rounded-full bg-primary/20 blur-3xl\" />\r\n </div>\r\n </div>\r\n </div>\r\n </section>\r\n );\r\n}\r\n"
|
|
21
|
+
"content": "import { Link } from \"react-router\";\r\nimport { ArrowRight, Star } from \"lucide-react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { Avatar, AvatarImage, AvatarFallback } from \"@/components/ui/avatar\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\ninterface HeroCtaProps {\r\n className?: string;\r\n}\r\n\r\nexport function HeroCta({ className }: HeroCtaProps) {\r\n const { t } = useTranslation(\"hero-cta\");\r\n\r\n const avatars = [\r\n { src: \"/images/placeholder.png\", alt: \"User 1\", fallback: \"U1\" },\r\n { src: \"/images/placeholder.png\", alt: \"User 2\", fallback: \"U2\" },\r\n { src: \"/images/placeholder.png\", alt: \"User 3\", fallback: \"U3\" },\r\n { src: \"/images/placeholder.png\", alt: \"User 4\", fallback: \"U4\" },\r\n { src: \"/images/placeholder.png\", alt: \"User 5\", fallback: \"U5\" },\r\n ];\r\n\r\n return (\r\n <section className={cn(\"py-16 md:py-24 lg:py-32\", className)}>\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"grid items-center gap-10 lg:grid-cols-2 lg:gap-16\">\r\n {/* Content Column */}\r\n <div className=\"flex flex-col items-center text-center lg:items-start lg:text-left\">\r\n <h1 className=\"mb-6 text-3xl font-bold text-pretty sm:text-4xl lg:text-5xl xl:text-6xl leading-tight\">\r\n {t(\"heading\", \"Build something amazing with our platform\")}\r\n </h1>\r\n <p className=\"mb-8 max-w-xl text-muted-foreground text-base lg:text-lg\">\r\n {t(\"description\", \"Create beautiful, responsive applications with ease. Our tools help you ship faster and build better products.\")}\r\n </p>\r\n\r\n {/* Social Proof */}\r\n <div className=\"mb-10 flex flex-col items-center gap-4 sm:flex-row lg:items-start\">\r\n <div className=\"flex -space-x-3\">\r\n {avatars.map((avatar, index) => (\r\n <Avatar key={index} className=\"h-10 w-10 border-2 border-background\">\r\n <AvatarImage src={avatar.src} alt={avatar.alt} />\r\n <AvatarFallback className=\"text-xs\">{avatar.fallback}</AvatarFallback>\r\n </Avatar>\r\n ))}\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-1\">\r\n {[...Array(5)].map((_, index) => (\r\n <Star\r\n key={index}\r\n className=\"h-4 w-4 fill-yellow-400 text-yellow-400\"\r\n />\r\n ))}\r\n <span className=\"ml-1 font-semibold text-sm\">5.0</span>\r\n </div>\r\n <p className=\"text-sm text-muted-foreground\">\r\n {t(\"reviews\", \"from 200+ happy users\")}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n {/* CTA Buttons */}\r\n <div className=\"flex w-full flex-col gap-3 sm:flex-row sm:w-auto\">\r\n <Button asChild size=\"lg\" className=\"w-full sm:w-auto\">\r\n <Link to=\"/register\">\r\n {t(\"primaryCta\", \"Get Started Free\")}\r\n </Link>\r\n </Button>\r\n <Button asChild variant=\"outline\" size=\"lg\" className=\"w-full sm:w-auto\">\r\n <Link to=\"/about\">\r\n {t(\"secondaryCta\", \"Learn More\")}\r\n <ArrowRight className=\"ml-2 h-4 w-4\" />\r\n </Link>\r\n </Button>\r\n </div>\r\n </div>\r\n\r\n {/* Image Column */}\r\n <div className=\"relative order-first lg:order-last\">\r\n <div className=\"aspect-[4/3] overflow-hidden rounded-2xl bg-muted\">\r\n <img\r\n src=\"/images/placeholder.png\"\r\n alt={t(\"imageAlt\", \"Hero image\")}\r\n className=\"h-full w-full object-cover\"\r\n onError={(e) => {\r\n e.currentTarget.style.display = \"none\";\r\n }}\r\n />\r\n </div>\r\n {/* Decorative gradient blur */}\r\n <div className=\"absolute -z-10 -bottom-4 -right-4 h-72 w-72 rounded-full bg-primary/20 blur-3xl\" />\r\n </div>\r\n </div>\r\n </div>\r\n </section>\r\n );\r\n}\r\n"
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"path": "hero-cta/lang/en.json",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"path": "hero-gradient/hero-gradient.tsx",
|
|
17
17
|
"type": "registry:component",
|
|
18
18
|
"target": "$modules$/hero-gradient/hero-gradient.tsx",
|
|
19
|
-
"content": "import { Link } from \"react-router\";\r\nimport { ArrowRight } from \"lucide-react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\ninterface HeroGradientProps {\r\n className?: string;\r\n}\r\n\r\nexport function HeroGradient({ className }: HeroGradientProps) {\r\n const { t } = useTranslation(\"hero-gradient\");\r\n\r\n return (\r\n <section\r\n className={cn(\r\n \"relative min-h-[70vh] flex items-center justify-center overflow-hidden\",\r\n className\r\n )}\r\n >\r\n {/* Gradient Background */}\r\n <div className=\"absolute inset-0 bg-gradient-to-br from-primary/20 via-background to-primary/10\" />\r\n\r\n {/* Animated gradient orbs */}\r\n <div className=\"absolute top-1/4 left-1/4 h-96 w-96 rounded-full bg-primary/30 blur-3xl animate-pulse\" />\r\n <div className=\"absolute bottom-1/4 right-1/4 h-80 w-80 rounded-full bg-primary/20 blur-3xl animate-pulse delay-700\" />\r\n\r\n {/* Grid pattern overlay */}\r\n <div className=\"absolute inset-0 bg-[linear-gradient(to_right,hsl(var(--border)/0.1)_1px,transparent_1px),linear-gradient(to_bottom,hsl(var(--border)/0.1)_1px,transparent_1px)] bg-[size:4rem_4rem]\" />\r\n\r\n {/* Content */}\r\n <div className=\"container mx-auto px-4 relative z-10\">\r\n <div className=\"max-w-4xl mx-auto text-center\">\r\n {/* Badge */}\r\n <div className=\"inline-flex items-center gap-2 rounded-full border border-border/50 bg-background/50 backdrop-blur-sm px-4 py-1.5 text-sm mb-8\">\r\n <span className=\"relative flex h-2 w-2\">\r\n <span className=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75\" />\r\n <span className=\"relative inline-flex rounded-full h-2 w-2 bg-primary\" />\r\n </span>\r\n {t(\"badge\", \"New features available\")}\r\n </div>\r\n\r\n {/* Heading */}\r\n <h1 className=\"text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold tracking-tight mb-6 leading-tight\">\r\n {t(\"headingLine1\", \"Transform your ideas\")}\r\n <br />\r\n <span className=\"bg-gradient-to-r from-primary to-primary/60 bg-clip-text text-transparent\">\r\n {t(\"headingLine2\", \"into reality\")}\r\n </span>\r\n </h1>\r\n\r\n {/* Description */}\r\n <p className=\"text-lg md:text-xl text-muted-foreground max-w-2xl mx-auto mb-10\">\r\n {t(\"description\", \"A powerful platform that helps you build, deploy, and scale your applications with ease. Start your journey today.\")}\r\n </p>\r\n\r\n {/* CTA Buttons */}\r\n <div className=\"flex flex-col sm:flex-row gap-4 justify-center\">\r\n <Button asChild size=\"lg\" className=\"text-base px-8\">\r\n <Link to=\"/register\">\r\n {t(\"primaryCta\", \"Start Building\")}\r\n <ArrowRight className=\"ml-2 h-4 w-4\" />\r\n </Link>\r\n </Button>\r\n <Button asChild variant=\"outline\" size=\"lg\" className=\"text-base px-8\">\r\n <Link to=\"/contact\">\r\n {t(\"secondaryCta\", \"Contact Sales\")}\r\n </Link>\r\n </Button>\r\n </div>\r\n\r\n {/* Trust badges */}\r\n <div className=\"mt-12 flex flex-wrap items-center justify-center gap-8 text-muted-foreground\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl font-bold text-foreground\">10K+</span>\r\n <span className=\"text-sm\">{t(\"users\", \"Active Users\")}</span>\r\n </div>\r\n <div className=\"h-8 w-px bg-border hidden sm:block\" />\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl font-bold text-foreground\">99.9%</span>\r\n <span className=\"text-sm\">{t(\"uptime\", \"Uptime\")}</span>\r\n </div>\r\n <div className=\"h-8 w-px bg-border hidden sm:block\" />\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl font-bold text-foreground\">24/7</span>\r\n <span className=\"text-sm\">{t(\"support\", \"Support\")}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </section>\r\n );\r\n}\r\n"
|
|
19
|
+
"content": "import { Link } from \"react-router\";\r\nimport { ArrowRight } from \"lucide-react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\ninterface HeroGradientProps {\r\n className?: string;\r\n}\r\n\r\nexport function HeroGradient({ className }: HeroGradientProps) {\r\n const { t } = useTranslation(\"hero-gradient\");\r\n\r\n return (\r\n <section\r\n className={cn(\r\n \"relative min-h-[70vh] flex items-center justify-center overflow-hidden\",\r\n className\r\n )}\r\n >\r\n {/* Gradient Background */}\r\n <div className=\"absolute inset-0 bg-gradient-to-br from-primary/20 via-background to-primary/10\" />\r\n\r\n {/* Animated gradient orbs */}\r\n <div className=\"absolute top-1/4 left-1/4 h-96 w-96 rounded-full bg-primary/30 blur-3xl animate-pulse\" />\r\n <div className=\"absolute bottom-1/4 right-1/4 h-80 w-80 rounded-full bg-primary/20 blur-3xl animate-pulse delay-700\" />\r\n\r\n {/* Grid pattern overlay */}\r\n <div className=\"absolute inset-0 bg-[linear-gradient(to_right,hsl(var(--border)/0.1)_1px,transparent_1px),linear-gradient(to_bottom,hsl(var(--border)/0.1)_1px,transparent_1px)] bg-[size:4rem_4rem]\" />\r\n\r\n {/* Content */}\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4 relative z-10\">\r\n <div className=\"max-w-4xl mx-auto text-center\">\r\n {/* Badge */}\r\n <div className=\"inline-flex items-center gap-2 rounded-full border border-border/50 bg-background/50 backdrop-blur-sm px-4 py-1.5 text-sm mb-8\">\r\n <span className=\"relative flex h-2 w-2\">\r\n <span className=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75\" />\r\n <span className=\"relative inline-flex rounded-full h-2 w-2 bg-primary\" />\r\n </span>\r\n {t(\"badge\", \"New features available\")}\r\n </div>\r\n\r\n {/* Heading */}\r\n <h1 className=\"text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold tracking-tight mb-6 leading-tight\">\r\n {t(\"headingLine1\", \"Transform your ideas\")}\r\n <br />\r\n <span className=\"bg-gradient-to-r from-primary to-primary/60 bg-clip-text text-transparent\">\r\n {t(\"headingLine2\", \"into reality\")}\r\n </span>\r\n </h1>\r\n\r\n {/* Description */}\r\n <p className=\"text-lg md:text-xl text-muted-foreground max-w-2xl mx-auto mb-10\">\r\n {t(\"description\", \"A powerful platform that helps you build, deploy, and scale your applications with ease. Start your journey today.\")}\r\n </p>\r\n\r\n {/* CTA Buttons */}\r\n <div className=\"flex flex-col sm:flex-row gap-4 justify-center\">\r\n <Button asChild size=\"lg\" className=\"text-base px-8\">\r\n <Link to=\"/register\">\r\n {t(\"primaryCta\", \"Start Building\")}\r\n <ArrowRight className=\"ml-2 h-4 w-4\" />\r\n </Link>\r\n </Button>\r\n <Button asChild variant=\"outline\" size=\"lg\" className=\"text-base px-8\">\r\n <Link to=\"/contact\">\r\n {t(\"secondaryCta\", \"Contact Sales\")}\r\n </Link>\r\n </Button>\r\n </div>\r\n\r\n {/* Trust badges */}\r\n <div className=\"mt-12 flex flex-wrap items-center justify-center gap-8 text-muted-foreground\">\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl font-bold text-foreground\">10K+</span>\r\n <span className=\"text-sm\">{t(\"users\", \"Active Users\")}</span>\r\n </div>\r\n <div className=\"h-8 w-px bg-border hidden sm:block\" />\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl font-bold text-foreground\">99.9%</span>\r\n <span className=\"text-sm\">{t(\"uptime\", \"Uptime\")}</span>\r\n </div>\r\n <div className=\"h-8 w-px bg-border hidden sm:block\" />\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-2xl font-bold text-foreground\">24/7</span>\r\n <span className=\"text-sm\">{t(\"support\", \"Support\")}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </section>\r\n );\r\n}\r\n"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"path": "hero-gradient/lang/en.json",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"path": "hero-profile/hero-profile.tsx",
|
|
20
20
|
"type": "registry:component",
|
|
21
21
|
"target": "$modules$/hero-profile/hero-profile.tsx",
|
|
22
|
-
"content": "import { useTranslation } from \"react-i18next\";\nimport { Facebook, Linkedin, Twitter, Github, Instagram } from \"lucide-react\";\nimport { motion } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\nconst socialLinks = [\n { icon: Facebook, href: \"#\", label: \"Facebook\" },\n { icon: Twitter, href: \"#\", label: \"Twitter\" },\n { icon: Linkedin, href: \"#\", label: \"LinkedIn\" },\n { icon: Github, href: \"#\", label: \"GitHub\" },\n { icon: Instagram, href: \"#\", label: \"Instagram\" },\n];\n\nexport function HeroProfile() {\n const { t } = useTranslation(\"hero-profile\");\n const companies = [\"Walmart\", \"LinkedIn\", \"Google\", \"Slack\", \"Amazon\"];\n\n return (\n <section className=\"relative min-h-[80vh] flex items-center overflow-hidden\">\n {/* Background */}\n <div className=\"absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-primary/10\" />\n\n {/* Content */}\n <div className=\"container mx-auto px-4 relative z-10 py-12\">\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-8\">\n {/* Left Column - Profile Card */}\n <motion.div\n initial={{ opacity: 0, x: -50 }}\n animate={{ opacity: 1, x: 0 }}\n transition={{ duration: 0.6, ease: \"easeOut\" }}\n className=\"lg:col-span-1 flex\"\n >\n <div className=\"bg-card/80 backdrop-blur-lg rounded-3xl p-6 md:p-8 text-center space-y-6 border border-border/50 shadow-xl flex flex-col justify-center w-full\">\n {/* Profile Image */}\n <motion.div\n initial={{ scale: 0.8, opacity: 0 }}\n animate={{ scale: 1, opacity: 1 }}\n transition={{ duration: 0.5, delay: 0.2 }}\n className=\"relative mx-auto w-40 h-40 sm:w-48 sm:h-48\"\n >\n <div className=\"absolute inset-0 bg-gradient-to-br from-primary to-primary/50 rounded-full blur-xl opacity-30 animate-pulse\" />\n <img\n src=\"/images/placeholder.png\"\n alt={t(\"name\")}\n className=\"relative w-full h-full object-cover object-center rounded-full border-4 border-primary/20 shadow-lg\"\n onError={(e) => {\n e.currentTarget.style.display = \"none\";\n }}\n />\n </motion.div>\n\n {/* Name and Bio */}\n <motion.div\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.5, delay: 0.3 }}\n className=\"space-y-2\"\n >\n <h1 className=\"text-2xl sm:text-3xl font-bold\">{t(\"name\")}</h1>\n <p className=\"text-muted-foreground\">{t(\"bio\")}</p>\n </motion.div>\n\n {/* Social Media Icons */}\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.5, delay: 0.4 }}\n className=\"flex justify-center gap-2\"\n >\n {socialLinks.slice(0, 4).map((social, index) => {\n const Icon = social.icon;\n return (\n <motion.a\n key={social.label}\n href={social.href}\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={{ duration: 0.3, delay: 0.5 + index * 0.1 }}\n whileHover={{ scale: 1.1, y: -2 }}\n whileTap={{ scale: 0.95 }}\n className={cn(\n \"w-10 h-10 rounded-full flex items-center justify-center\",\n \"bg-muted/50 text-muted-foreground\",\n \"hover:bg-primary hover:text-primary-foreground\",\n \"transition-colors duration-300 shadow-sm\"\n )}\n >\n <Icon className=\"w-4 h-4\" />\n </motion.a>\n );\n })}\n </motion.div>\n </div>\n </motion.div>\n\n {/* Right Column - Two Cards */}\n <div className=\"lg:col-span-2 flex flex-col gap-6\">\n {/* Top Card - Introduction */}\n <motion.div\n initial={{ opacity: 0, y: 30 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.6, delay: 0.2 }}\n className=\"bg-card/80 backdrop-blur-lg rounded-3xl p-6 md:p-8 border border-border/50 shadow-xl flex-1 flex flex-col justify-center\"\n >\n <div className=\"space-y-4\">\n <motion.p\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ delay: 0.4 }}\n className=\"text-sm text-muted-foreground\"\n >\n {t(\"greeting\")}\n </motion.p>\n\n <motion.h2\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ delay: 0.5 }}\n className=\"text-2xl sm:text-3xl lg:text-4xl font-bold leading-tight\"\n >\n {t(\"intro\")}\n </motion.h2>\n\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ delay: 0.6 }}\n className=\"flex items-center gap-2\"\n >\n <span className=\"inline-flex items-center gap-2 px-4 py-2 bg-primary/10 rounded-full text-sm font-medium text-primary\">\n <span className=\"w-2 h-2 bg-green-500 rounded-full animate-pulse\" />\n {t(\"freelancing\")}\n </span>\n </motion.div>\n </div>\n </motion.div>\n\n {/* Bottom Card - Companies Marquee */}\n <motion.div\n initial={{ opacity: 0, y: 30 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.6, delay: 0.4 }}\n className=\"bg-card/80 backdrop-blur-lg rounded-3xl p-6 md:p-8 border border-border/50 shadow-xl overflow-hidden flex-1 flex flex-col justify-center\"\n >\n <h3 className=\"text-lg font-semibold mb-6\">\n {t(\"companiesTitle\")}\n </h3>\n\n <div className=\"relative overflow-hidden\">\n {/* Gradient masks */}\n <div className=\"absolute left-0 top-0 bottom-0 w-20 bg-gradient-to-r from-card to-transparent z-10\" />\n <div className=\"absolute right-0 top-0 bottom-0 w-20 bg-gradient-to-l from-card to-transparent z-10\" />\n\n {/* Scrolling container */}\n <motion.div\n animate={{ x: [0, -1000] }}\n transition={{\n x: {\n repeat: Infinity,\n repeatType: \"loop\",\n duration: 20,\n ease: \"linear\",\n },\n }}\n className=\"flex gap-16 whitespace-nowrap\"\n >\n {[...companies, ...companies, ...companies].map(\n (company, index) => (\n <div\n key={index}\n className=\"text-xl font-bold text-muted-foreground/70 hover:text-foreground transition-colors\"\n >\n {company}\n </div>\n )\n )}\n </motion.div>\n </div>\n </motion.div>\n </div>\n </div>\n </div>\n </section>\n );\n}\n"
|
|
22
|
+
"content": "import { useTranslation } from \"react-i18next\";\nimport { Facebook, Linkedin, Twitter, Github, Instagram } from \"lucide-react\";\nimport { motion } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\nconst socialLinks = [\n { icon: Facebook, href: \"#\", label: \"Facebook\" },\n { icon: Twitter, href: \"#\", label: \"Twitter\" },\n { icon: Linkedin, href: \"#\", label: \"LinkedIn\" },\n { icon: Github, href: \"#\", label: \"GitHub\" },\n { icon: Instagram, href: \"#\", label: \"Instagram\" },\n];\n\nexport function HeroProfile() {\n const { t } = useTranslation(\"hero-profile\");\n const companies = [\"Walmart\", \"LinkedIn\", \"Google\", \"Slack\", \"Amazon\"];\n\n return (\n <section className=\"relative min-h-[80vh] flex items-center overflow-hidden\">\n {/* Background */}\n <div className=\"absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-primary/10\" />\n\n {/* Content */}\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4 relative z-10 py-12\">\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-8\">\n {/* Left Column - Profile Card */}\n <motion.div\n initial={{ opacity: 0, x: -50 }}\n animate={{ opacity: 1, x: 0 }}\n transition={{ duration: 0.6, ease: \"easeOut\" }}\n className=\"lg:col-span-1 flex\"\n >\n <div className=\"bg-card/80 backdrop-blur-lg rounded-3xl p-6 md:p-8 text-center space-y-6 border border-border/50 shadow-xl flex flex-col justify-center w-full\">\n {/* Profile Image */}\n <motion.div\n initial={{ scale: 0.8, opacity: 0 }}\n animate={{ scale: 1, opacity: 1 }}\n transition={{ duration: 0.5, delay: 0.2 }}\n className=\"relative mx-auto w-40 h-40 sm:w-48 sm:h-48\"\n >\n <div className=\"absolute inset-0 bg-gradient-to-br from-primary to-primary/50 rounded-full blur-xl opacity-30 animate-pulse\" />\n <img\n src=\"/images/placeholder.png\"\n alt={t(\"name\")}\n className=\"relative w-full h-full object-cover object-center rounded-full border-4 border-primary/20 shadow-lg\"\n onError={(e) => {\n e.currentTarget.style.display = \"none\";\n }}\n />\n </motion.div>\n\n {/* Name and Bio */}\n <motion.div\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.5, delay: 0.3 }}\n className=\"space-y-2\"\n >\n <h1 className=\"text-2xl sm:text-3xl font-bold\">{t(\"name\")}</h1>\n <p className=\"text-muted-foreground\">{t(\"bio\")}</p>\n </motion.div>\n\n {/* Social Media Icons */}\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.5, delay: 0.4 }}\n className=\"flex justify-center gap-2\"\n >\n {socialLinks.slice(0, 4).map((social, index) => {\n const Icon = social.icon;\n return (\n <motion.a\n key={social.label}\n href={social.href}\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={{ duration: 0.3, delay: 0.5 + index * 0.1 }}\n whileHover={{ scale: 1.1, y: -2 }}\n whileTap={{ scale: 0.95 }}\n className={cn(\n \"w-10 h-10 rounded-full flex items-center justify-center\",\n \"bg-muted/50 text-muted-foreground\",\n \"hover:bg-primary hover:text-primary-foreground\",\n \"transition-colors duration-300 shadow-sm\"\n )}\n >\n <Icon className=\"w-4 h-4\" />\n </motion.a>\n );\n })}\n </motion.div>\n </div>\n </motion.div>\n\n {/* Right Column - Two Cards */}\n <div className=\"lg:col-span-2 flex flex-col gap-6\">\n {/* Top Card - Introduction */}\n <motion.div\n initial={{ opacity: 0, y: 30 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.6, delay: 0.2 }}\n className=\"bg-card/80 backdrop-blur-lg rounded-3xl p-6 md:p-8 border border-border/50 shadow-xl flex-1 flex flex-col justify-center\"\n >\n <div className=\"space-y-4\">\n <motion.p\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ delay: 0.4 }}\n className=\"text-sm text-muted-foreground\"\n >\n {t(\"greeting\")}\n </motion.p>\n\n <motion.h2\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ delay: 0.5 }}\n className=\"text-2xl sm:text-3xl lg:text-4xl font-bold leading-tight\"\n >\n {t(\"intro\")}\n </motion.h2>\n\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ delay: 0.6 }}\n className=\"flex items-center gap-2\"\n >\n <span className=\"inline-flex items-center gap-2 px-4 py-2 bg-primary/10 rounded-full text-sm font-medium text-primary\">\n <span className=\"w-2 h-2 bg-green-500 rounded-full animate-pulse\" />\n {t(\"freelancing\")}\n </span>\n </motion.div>\n </div>\n </motion.div>\n\n {/* Bottom Card - Companies Marquee */}\n <motion.div\n initial={{ opacity: 0, y: 30 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.6, delay: 0.4 }}\n className=\"bg-card/80 backdrop-blur-lg rounded-3xl p-6 md:p-8 border border-border/50 shadow-xl overflow-hidden flex-1 flex flex-col justify-center\"\n >\n <h3 className=\"text-lg font-semibold mb-6\">\n {t(\"companiesTitle\")}\n </h3>\n\n <div className=\"relative overflow-hidden\">\n {/* Gradient masks */}\n <div className=\"absolute left-0 top-0 bottom-0 w-20 bg-gradient-to-r from-card to-transparent z-10\" />\n <div className=\"absolute right-0 top-0 bottom-0 w-20 bg-gradient-to-l from-card to-transparent z-10\" />\n\n {/* Scrolling container */}\n <motion.div\n animate={{ x: [0, -1000] }}\n transition={{\n x: {\n repeat: Infinity,\n repeatType: \"loop\",\n duration: 20,\n ease: \"linear\",\n },\n }}\n className=\"flex gap-16 whitespace-nowrap\"\n >\n {[...companies, ...companies, ...companies].map(\n (company, index) => (\n <div\n key={index}\n className=\"text-xl font-bold text-muted-foreground/70 hover:text-foreground transition-colors\"\n >\n {company}\n </div>\n )\n )}\n </motion.div>\n </div>\n </motion.div>\n </div>\n </div>\n </div>\n </section>\n );\n}\n"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"path": "hero-profile/lang/en.json",
|
package/dist/registry/hero.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"path": "hero/hero.tsx",
|
|
17
17
|
"type": "registry:component",
|
|
18
18
|
"target": "$modules$/hero/hero.tsx",
|
|
19
|
-
"content": "import { useTranslation } from \"react-i18next\";\n\nexport function Hero() {\n const { t } = useTranslation(\"hero\");\n\n return (\n <section className=\"relative min-h-[60vh] flex items-center overflow-hidden bg-gradient-to-br from-background via-muted/10 to-background\">\n {/* Background Image */}\n <div className=\"absolute inset-0\">\n {/* Background image will be placed here */}\n <img\n src=\"/images/placeholder.png\"\n alt=\"Hero Background\"\n className=\"w-full h-full object-cover\"\n onError={(e) => {\n // Hide broken image and keep gradient background\n e.currentTarget.style.display = \"none\";\n }}\n />\n\n {/* Dark overlay for text readability */}\n <div className=\"absolute inset-0 bg-gradient-to-r from-black/60 via-black/30 to-transparent\"></div>\n\n {/* Fallback gradient background */}\n <div className=\"absolute inset-0 bg-gradient-to-r from-primary/5 via-transparent to-primary/5\"></div>\n </div>\n\n {/* Content - Left Aligned with better contrast */}\n <div className=\"container mx-auto px-4 relative z-10\">\n <div className=\"max-w-2xl\">\n {/* Main Headline */}\n <div className=\"space-y-6 mb-8\">\n <h1 className=\"text-4xl md:text-5xl lg:text-6xl font-bold leading-normal text-white drop-shadow-lg pb-1\">\n <span>{t(\"discover\", \"Discover\")} </span>\n <span className=\"bg-gradient-to-r from-primary to-primary/80 bg-clip-text text-transparent\">\n {t(\"amazing\", \"Inspiring\")}\n </span>\n <br />\n <span>{t(\"content\", \"Stories\")}</span>\n </h1>\n\n <p className=\"text-xl text-white/90 max-w-lg leading-relaxed drop-shadow-md\">\n {t(\n \"subtitle\",\n \"Dive into a world of captivating narratives, expert insights, and thought-provoking content that inspires and educates.\"\n )}\n </p>\n </div>\n </div>\n </div>\n </section>\n );\n}\n"
|
|
19
|
+
"content": "import { useTranslation } from \"react-i18next\";\n\nexport function Hero() {\n const { t } = useTranslation(\"hero\");\n\n return (\n <section className=\"relative min-h-[60vh] flex items-center overflow-hidden bg-gradient-to-br from-background via-muted/10 to-background\">\n {/* Background Image */}\n <div className=\"absolute inset-0\">\n {/* Background image will be placed here */}\n <img\n src=\"/images/placeholder.png\"\n alt=\"Hero Background\"\n className=\"w-full h-full object-cover\"\n onError={(e) => {\n // Hide broken image and keep gradient background\n e.currentTarget.style.display = \"none\";\n }}\n />\n\n {/* Dark overlay for text readability */}\n <div className=\"absolute inset-0 bg-gradient-to-r from-black/60 via-black/30 to-transparent\"></div>\n\n {/* Fallback gradient background */}\n <div className=\"absolute inset-0 bg-gradient-to-r from-primary/5 via-transparent to-primary/5\"></div>\n </div>\n\n {/* Content - Left Aligned with better contrast */}\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4 relative z-10\">\n <div className=\"max-w-2xl\">\n {/* Main Headline */}\n <div className=\"space-y-6 mb-8\">\n <h1 className=\"text-4xl md:text-5xl lg:text-6xl font-bold leading-normal text-white drop-shadow-lg pb-1\">\n <span>{t(\"discover\", \"Discover\")} </span>\n <span className=\"bg-gradient-to-r from-primary to-primary/80 bg-clip-text text-transparent\">\n {t(\"amazing\", \"Inspiring\")}\n </span>\n <br />\n <span>{t(\"content\", \"Stories\")}</span>\n </h1>\n\n <p className=\"text-xl text-white/90 max-w-lg leading-relaxed drop-shadow-md\">\n {t(\n \"subtitle\",\n \"Dive into a world of captivating narratives, expert insights, and thought-provoking content that inspires and educates.\"\n )}\n </p>\n </div>\n </div>\n </div>\n </section>\n );\n}\n"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"path": "hero/lang/en.json",
|
package/dist/registry/index.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
[
|
|
2
2
|
"about-page",
|
|
3
3
|
"about-section",
|
|
4
|
+
"api",
|
|
5
|
+
"auth",
|
|
4
6
|
"animations",
|
|
5
7
|
"bento-grid-section",
|
|
6
8
|
"blog-core",
|
|
@@ -20,6 +22,7 @@
|
|
|
20
22
|
"content-section",
|
|
21
23
|
"cookies-page",
|
|
22
24
|
"cta-section",
|
|
25
|
+
"db",
|
|
23
26
|
"ecommerce-core",
|
|
24
27
|
"empty-page",
|
|
25
28
|
"faq-categorized",
|