@promakeai/cli 0.3.0 → 0.3.2

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.
Files changed (113) hide show
  1. package/dist/index.js +209 -415
  2. package/dist/registry/about-page.json +3 -3
  3. package/dist/registry/about-section.json +4 -4
  4. package/dist/registry/animations.json +2 -2
  5. package/dist/registry/announcement-bar.json +4 -4
  6. package/dist/registry/api.json +1 -1
  7. package/dist/registry/auth-core.json +3 -3
  8. package/dist/registry/bento-grid-section.json +4 -4
  9. package/dist/registry/blog-core.json +5 -5
  10. package/dist/registry/blog-list-page.json +3 -3
  11. package/dist/registry/blog-section.json +4 -4
  12. package/dist/registry/cards-carousel-section.json +4 -4
  13. package/dist/registry/cart-drawer.json +3 -3
  14. package/dist/registry/cart-page.json +3 -3
  15. package/dist/registry/case-study-page.json +3 -3
  16. package/dist/registry/category-section.json +3 -3
  17. package/dist/registry/checkout-page.json +3 -3
  18. package/dist/registry/coming-soon-page-minimal.json +4 -4
  19. package/dist/registry/coming-soon-page.json +4 -4
  20. package/dist/registry/contact-info-grid.json +4 -4
  21. package/dist/registry/contact-page-centered.json +4 -4
  22. package/dist/registry/contact-page-split.json +4 -4
  23. package/dist/registry/contact-page.json +3 -3
  24. package/dist/registry/content-section.json +4 -4
  25. package/dist/registry/cookie-consent.json +4 -4
  26. package/dist/registry/cookies-page.json +3 -3
  27. package/dist/registry/cta-section.json +3 -3
  28. package/dist/registry/ecommerce-core.json +10 -10
  29. package/dist/registry/empty-page.json +3 -3
  30. package/dist/registry/faq-categorized.json +4 -4
  31. package/dist/registry/faq-simple.json +4 -4
  32. package/dist/registry/favorites-blog-block.json +1 -1
  33. package/dist/registry/favorites-blog-page.json +4 -4
  34. package/dist/registry/favorites-ecommerce-block.json +1 -1
  35. package/dist/registry/favorites-ecommerce-page.json +4 -4
  36. package/dist/registry/feature-section.json +3 -3
  37. package/dist/registry/featured-products.json +3 -3
  38. package/dist/registry/footer-detailed.json +4 -4
  39. package/dist/registry/footer-minimal.json +3 -3
  40. package/dist/registry/footer.json +3 -3
  41. package/dist/registry/forgot-password-page-split.json +4 -4
  42. package/dist/registry/forgot-password-page.json +4 -4
  43. package/dist/registry/google-adsense.json +4 -4
  44. package/dist/registry/google-map.json +2 -2
  45. package/dist/registry/header-centered-pill.json +4 -4
  46. package/dist/registry/header-ecommerce.json +3 -3
  47. package/dist/registry/header-mega.json +4 -4
  48. package/dist/registry/header-minimal.json +4 -4
  49. package/dist/registry/header-simple.json +3 -3
  50. package/dist/registry/hero-carousel.json +3 -3
  51. package/dist/registry/hero-cta.json +4 -4
  52. package/dist/registry/hero-gradient.json +4 -4
  53. package/dist/registry/hero-grid.json +4 -4
  54. package/dist/registry/hero-profile.json +3 -3
  55. package/dist/registry/hero.json +3 -3
  56. package/dist/registry/landing-page-app.json +3 -3
  57. package/dist/registry/landing-page-saas.json +3 -3
  58. package/dist/registry/login-page-split.json +4 -4
  59. package/dist/registry/login-page.json +4 -4
  60. package/dist/registry/logo-cloud.json +4 -4
  61. package/dist/registry/masonry-grid.json +3 -3
  62. package/dist/registry/my-orders-page.json +4 -4
  63. package/dist/registry/newsletter-section.json +4 -4
  64. package/dist/registry/order-card-compact.json +1 -1
  65. package/dist/registry/order-confirmation-page.json +4 -4
  66. package/dist/registry/order-detail-block.json +1 -1
  67. package/dist/registry/orders-list-block.json +1 -1
  68. package/dist/registry/payment-success-block.json +1 -1
  69. package/dist/registry/portfolio-page.json +4 -4
  70. package/dist/registry/post-card.json +3 -3
  71. package/dist/registry/post-detail-block.json +1 -1
  72. package/dist/registry/post-detail-page.json +4 -4
  73. package/dist/registry/pricing-card.json +3 -3
  74. package/dist/registry/pricing-page.json +4 -4
  75. package/dist/registry/pricing-section.json +4 -4
  76. package/dist/registry/privacy-page.json +3 -3
  77. package/dist/registry/product-card-detailed.json +4 -4
  78. package/dist/registry/product-card-hover.json +4 -4
  79. package/dist/registry/product-card.json +3 -3
  80. package/dist/registry/product-detail-block.json +1 -1
  81. package/dist/registry/product-detail-page.json +4 -4
  82. package/dist/registry/product-detail-section.json +4 -4
  83. package/dist/registry/product-quick-view.json +4 -4
  84. package/dist/registry/products-page.json +3 -3
  85. package/dist/registry/reading-progress.json +4 -4
  86. package/dist/registry/register-page-split.json +4 -4
  87. package/dist/registry/register-page.json +4 -4
  88. package/dist/registry/related-posts-block.json +1 -1
  89. package/dist/registry/related-products-block.json +1 -1
  90. package/dist/registry/reset-password-page-split.json +4 -4
  91. package/dist/registry/service-card.json +1 -1
  92. package/dist/registry/share-buttons.json +4 -4
  93. package/dist/registry/skill-card.json +1 -1
  94. package/dist/registry/team-page.json +4 -4
  95. package/dist/registry/terms-page.json +3 -3
  96. package/dist/registry/testimonials-carousel.json +4 -4
  97. package/dist/registry/testimonials-grid.json +4 -4
  98. package/dist/registry/timeline-section.json +4 -4
  99. package/dist/registry/video-hero.json +4 -4
  100. package/dist/registry/youtube-embed.json +4 -4
  101. package/package.json +2 -2
  102. package/template/.env +6 -6
  103. package/template/public/_redirects +1 -1
  104. package/template/public/robots.txt +14 -14
  105. package/template/src/components/GoogleAnalytics.tsx +34 -34
  106. package/template/src/components/LanguageSwitcher.tsx +53 -53
  107. package/template/src/components/ScriptInjector.tsx +62 -62
  108. package/template/src/lib/env.ts +19 -19
  109. package/template/src/router.tsx +14 -14
  110. package/template/src/vite-env.d.ts +1 -1
  111. package/dist/registry/auth.json +0 -70
  112. package/dist/registry/docs/reset-password-page.md +0 -36
  113. package/dist/registry/reset-password-page.json +0 -39
@@ -17,25 +17,25 @@
17
17
  "path": "forgot-password-page/index.ts",
18
18
  "type": "registry:index",
19
19
  "target": "$modules$/forgot-password-page/index.ts",
20
- "content": "export * from './forgot-password-page';\r\nexport { default } from './forgot-password-page';\r\n"
20
+ "content": "export * from './forgot-password-page';\nexport { default } from './forgot-password-page';\n"
21
21
  },
22
22
  {
23
23
  "path": "forgot-password-page/forgot-password-page.tsx",
24
24
  "type": "registry:page",
25
25
  "target": "$modules$/forgot-password-page/forgot-password-page.tsx",
26
- "content": "import { useState } from \"react\";\r\nimport { Link } from \"react-router\";\r\nimport { toast } from \"sonner\";\r\nimport { Layout } from \"@/components/Layout\";\r\nimport { usePageTitle } from \"@/hooks/use-page-title\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAuth } from \"@/modules/auth-core\";\r\nimport { getErrorMessage } from \"@/modules/api\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { Input } from \"@/components/ui/input\";\r\nimport { Label } from \"@/components/ui/label\";\r\nimport {\r\n Card,\r\n CardContent,\r\n CardHeader,\r\n CardTitle,\r\n CardDescription,\r\n} from \"@/components/ui/card\";\r\nimport { KeyRound, ArrowLeft, Eye, EyeOff, CheckCircle2 } from \"lucide-react\";\r\n\r\ntype Step = \"request\" | \"reset\" | \"success\";\r\n\r\nexport function ForgotPasswordPage() {\r\n const { t } = useTranslation(\"forgot-password-page\");\r\n usePageTitle({ title: t(\"title\", \"Forgot Password\") });\r\n\r\n const { forgotPassword, resetPassword } = useAuth();\r\n\r\n const [step, setStep] = useState<Step>(\"request\");\r\n const [username, setUsername] = useState(\"\");\r\n const [code, setCode] = useState(\"\");\r\n const [newPassword, setNewPassword] = useState(\"\");\r\n const [confirmPassword, setConfirmPassword] = useState(\"\");\r\n const [showPassword, setShowPassword] = useState(false);\r\n const [isSubmitting, setIsSubmitting] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const handleRequestCode = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setIsSubmitting(true);\r\n setError(null);\r\n\r\n try {\r\n await forgotPassword(username);\r\n toast.success(t(\"codeSentTitle\", \"Code Sent!\"), {\r\n description: t(\r\n \"codeSentDesc\",\r\n \"A password reset code has been sent to your email.\",\r\n ),\r\n });\r\n setStep(\"reset\");\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"errorGeneric\", \"Failed to send reset code. Please try again.\"),\r\n );\r\n setError(errorMessage);\r\n toast.error(t(\"errorTitle\", \"Error\"), {\r\n description: errorMessage,\r\n });\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n const handleResetPassword = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n\r\n // Validate passwords match\r\n if (newPassword !== confirmPassword) {\r\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\r\n return;\r\n }\r\n\r\n setIsSubmitting(true);\r\n\r\n try {\r\n await resetPassword(username, code, newPassword);\r\n toast.success(t(\"resetSuccessTitle\", \"Password Reset!\"), {\r\n description: t(\r\n \"resetSuccessDesc\",\r\n \"Your password has been successfully reset.\",\r\n ),\r\n });\r\n setStep(\"success\");\r\n } catch (err) {\r\n const errorMessage = getErrorMessage(\r\n err,\r\n t(\"errorResetGeneric\", \"Failed to reset password. Please try again.\"),\r\n );\r\n setError(errorMessage);\r\n toast.error(t(\"errorTitle\", \"Error\"), {\r\n description: errorMessage,\r\n });\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n // Success step\r\n if (step === \"success\") {\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardContent className=\"pt-8 pb-8 text-center\">\r\n <CheckCircle2 className=\"w-16 h-16 text-green-500 mx-auto mb-4\" />\r\n <h1 className=\"text-2xl font-bold mb-2\">\r\n {t(\"successTitle\", \"Password Reset Successfully!\")}\r\n </h1>\r\n <p className=\"text-muted-foreground mb-6\">\r\n {t(\r\n \"successDescription\",\r\n \"Your password has been changed. You can now login with your new password.\",\r\n )}\r\n </p>\r\n <Button asChild className=\"w-full\">\r\n <Link to=\"/login\">{t(\"goToLogin\", \"Go to Login\")}</Link>\r\n </Button>\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n }\r\n\r\n return (\r\n <Layout>\r\n <div className=\"min-h-screen bg-muted/30 py-12\">\r\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\r\n {/* Hero Section */}\r\n <div className=\"text-center mb-12\">\r\n <h1 className=\"text-4xl font-bold text-foreground mb-4\">\r\n {t(\"title\", \"Forgot Password\")}\r\n </h1>\r\n <div className=\"w-16 h-1 bg-primary mx-auto mb-6\"></div>\r\n <p className=\"text-lg text-muted-foreground max-w-xl mx-auto\">\r\n {step === \"request\"\r\n ? t(\r\n \"descriptionRequest\",\r\n \"Enter your username and we'll send you a code to reset your password.\",\r\n )\r\n : t(\r\n \"descriptionReset\",\r\n \"Enter the code sent to your email and your new password.\",\r\n )}\r\n </p>\r\n </div>\r\n\r\n <div className=\"max-w-md mx-auto\">\r\n <Card>\r\n <CardHeader>\r\n <CardTitle className=\"flex items-center gap-2\">\r\n <KeyRound className=\"w-5 h-5 text-primary\" />\r\n {step === \"request\"\r\n ? t(\"cardTitleRequest\", \"Request Reset Code\")\r\n : t(\"cardTitleReset\", \"Reset Password\")}\r\n </CardTitle>\r\n <CardDescription>\r\n {step === \"request\"\r\n ? t(\"cardDescRequest\", \"Step 1 of 2: Request a reset code\")\r\n : t(\r\n \"cardDescReset\",\r\n \"Step 2 of 2: Enter code and new password\",\r\n )}\r\n </CardDescription>\r\n </CardHeader>\r\n <CardContent>\r\n {step === \"request\" ? (\r\n // Step 1: Request Code\r\n <form onSubmit={handleRequestCode} className=\"space-y-6\">\r\n <div>\r\n <Label htmlFor=\"username\">\r\n {t(\"username\", \"Username\")} *\r\n </Label>\r\n <Input\r\n id=\"username\"\r\n type=\"text\"\r\n value={username}\r\n onChange={(e) => setUsername(e.target.value)}\r\n placeholder={t(\r\n \"usernamePlaceholder\",\r\n \"Enter your username\",\r\n )}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"username\"\r\n />\r\n </div>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n size=\"lg\"\r\n className=\"w-full\"\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"sending\", \"Sending...\")}\r\n </>\r\n ) : (\r\n t(\"sendCode\", \"Send Reset Code\")\r\n )}\r\n </Button>\r\n\r\n <div className=\"text-center\">\r\n <Link\r\n to=\"/login\"\r\n className=\"text-sm text-muted-foreground hover:text-primary inline-flex items-center gap-1\"\r\n >\r\n <ArrowLeft className=\"w-4 h-4\" />\r\n {t(\"backToLogin\", \"Back to Login\")}\r\n </Link>\r\n </div>\r\n </form>\r\n ) : (\r\n // Step 2: Reset Password\r\n <form onSubmit={handleResetPassword} className=\"space-y-6\">\r\n <div className=\"p-3 bg-muted rounded-lg text-sm\">\r\n <span className=\"text-muted-foreground\">\r\n {t(\"codeFor\", \"Reset code for:\")}{\" \"}\r\n </span>\r\n <span className=\"font-medium\">{username}</span>\r\n </div>\r\n\r\n <div>\r\n <Label htmlFor=\"code\">{t(\"code\", \"Reset Code\")} *</Label>\r\n <Input\r\n id=\"code\"\r\n type=\"text\"\r\n value={code}\r\n onChange={(e) => setCode(e.target.value)}\r\n placeholder={t(\"codePlaceholder\", \"Enter 6-digit code\")}\r\n required\r\n className=\"mt-1\"\r\n maxLength={6}\r\n />\r\n </div>\r\n\r\n <div>\r\n <Label htmlFor=\"newPassword\">\r\n {t(\"newPassword\", \"New Password\")} *\r\n </Label>\r\n <div className=\"relative\">\r\n <Input\r\n id=\"newPassword\"\r\n type={showPassword ? \"text\" : \"password\"}\r\n value={newPassword}\r\n onChange={(e) => setNewPassword(e.target.value)}\r\n placeholder={t(\r\n \"newPasswordPlaceholder\",\r\n \"Enter new password\",\r\n )}\r\n required\r\n className=\"mt-1 pr-10\"\r\n autoComplete=\"new-password\"\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowPassword(!showPassword)}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\r\n >\r\n {showPassword ? (\r\n <EyeOff className=\"w-4 h-4\" />\r\n ) : (\r\n <Eye className=\"w-4 h-4\" />\r\n )}\r\n </button>\r\n </div>\r\n <p className=\"text-xs text-muted-foreground mt-1\">\r\n {t(\r\n \"passwordRequirements\",\r\n \"At least 8 characters, 1 letter and 1 number\",\r\n )}\r\n </p>\r\n </div>\r\n\r\n <div>\r\n <Label htmlFor=\"confirmPassword\">\r\n {t(\"confirmPassword\", \"Confirm Password\")} *\r\n </Label>\r\n <Input\r\n id=\"confirmPassword\"\r\n type={showPassword ? \"text\" : \"password\"}\r\n value={confirmPassword}\r\n onChange={(e) => setConfirmPassword(e.target.value)}\r\n placeholder={t(\r\n \"confirmPasswordPlaceholder\",\r\n \"Confirm new password\",\r\n )}\r\n required\r\n className=\"mt-1\"\r\n autoComplete=\"new-password\"\r\n />\r\n </div>\r\n\r\n {error && (\r\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\r\n <p className=\"text-red-800 text-sm font-medium\">\r\n {error}\r\n </p>\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n size=\"lg\"\r\n className=\"w-full\"\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? (\r\n <>\r\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2\" />\r\n {t(\"resetting\", \"Resetting...\")}\r\n </>\r\n ) : (\r\n t(\"resetPassword\", \"Reset Password\")\r\n )}\r\n </Button>\r\n\r\n <div className=\"flex justify-between\">\r\n <button\r\n type=\"button\"\r\n onClick={() => {\r\n setStep(\"request\");\r\n setCode(\"\");\r\n setNewPassword(\"\");\r\n setConfirmPassword(\"\");\r\n setError(null);\r\n }}\r\n className=\"text-sm text-muted-foreground hover:text-primary\"\r\n >\r\n {t(\"changeUsername\", \"Change username\")}\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={() =>\r\n handleRequestCode({\r\n preventDefault: () => {},\r\n } as React.FormEvent)\r\n }\r\n className=\"text-sm text-primary hover:underline\"\r\n disabled={isSubmitting}\r\n >\r\n {t(\"resendCode\", \"Resend code\")}\r\n </button>\r\n </div>\r\n </form>\r\n )}\r\n </CardContent>\r\n </Card>\r\n </div>\r\n </div>\r\n </div>\r\n </Layout>\r\n );\r\n}\r\n\r\nexport default ForgotPasswordPage;\r\n"
26
+ "content": "import { useState } from \"react\";\nimport { Link } from \"react-router\";\nimport { toast } from \"sonner\";\nimport { Layout } from \"@/components/Layout\";\nimport { usePageTitle } from \"@/hooks/use-page-title\";\nimport { useTranslation } from \"react-i18next\";\nimport { useAuth } from \"@/modules/auth-core\";\nimport { getErrorMessage } from \"@/modules/api\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n} from \"@/components/ui/card\";\nimport { KeyRound, ArrowLeft, Eye, EyeOff, CheckCircle2 } from \"lucide-react\";\n\ntype Step = \"request\" | \"reset\" | \"success\";\n\nexport function ForgotPasswordPage() {\n const { t } = useTranslation(\"forgot-password-page\");\n usePageTitle({ title: t(\"title\", \"Forgot Password\") });\n\n const { forgotPassword, resetPassword } = useAuth();\n\n const [step, setStep] = useState<Step>(\"request\");\n const [username, setUsername] = useState(\"\");\n const [code, setCode] = useState(\"\");\n const [newPassword, setNewPassword] = useState(\"\");\n const [confirmPassword, setConfirmPassword] = useState(\"\");\n const [showPassword, setShowPassword] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleRequestCode = async (e: React.FormEvent) => {\n e.preventDefault();\n setIsSubmitting(true);\n setError(null);\n\n try {\n await forgotPassword(username);\n toast.success(t(\"codeSentTitle\", \"Code Sent!\"), {\n description: t(\n \"codeSentDesc\",\n \"A password reset code has been sent to your email.\",\n ),\n });\n setStep(\"reset\");\n } catch (err) {\n const errorMessage = getErrorMessage(\n err,\n t(\"errorGeneric\", \"Failed to send reset code. Please try again.\"),\n );\n setError(errorMessage);\n toast.error(t(\"errorTitle\", \"Error\"), {\n description: errorMessage,\n });\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const handleResetPassword = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n\n // Validate passwords match\n if (newPassword !== confirmPassword) {\n setError(t(\"passwordMismatch\", \"Passwords do not match\"));\n return;\n }\n\n setIsSubmitting(true);\n\n try {\n await resetPassword(username, code, newPassword);\n toast.success(t(\"resetSuccessTitle\", \"Password Reset!\"), {\n description: t(\n \"resetSuccessDesc\",\n \"Your password has been successfully reset.\",\n ),\n });\n setStep(\"success\");\n } catch (err) {\n const errorMessage = getErrorMessage(\n err,\n t(\"errorResetGeneric\", \"Failed to reset password. Please try again.\"),\n );\n setError(errorMessage);\n toast.error(t(\"errorTitle\", \"Error\"), {\n description: errorMessage,\n });\n } finally {\n setIsSubmitting(false);\n }\n };\n\n // Success step\n if (step === \"success\") {\n return (\n <Layout>\n <div className=\"min-h-screen bg-muted/30 py-12\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n <div className=\"max-w-md mx-auto\">\n <Card>\n <CardContent className=\"pt-8 pb-8 text-center\">\n <CheckCircle2 className=\"w-16 h-16 text-green-500 mx-auto mb-4\" />\n <h1 className=\"text-2xl font-bold mb-2\">\n {t(\"successTitle\", \"Password Reset Successfully!\")}\n </h1>\n <p className=\"text-muted-foreground mb-6\">\n {t(\n \"successDescription\",\n \"Your password has been changed. You can now login with your new password.\",\n )}\n </p>\n <Button asChild className=\"w-full\">\n <Link to=\"/login\">{t(\"goToLogin\", \"Go to Login\")}</Link>\n </Button>\n </CardContent>\n </Card>\n </div>\n </div>\n </div>\n </Layout>\n );\n }\n\n return (\n <Layout>\n <div className=\"min-h-screen bg-muted/30 py-12\">\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n {/* Hero Section */}\n <div className=\"text-center mb-12\">\n <h1 className=\"text-4xl font-bold text-foreground mb-4\">\n {t(\"title\", \"Forgot Password\")}\n </h1>\n <div className=\"w-16 h-1 bg-primary mx-auto mb-6\"></div>\n <p className=\"text-lg text-muted-foreground max-w-xl mx-auto\">\n {step === \"request\"\n ? t(\n \"descriptionRequest\",\n \"Enter your username and we'll send you a code to reset your password.\",\n )\n : t(\n \"descriptionReset\",\n \"Enter the code sent to your email and your new password.\",\n )}\n </p>\n </div>\n\n <div className=\"max-w-md mx-auto\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <KeyRound className=\"w-5 h-5 text-primary\" />\n {step === \"request\"\n ? t(\"cardTitleRequest\", \"Request Reset Code\")\n : t(\"cardTitleReset\", \"Reset Password\")}\n </CardTitle>\n <CardDescription>\n {step === \"request\"\n ? t(\"cardDescRequest\", \"Step 1 of 2: Request a reset code\")\n : t(\n \"cardDescReset\",\n \"Step 2 of 2: Enter code and new password\",\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {step === \"request\" ? (\n // Step 1: Request Code\n <form onSubmit={handleRequestCode} className=\"space-y-6\">\n <div>\n <Label htmlFor=\"username\">\n {t(\"username\", \"Username\")} *\n </Label>\n <Input\n id=\"username\"\n type=\"text\"\n value={username}\n onChange={(e) => setUsername(e.target.value)}\n placeholder={t(\n \"usernamePlaceholder\",\n \"Enter your username\",\n )}\n required\n className=\"mt-1\"\n autoComplete=\"username\"\n />\n </div>\n\n {error && (\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\n <p className=\"text-red-800 text-sm font-medium\">\n {error}\n </p>\n </div>\n )}\n\n <Button\n type=\"submit\"\n size=\"lg\"\n className=\"w-full\"\n disabled={isSubmitting}\n >\n {isSubmitting ? (\n <>\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2\" />\n {t(\"sending\", \"Sending...\")}\n </>\n ) : (\n t(\"sendCode\", \"Send Reset Code\")\n )}\n </Button>\n\n <div className=\"text-center\">\n <Link\n to=\"/login\"\n className=\"text-sm text-muted-foreground hover:text-primary inline-flex items-center gap-1\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n {t(\"backToLogin\", \"Back to Login\")}\n </Link>\n </div>\n </form>\n ) : (\n // Step 2: Reset Password\n <form onSubmit={handleResetPassword} className=\"space-y-6\">\n <div className=\"p-3 bg-muted rounded-lg text-sm\">\n <span className=\"text-muted-foreground\">\n {t(\"codeFor\", \"Reset code for:\")}{\" \"}\n </span>\n <span className=\"font-medium\">{username}</span>\n </div>\n\n <div>\n <Label htmlFor=\"code\">{t(\"code\", \"Reset Code\")} *</Label>\n <Input\n id=\"code\"\n type=\"text\"\n value={code}\n onChange={(e) => setCode(e.target.value)}\n placeholder={t(\"codePlaceholder\", \"Enter 6-digit code\")}\n required\n className=\"mt-1\"\n maxLength={6}\n />\n </div>\n\n <div>\n <Label htmlFor=\"newPassword\">\n {t(\"newPassword\", \"New Password\")} *\n </Label>\n <div className=\"relative\">\n <Input\n id=\"newPassword\"\n type={showPassword ? \"text\" : \"password\"}\n value={newPassword}\n onChange={(e) => setNewPassword(e.target.value)}\n placeholder={t(\n \"newPasswordPlaceholder\",\n \"Enter new password\",\n )}\n required\n className=\"mt-1 pr-10\"\n autoComplete=\"new-password\"\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword(!showPassword)}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n >\n {showPassword ? (\n <EyeOff className=\"w-4 h-4\" />\n ) : (\n <Eye className=\"w-4 h-4\" />\n )}\n </button>\n </div>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {t(\n \"passwordRequirements\",\n \"At least 8 characters, 1 letter and 1 number\",\n )}\n </p>\n </div>\n\n <div>\n <Label htmlFor=\"confirmPassword\">\n {t(\"confirmPassword\", \"Confirm Password\")} *\n </Label>\n <Input\n id=\"confirmPassword\"\n type={showPassword ? \"text\" : \"password\"}\n value={confirmPassword}\n onChange={(e) => setConfirmPassword(e.target.value)}\n placeholder={t(\n \"confirmPasswordPlaceholder\",\n \"Confirm new password\",\n )}\n required\n className=\"mt-1\"\n autoComplete=\"new-password\"\n />\n </div>\n\n {error && (\n <div className=\"p-4 bg-red-50 border border-red-200 rounded-lg\">\n <p className=\"text-red-800 text-sm font-medium\">\n {error}\n </p>\n </div>\n )}\n\n <Button\n type=\"submit\"\n size=\"lg\"\n className=\"w-full\"\n disabled={isSubmitting}\n >\n {isSubmitting ? (\n <>\n <div className=\"w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2\" />\n {t(\"resetting\", \"Resetting...\")}\n </>\n ) : (\n t(\"resetPassword\", \"Reset Password\")\n )}\n </Button>\n\n <div className=\"flex justify-between\">\n <button\n type=\"button\"\n onClick={() => {\n setStep(\"request\");\n setCode(\"\");\n setNewPassword(\"\");\n setConfirmPassword(\"\");\n setError(null);\n }}\n className=\"text-sm text-muted-foreground hover:text-primary\"\n >\n {t(\"changeUsername\", \"Change username\")}\n </button>\n <button\n type=\"button\"\n onClick={() =>\n handleRequestCode({\n preventDefault: () => {},\n } as React.FormEvent)\n }\n className=\"text-sm text-primary hover:underline\"\n disabled={isSubmitting}\n >\n {t(\"resendCode\", \"Resend code\")}\n </button>\n </div>\n </form>\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n </div>\n </Layout>\n );\n}\n\nexport default ForgotPasswordPage;\n"
27
27
  },
28
28
  {
29
29
  "path": "forgot-password-page/lang/en.json",
30
30
  "type": "registry:lang",
31
31
  "target": "$modules$/forgot-password-page/lang/en.json",
32
- "content": "{\r\n \"title\": \"Forgot Password\",\r\n \"descriptionRequest\": \"Enter your username and we'll send you a code to reset your password.\",\r\n \"descriptionReset\": \"Enter the code sent to your email and your new password.\",\r\n \"cardTitleRequest\": \"Request Reset Code\",\r\n \"cardTitleReset\": \"Reset Password\",\r\n \"cardDescRequest\": \"Step 1 of 2: Request a reset code\",\r\n \"cardDescReset\": \"Step 2 of 2: Enter code and new password\",\r\n \"username\": \"Username\",\r\n \"usernamePlaceholder\": \"Enter your username\",\r\n \"code\": \"Reset Code\",\r\n \"codePlaceholder\": \"Enter 6-digit code\",\r\n \"codeFor\": \"Reset code for:\",\r\n \"newPassword\": \"New Password\",\r\n \"newPasswordPlaceholder\": \"Enter new password\",\r\n \"confirmPassword\": \"Confirm Password\",\r\n \"confirmPasswordPlaceholder\": \"Confirm new password\",\r\n \"passwordRequirements\": \"At least 8 characters, 1 letter and 1 number\",\r\n \"passwordMismatch\": \"Passwords do not match\",\r\n \"sendCode\": \"Send Reset Code\",\r\n \"sending\": \"Sending...\",\r\n \"resetPassword\": \"Reset Password\",\r\n \"resetting\": \"Resetting...\",\r\n \"backToLogin\": \"Back to Login\",\r\n \"changeUsername\": \"Change username\",\r\n \"resendCode\": \"Resend code\",\r\n \"codeSentTitle\": \"Code Sent!\",\r\n \"codeSentDesc\": \"A password reset code has been sent to your email.\",\r\n \"errorTitle\": \"Error\",\r\n \"errorGeneric\": \"Failed to send reset code. Please try again.\",\r\n \"errorResetGeneric\": \"Failed to reset password. Please try again.\",\r\n \"resetSuccessTitle\": \"Password Reset!\",\r\n \"resetSuccessDesc\": \"Your password has been successfully reset.\",\r\n \"successTitle\": \"Password Reset Successfully!\",\r\n \"successDescription\": \"Your password has been changed. You can now login with your new password.\",\r\n \"goToLogin\": \"Go to Login\"\r\n}\r\n"
32
+ "content": "{\n \"title\": \"Forgot Password\",\n \"descriptionRequest\": \"Enter your username and we'll send you a code to reset your password.\",\n \"descriptionReset\": \"Enter the code sent to your email and your new password.\",\n \"cardTitleRequest\": \"Request Reset Code\",\n \"cardTitleReset\": \"Reset Password\",\n \"cardDescRequest\": \"Step 1 of 2: Request a reset code\",\n \"cardDescReset\": \"Step 2 of 2: Enter code and new password\",\n \"username\": \"Username\",\n \"usernamePlaceholder\": \"Enter your username\",\n \"code\": \"Reset Code\",\n \"codePlaceholder\": \"Enter 6-digit code\",\n \"codeFor\": \"Reset code for:\",\n \"newPassword\": \"New Password\",\n \"newPasswordPlaceholder\": \"Enter new password\",\n \"confirmPassword\": \"Confirm Password\",\n \"confirmPasswordPlaceholder\": \"Confirm new password\",\n \"passwordRequirements\": \"At least 8 characters, 1 letter and 1 number\",\n \"passwordMismatch\": \"Passwords do not match\",\n \"sendCode\": \"Send Reset Code\",\n \"sending\": \"Sending...\",\n \"resetPassword\": \"Reset Password\",\n \"resetting\": \"Resetting...\",\n \"backToLogin\": \"Back to Login\",\n \"changeUsername\": \"Change username\",\n \"resendCode\": \"Resend code\",\n \"codeSentTitle\": \"Code Sent!\",\n \"codeSentDesc\": \"A password reset code has been sent to your email.\",\n \"errorTitle\": \"Error\",\n \"errorGeneric\": \"Failed to send reset code. Please try again.\",\n \"errorResetGeneric\": \"Failed to reset password. Please try again.\",\n \"resetSuccessTitle\": \"Password Reset!\",\n \"resetSuccessDesc\": \"Your password has been successfully reset.\",\n \"successTitle\": \"Password Reset Successfully!\",\n \"successDescription\": \"Your password has been changed. You can now login with your new password.\",\n \"goToLogin\": \"Go to Login\"\n}\n"
33
33
  },
34
34
  {
35
35
  "path": "forgot-password-page/lang/tr.json",
36
36
  "type": "registry:lang",
37
37
  "target": "$modules$/forgot-password-page/lang/tr.json",
38
- "content": "{\r\n \"title\": \"Şifremi Unuttum\",\r\n \"descriptionRequest\": \"Kullanıcı adınızı girin, size şifre sıfırlama kodu göndereceğiz.\",\r\n \"descriptionReset\": \"E-postanıza gönderilen kodu ve yeni şifrenizi girin.\",\r\n \"cardTitleRequest\": \"Sıfırlama Kodu İste\",\r\n \"cardTitleReset\": \"Şifre Sıfırla\",\r\n \"cardDescRequest\": \"Adım 1/2: Sıfırlama kodu isteyin\",\r\n \"cardDescReset\": \"Adım 2/2: Kodu ve yeni şifreyi girin\",\r\n \"username\": \"Kullanıcı Adı\",\r\n \"usernamePlaceholder\": \"Kullanıcı adınızı girin\",\r\n \"code\": \"Sıfırlama Kodu\",\r\n \"codePlaceholder\": \"6 haneli kodu girin\",\r\n \"codeFor\": \"Sıfırlama kodu:\",\r\n \"newPassword\": \"Yeni Şifre\",\r\n \"newPasswordPlaceholder\": \"Yeni şifre girin\",\r\n \"confirmPassword\": \"Şifre Onayı\",\r\n \"confirmPasswordPlaceholder\": \"Yeni şifreyi onaylayın\",\r\n \"passwordRequirements\": \"En az 8 karakter, 1 harf ve 1 rakam\",\r\n \"passwordMismatch\": \"Şifreler eşleşmiyor\",\r\n \"sendCode\": \"Sıfırlama Kodu Gönder\",\r\n \"sending\": \"Gönderiliyor...\",\r\n \"resetPassword\": \"Şifreyi Sıfırla\",\r\n \"resetting\": \"Sıfırlanıyor...\",\r\n \"backToLogin\": \"Girişe Dön\",\r\n \"changeUsername\": \"Kullanıcı adını değiştir\",\r\n \"resendCode\": \"Kodu tekrar gönder\",\r\n \"codeSentTitle\": \"Kod Gönderildi!\",\r\n \"codeSentDesc\": \"E-postanıza şifre sıfırlama kodu gönderildi.\",\r\n \"errorTitle\": \"Hata\",\r\n \"errorGeneric\": \"Sıfırlama kodu gönderilemedi. Lütfen tekrar deneyin.\",\r\n \"errorResetGeneric\": \"Şifre sıfırlanamadı. Lütfen tekrar deneyin.\",\r\n \"resetSuccessTitle\": \"Şifre Sıfırlandı!\",\r\n \"resetSuccessDesc\": \"Şifreniz başarıyla sıfırlandı.\",\r\n \"successTitle\": \"Şifre Başarıyla Sıfırlandı!\",\r\n \"successDescription\": \"Şifreniz değiştirildi. Artık yeni şifrenizle giriş yapabilirsiniz.\",\r\n \"goToLogin\": \"Girişe Git\"\r\n}\r\n"
38
+ "content": "{\n \"title\": \"Şifremi Unuttum\",\n \"descriptionRequest\": \"Kullanıcı adınızı girin, size şifre sıfırlama kodu göndereceğiz.\",\n \"descriptionReset\": \"E-postanıza gönderilen kodu ve yeni şifrenizi girin.\",\n \"cardTitleRequest\": \"Sıfırlama Kodu İste\",\n \"cardTitleReset\": \"Şifre Sıfırla\",\n \"cardDescRequest\": \"Adım 1/2: Sıfırlama kodu isteyin\",\n \"cardDescReset\": \"Adım 2/2: Kodu ve yeni şifreyi girin\",\n \"username\": \"Kullanıcı Adı\",\n \"usernamePlaceholder\": \"Kullanıcı adınızı girin\",\n \"code\": \"Sıfırlama Kodu\",\n \"codePlaceholder\": \"6 haneli kodu girin\",\n \"codeFor\": \"Sıfırlama kodu:\",\n \"newPassword\": \"Yeni Şifre\",\n \"newPasswordPlaceholder\": \"Yeni şifre girin\",\n \"confirmPassword\": \"Şifre Onayı\",\n \"confirmPasswordPlaceholder\": \"Yeni şifreyi onaylayın\",\n \"passwordRequirements\": \"En az 8 karakter, 1 harf ve 1 rakam\",\n \"passwordMismatch\": \"Şifreler eşleşmiyor\",\n \"sendCode\": \"Sıfırlama Kodu Gönder\",\n \"sending\": \"Gönderiliyor...\",\n \"resetPassword\": \"Şifreyi Sıfırla\",\n \"resetting\": \"Sıfırlanıyor...\",\n \"backToLogin\": \"Girişe Dön\",\n \"changeUsername\": \"Kullanıcı adını değiştir\",\n \"resendCode\": \"Kodu tekrar gönder\",\n \"codeSentTitle\": \"Kod Gönderildi!\",\n \"codeSentDesc\": \"E-postanıza şifre sıfırlama kodu gönderildi.\",\n \"errorTitle\": \"Hata\",\n \"errorGeneric\": \"Sıfırlama kodu gönderilemedi. Lütfen tekrar deneyin.\",\n \"errorResetGeneric\": \"Şifre sıfırlanamadı. Lütfen tekrar deneyin.\",\n \"resetSuccessTitle\": \"Şifre Sıfırlandı!\",\n \"resetSuccessDesc\": \"Şifreniz başarıyla sıfırlandı.\",\n \"successTitle\": \"Şifre Başarıyla Sıfırlandı!\",\n \"successDescription\": \"Şifreniz değiştirildi. Artık yeni şifrenizle giriş yapabilirsiniz.\",\n \"goToLogin\": \"Girişe Git\"\n}\n"
39
39
  }
40
40
  ],
41
41
  "exports": {
@@ -10,25 +10,25 @@
10
10
  "path": "google-adsense/index.ts",
11
11
  "type": "registry:index",
12
12
  "target": "$modules$/google-adsense/index.ts",
13
- "content": "export * from './google-adsense';\r\n"
13
+ "content": "export * from './google-adsense';\n"
14
14
  },
15
15
  {
16
16
  "path": "google-adsense/google-adsense.tsx",
17
17
  "type": "registry:component",
18
18
  "target": "$modules$/google-adsense/google-adsense.tsx",
19
- "content": "import { useEffect, useRef, useState } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\ndeclare global {\r\n interface Window {\r\n adsbygoogle: unknown[];\r\n }\r\n}\r\n\r\ninterface GoogleAdsenseProps {\r\n client?: string;\r\n slot: string;\r\n format?: \"auto\" | \"fluid\" | \"rectangle\" | \"vertical\" | \"horizontal\";\r\n responsive?: boolean;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n testMode?: boolean;\r\n}\r\n\r\nconst ADSENSE_SCRIPT_ID = \"google-adsense-script\";\r\n\r\nexport function GoogleAdsense({\r\n client,\r\n slot,\r\n format = \"auto\",\r\n responsive = true,\r\n className,\r\n style,\r\n testMode = false,\r\n}: GoogleAdsenseProps) {\r\n const { t } = useTranslation(\"google-adsense\");\r\n const adRef = useRef<HTMLModElement>(null);\r\n const [isLoaded, setIsLoaded] = useState(false);\r\n const [hasError, setHasError] = useState(false);\r\n\r\n const adClient = client || import.meta.env.VITE_ADSENSE_CLIENT;\r\n const isDev = import.meta.env.DEV;\r\n\r\n // Load AdSense script once\r\n useEffect(() => {\r\n if (isDev && !testMode) return;\r\n if (!adClient) {\r\n setHasError(true);\r\n return;\r\n }\r\n\r\n const existingScript = document.getElementById(ADSENSE_SCRIPT_ID);\r\n if (existingScript) {\r\n setIsLoaded(true);\r\n return;\r\n }\r\n\r\n const script = document.createElement(\"script\");\r\n script.id = ADSENSE_SCRIPT_ID;\r\n script.src = `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${adClient}`;\r\n script.async = true;\r\n script.crossOrigin = \"anonymous\";\r\n\r\n script.onload = () => setIsLoaded(true);\r\n script.onerror = () => setHasError(true);\r\n\r\n document.head.appendChild(script);\r\n }, [adClient, isDev, testMode]);\r\n\r\n // Push ad when script is loaded\r\n useEffect(() => {\r\n if (!isLoaded || !adRef.current || (isDev && !testMode)) return;\r\n\r\n const adElement = adRef.current;\r\n if (adElement.dataset.adStatus) return; // Already initialized\r\n\r\n try {\r\n (window.adsbygoogle = window.adsbygoogle || []).push({});\r\n } catch (err) {\r\n console.error(\"AdSense error:\", err);\r\n setHasError(true);\r\n }\r\n }, [isLoaded, isDev, testMode]);\r\n\r\n // Development placeholder\r\n if (isDev && !testMode) {\r\n return (\r\n <div\r\n className={cn(\r\n \"flex items-center justify-center bg-muted/50 border-2 border-dashed border-muted-foreground/25 rounded-lg\",\r\n className\r\n )}\r\n style={{ minHeight: \"90px\", ...style }}\r\n >\r\n <div className=\"text-center p-4\">\r\n <p className=\"text-sm font-medium text-muted-foreground\">\r\n {t(\"devPlaceholder\", \"AdSense Placeholder\")}\r\n </p>\r\n <p className=\"text-xs text-muted-foreground/70 mt-1\">\r\n {t(\"devNote\", \"Ads will appear in production\")}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // Error state\r\n if (hasError || !adClient) {\r\n return (\r\n <div\r\n className={cn(\r\n \"flex items-center justify-center bg-muted/30 rounded-lg\",\r\n className\r\n )}\r\n style={{ minHeight: \"90px\", ...style }}\r\n >\r\n <p className=\"text-xs text-muted-foreground\">\r\n {t(\"error\", \"Ad could not be loaded\")}\r\n </p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <ins\r\n ref={adRef}\r\n className={cn(\"adsbygoogle block\", className)}\r\n style={{ display: \"block\", minHeight: \"90px\", ...style }}\r\n data-ad-client={adClient}\r\n data-ad-slot={slot}\r\n data-ad-format={format}\r\n data-full-width-responsive={responsive ? \"true\" : \"false\"}\r\n {...(testMode && { \"data-adtest\": \"on\" })}\r\n />\r\n );\r\n}\r\n"
19
+ "content": "import { useEffect, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { cn } from \"@/lib/utils\";\n\ndeclare global {\n interface Window {\n adsbygoogle: unknown[];\n }\n}\n\ninterface GoogleAdsenseProps {\n client?: string;\n slot: string;\n format?: \"auto\" | \"fluid\" | \"rectangle\" | \"vertical\" | \"horizontal\";\n responsive?: boolean;\n className?: string;\n style?: React.CSSProperties;\n testMode?: boolean;\n}\n\nconst ADSENSE_SCRIPT_ID = \"google-adsense-script\";\n\nexport function GoogleAdsense({\n client,\n slot,\n format = \"auto\",\n responsive = true,\n className,\n style,\n testMode = false,\n}: GoogleAdsenseProps) {\n const { t } = useTranslation(\"google-adsense\");\n const adRef = useRef<HTMLModElement>(null);\n const [isLoaded, setIsLoaded] = useState(false);\n const [hasError, setHasError] = useState(false);\n\n const adClient = client || import.meta.env.VITE_ADSENSE_CLIENT;\n const isDev = import.meta.env.DEV;\n\n // Load AdSense script once\n useEffect(() => {\n if (isDev && !testMode) return;\n if (!adClient) {\n setHasError(true);\n return;\n }\n\n const existingScript = document.getElementById(ADSENSE_SCRIPT_ID);\n if (existingScript) {\n setIsLoaded(true);\n return;\n }\n\n const script = document.createElement(\"script\");\n script.id = ADSENSE_SCRIPT_ID;\n script.src = `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${adClient}`;\n script.async = true;\n script.crossOrigin = \"anonymous\";\n\n script.onload = () => setIsLoaded(true);\n script.onerror = () => setHasError(true);\n\n document.head.appendChild(script);\n }, [adClient, isDev, testMode]);\n\n // Push ad when script is loaded\n useEffect(() => {\n if (!isLoaded || !adRef.current || (isDev && !testMode)) return;\n\n const adElement = adRef.current;\n if (adElement.dataset.adStatus) return; // Already initialized\n\n try {\n (window.adsbygoogle = window.adsbygoogle || []).push({});\n } catch (err) {\n console.error(\"AdSense error:\", err);\n setHasError(true);\n }\n }, [isLoaded, isDev, testMode]);\n\n // Development placeholder\n if (isDev && !testMode) {\n return (\n <div\n className={cn(\n \"flex items-center justify-center bg-muted/50 border-2 border-dashed border-muted-foreground/25 rounded-lg\",\n className\n )}\n style={{ minHeight: \"90px\", ...style }}\n >\n <div className=\"text-center p-4\">\n <p className=\"text-sm font-medium text-muted-foreground\">\n {t(\"devPlaceholder\", \"AdSense Placeholder\")}\n </p>\n <p className=\"text-xs text-muted-foreground/70 mt-1\">\n {t(\"devNote\", \"Ads will appear in production\")}\n </p>\n </div>\n </div>\n );\n }\n\n // Error state\n if (hasError || !adClient) {\n return (\n <div\n className={cn(\n \"flex items-center justify-center bg-muted/30 rounded-lg\",\n className\n )}\n style={{ minHeight: \"90px\", ...style }}\n >\n <p className=\"text-xs text-muted-foreground\">\n {t(\"error\", \"Ad could not be loaded\")}\n </p>\n </div>\n );\n }\n\n return (\n <ins\n ref={adRef}\n className={cn(\"adsbygoogle block\", className)}\n style={{ display: \"block\", minHeight: \"90px\", ...style }}\n data-ad-client={adClient}\n data-ad-slot={slot}\n data-ad-format={format}\n data-full-width-responsive={responsive ? \"true\" : \"false\"}\n {...(testMode && { \"data-adtest\": \"on\" })}\n />\n );\n}\n"
20
20
  },
21
21
  {
22
22
  "path": "google-adsense/lang/en.json",
23
23
  "type": "registry:lang",
24
24
  "target": "$modules$/google-adsense/lang/en.json",
25
- "content": "{\r\n \"devPlaceholder\": \"AdSense Placeholder\",\r\n \"devNote\": \"Ads will appear in production\",\r\n \"error\": \"Ad could not be loaded\"\r\n}\r\n"
25
+ "content": "{\n \"devPlaceholder\": \"AdSense Placeholder\",\n \"devNote\": \"Ads will appear in production\",\n \"error\": \"Ad could not be loaded\"\n}\n"
26
26
  },
27
27
  {
28
28
  "path": "google-adsense/lang/tr.json",
29
29
  "type": "registry:lang",
30
30
  "target": "$modules$/google-adsense/lang/tr.json",
31
- "content": "{\r\n \"devPlaceholder\": \"AdSense Yer Tutucusu\",\r\n \"devNote\": \"Reklamlar production'da görünecek\",\r\n \"error\": \"Reklam yüklenemedi\"\r\n}\r\n"
31
+ "content": "{\n \"devPlaceholder\": \"AdSense Yer Tutucusu\",\n \"devNote\": \"Reklamlar production'da görünecek\",\n \"error\": \"Reklam yüklenemedi\"\n}\n"
32
32
  }
33
33
  ],
34
34
  "envVars": {
@@ -10,13 +10,13 @@
10
10
  "path": "google-map/index.ts",
11
11
  "type": "registry:index",
12
12
  "target": "$modules$/google-map/index.ts",
13
- "content": "export * from './google-map';\r\n"
13
+ "content": "export * from './google-map';\n"
14
14
  },
15
15
  {
16
16
  "path": "google-map/google-map.tsx",
17
17
  "type": "registry:component",
18
18
  "target": "$modules$/google-map/google-map.tsx",
19
- "content": "import { useState } from \"react\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { MapPin } from \"lucide-react\";\r\n\r\ninterface GoogleMapProps {\r\n latitude: number;\r\n longitude: number;\r\n zoom?: number;\r\n apiKey?: string;\r\n height?: string;\r\n className?: string;\r\n title?: string;\r\n}\r\n\r\nexport function GoogleMap({\r\n latitude,\r\n longitude,\r\n zoom = 15,\r\n apiKey,\r\n height = \"400px\",\r\n className,\r\n title,\r\n}: GoogleMapProps) {\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [hasError, setHasError] = useState(false);\r\n\r\n // Build the embed URL\r\n const buildMapUrl = () => {\r\n const baseUrl = apiKey\r\n ? \"https://www.google.com/maps/embed/v1/place\"\r\n : \"https://maps.google.com/maps\";\r\n\r\n if (apiKey) {\r\n // With API key - use official Embed API\r\n const params = new URLSearchParams({\r\n key: apiKey,\r\n q: `${latitude},${longitude}`,\r\n zoom: zoom.toString(),\r\n });\r\n return `${baseUrl}?${params.toString()}`;\r\n } else {\r\n // Without API key - use basic embed\r\n const params = new URLSearchParams({\r\n q: `${latitude},${longitude}`,\r\n z: zoom.toString(),\r\n output: \"embed\",\r\n });\r\n return `${baseUrl}?${params.toString()}`;\r\n }\r\n };\r\n\r\n const handleLoad = () => {\r\n setIsLoading(false);\r\n };\r\n\r\n const handleError = () => {\r\n setIsLoading(false);\r\n setHasError(true);\r\n };\r\n\r\n if (hasError) {\r\n return (\r\n <div\r\n className={cn(\r\n \"flex flex-col items-center justify-center bg-muted rounded-lg border\",\r\n className\r\n )}\r\n style={{ height }}\r\n >\r\n <MapPin className=\"h-12 w-12 text-muted-foreground mb-3\" />\r\n <p className=\"text-sm text-muted-foreground\">Failed to load map</p>\r\n <a\r\n href={`https://www.google.com/maps?q=${latitude},${longitude}`}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"text-sm text-primary hover:underline mt-2\"\r\n >\r\n Open in Google Maps\r\n </a>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n className={cn(\"relative rounded-lg overflow-hidden border\", className)}\r\n style={{ height }}\r\n >\r\n {isLoading && (\r\n <div className=\"absolute inset-0 flex items-center justify-center bg-muted\">\r\n <div className=\"flex flex-col items-center gap-3\">\r\n <div className=\"h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent\" />\r\n <span className=\"text-sm text-muted-foreground\">Loading map...</span>\r\n </div>\r\n </div>\r\n )}\r\n <iframe\r\n src={buildMapUrl()}\r\n width=\"100%\"\r\n height=\"100%\"\r\n style={{ border: 0 }}\r\n allowFullScreen\r\n loading=\"lazy\"\r\n referrerPolicy=\"no-referrer-when-downgrade\"\r\n title={title || `Map location: ${latitude}, ${longitude}`}\r\n onLoad={handleLoad}\r\n onError={handleError}\r\n className={cn(isLoading && \"invisible\")}\r\n />\r\n </div>\r\n );\r\n}\r\n"
19
+ "content": "import { useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { MapPin } from \"lucide-react\";\n\ninterface GoogleMapProps {\n latitude: number;\n longitude: number;\n zoom?: number;\n apiKey?: string;\n height?: string;\n className?: string;\n title?: string;\n}\n\nexport function GoogleMap({\n latitude,\n longitude,\n zoom = 15,\n apiKey,\n height = \"400px\",\n className,\n title,\n}: GoogleMapProps) {\n const [isLoading, setIsLoading] = useState(true);\n const [hasError, setHasError] = useState(false);\n\n // Build the embed URL\n const buildMapUrl = () => {\n const baseUrl = apiKey\n ? \"https://www.google.com/maps/embed/v1/place\"\n : \"https://maps.google.com/maps\";\n\n if (apiKey) {\n // With API key - use official Embed API\n const params = new URLSearchParams({\n key: apiKey,\n q: `${latitude},${longitude}`,\n zoom: zoom.toString(),\n });\n return `${baseUrl}?${params.toString()}`;\n } else {\n // Without API key - use basic embed\n const params = new URLSearchParams({\n q: `${latitude},${longitude}`,\n z: zoom.toString(),\n output: \"embed\",\n });\n return `${baseUrl}?${params.toString()}`;\n }\n };\n\n const handleLoad = () => {\n setIsLoading(false);\n };\n\n const handleError = () => {\n setIsLoading(false);\n setHasError(true);\n };\n\n if (hasError) {\n return (\n <div\n className={cn(\n \"flex flex-col items-center justify-center bg-muted rounded-lg border\",\n className\n )}\n style={{ height }}\n >\n <MapPin className=\"h-12 w-12 text-muted-foreground mb-3\" />\n <p className=\"text-sm text-muted-foreground\">Failed to load map</p>\n <a\n href={`https://www.google.com/maps?q=${latitude},${longitude}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-primary hover:underline mt-2\"\n >\n Open in Google Maps\n </a>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\"relative rounded-lg overflow-hidden border\", className)}\n style={{ height }}\n >\n {isLoading && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-muted\">\n <div className=\"flex flex-col items-center gap-3\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent\" />\n <span className=\"text-sm text-muted-foreground\">Loading map...</span>\n </div>\n </div>\n )}\n <iframe\n src={buildMapUrl()}\n width=\"100%\"\n height=\"100%\"\n style={{ border: 0 }}\n allowFullScreen\n loading=\"lazy\"\n referrerPolicy=\"no-referrer-when-downgrade\"\n title={title || `Map location: ${latitude}, ${longitude}`}\n onLoad={handleLoad}\n onError={handleError}\n className={cn(isLoading && \"invisible\")}\n />\n </div>\n );\n}\n"
20
20
  }
21
21
  ],
22
22
  "envVars": {
@@ -15,25 +15,25 @@
15
15
  "path": "header-centered-pill/index.ts",
16
16
  "type": "registry:index",
17
17
  "target": "$modules$/header-centered-pill/index.ts",
18
- "content": "export * from './header-centered-pill';\r\n"
18
+ "content": "export * from './header-centered-pill';\n"
19
19
  },
20
20
  {
21
21
  "path": "header-centered-pill/header-centered-pill.tsx",
22
22
  "type": "registry:component",
23
23
  "target": "$modules$/header-centered-pill/header-centered-pill.tsx",
24
- "content": "import { useState } from \"react\";\r\nimport { Link } from \"react-router\";\r\nimport { Menu } from \"lucide-react\";\r\nimport { Button, buttonVariants } from \"@/components/ui/button\";\r\nimport {\r\n Sheet,\r\n SheetHeader,\r\n SheetTitle,\r\n SheetContent,\r\n SheetTrigger,\r\n} from \"@/components/ui/sheet\";\r\nimport { Logo } from \"@/components/Logo\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { useTranslation } from \"react-i18next\";\r\n\r\nexport function HeaderCenteredPill() {\r\n const [mobileMenuOpen, setMobileMenuOpen] = useState(false);\r\n const { t } = useTranslation(\"header-centered-pill\");\r\n\r\n const navigation = [\r\n { name: t(\"features\", \"Features\"), href: \"/features\" },\r\n { name: t(\"pricing\", \"Pricing\"), href: \"/pricing\" },\r\n { name: t(\"blog\", \"Blog\"), href: \"/blog\" },\r\n { name: t(\"company\", \"Company\"), href: \"/about\" },\r\n { name: t(\"signIn\", \"Sign in\"), href: \"/login\" },\r\n ];\r\n\r\n return (\r\n <header className=\"p-4\">\r\n <div className=\"mx-auto flex max-w-2xl items-center justify-between space-x-4 rounded-full border bg-background p-1.5 pl-4\">\r\n <Link to=\"/\">\r\n <Logo size=\"sm\" />\r\n </Link>\r\n\r\n {/* Desktop Navigation */}\r\n <div className=\"hidden md:inline-flex\">\r\n {navigation.map((item) => (\r\n <Link\r\n key={item.name}\r\n to={item.href}\r\n className={buttonVariants({ variant: \"ghost\", size: \"sm\" })}\r\n >\r\n {item.name}\r\n </Link>\r\n ))}\r\n </div>\r\n\r\n {/* Desktop CTA */}\r\n <div className=\"hidden md:inline-flex\">\r\n <Link\r\n to=\"/register\"\r\n className={cn(buttonVariants({ size: \"sm\" }), \"rounded-full\")}\r\n >\r\n {t(\"getStarted\", \"Get Started\")}\r\n </Link>\r\n </div>\r\n\r\n {/* Mobile Menu */}\r\n <div className=\"md:hidden\">\r\n <Sheet open={mobileMenuOpen} onOpenChange={setMobileMenuOpen}>\r\n <SheetTrigger asChild>\r\n <Button variant=\"ghost\" size=\"icon\" className=\"rounded-full\">\r\n <Menu className=\"h-5 w-5\" />\r\n <span className=\"sr-only\">{t(\"menu\", \"Menu\")}</span>\r\n </Button>\r\n </SheetTrigger>\r\n <SheetContent side=\"right\" className=\"w-[300px] px-6\">\r\n <SheetHeader>\r\n <SheetTitle>{t(\"menu\", \"Menu\")}</SheetTitle>\r\n </SheetHeader>\r\n <div className=\"flex flex-col space-y-4 mt-8\">\r\n {navigation.map((item) => (\r\n <Link\r\n key={item.name}\r\n to={item.href}\r\n className=\"text-lg font-medium hover:text-primary transition-colors\"\r\n onClick={() => setMobileMenuOpen(false)}\r\n >\r\n {item.name}\r\n </Link>\r\n ))}\r\n <Link\r\n to=\"/register\"\r\n className={cn(buttonVariants(), \"rounded-full mt-4\")}\r\n onClick={() => setMobileMenuOpen(false)}\r\n >\r\n {t(\"getStarted\", \"Get Started\")}\r\n </Link>\r\n </div>\r\n </SheetContent>\r\n </Sheet>\r\n </div>\r\n </div>\r\n </header>\r\n );\r\n}\r\n"
24
+ "content": "import { useState } from \"react\";\nimport { Link } from \"react-router\";\nimport { Menu } from \"lucide-react\";\nimport { Button, buttonVariants } 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 { cn } from \"@/lib/utils\";\nimport { useTranslation } from \"react-i18next\";\n\nexport function HeaderCenteredPill() {\n const [mobileMenuOpen, setMobileMenuOpen] = useState(false);\n const { t } = useTranslation(\"header-centered-pill\");\n\n const navigation = [\n { name: t(\"features\", \"Features\"), href: \"/features\" },\n { name: t(\"pricing\", \"Pricing\"), href: \"/pricing\" },\n { name: t(\"blog\", \"Blog\"), href: \"/blog\" },\n { name: t(\"company\", \"Company\"), href: \"/about\" },\n { name: t(\"signIn\", \"Sign in\"), href: \"/login\" },\n ];\n\n return (\n <header className=\"p-4\">\n <div className=\"mx-auto flex max-w-2xl items-center justify-between space-x-4 rounded-full border bg-background p-1.5 pl-4\">\n <Link to=\"/\">\n <Logo size=\"sm\" />\n </Link>\n\n {/* Desktop Navigation */}\n <div className=\"hidden md:inline-flex\">\n {navigation.map((item) => (\n <Link\n key={item.name}\n to={item.href}\n className={buttonVariants({ variant: \"ghost\", size: \"sm\" })}\n >\n {item.name}\n </Link>\n ))}\n </div>\n\n {/* Desktop CTA */}\n <div className=\"hidden md:inline-flex\">\n <Link\n to=\"/register\"\n className={cn(buttonVariants({ size: \"sm\" }), \"rounded-full\")}\n >\n {t(\"getStarted\", \"Get Started\")}\n </Link>\n </div>\n\n {/* Mobile Menu */}\n <div className=\"md:hidden\">\n <Sheet open={mobileMenuOpen} onOpenChange={setMobileMenuOpen}>\n <SheetTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"rounded-full\">\n <Menu className=\"h-5 w-5\" />\n <span className=\"sr-only\">{t(\"menu\", \"Menu\")}</span>\n </Button>\n </SheetTrigger>\n <SheetContent side=\"right\" className=\"w-[300px] px-6\">\n <SheetHeader>\n <SheetTitle>{t(\"menu\", \"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 <Link\n to=\"/register\"\n className={cn(buttonVariants(), \"rounded-full mt-4\")}\n onClick={() => setMobileMenuOpen(false)}\n >\n {t(\"getStarted\", \"Get Started\")}\n </Link>\n </div>\n </SheetContent>\n </Sheet>\n </div>\n </div>\n </header>\n );\n}\n"
25
25
  },
26
26
  {
27
27
  "path": "header-centered-pill/lang/en.json",
28
28
  "type": "registry:lang",
29
29
  "target": "$modules$/header-centered-pill/lang/en.json",
30
- "content": "{\r\n \"menu\": \"Menu\",\r\n \"features\": \"Features\",\r\n \"pricing\": \"Pricing\",\r\n \"blog\": \"Blog\",\r\n \"company\": \"Company\",\r\n \"signIn\": \"Sign in\",\r\n \"getStarted\": \"Get Started\"\r\n}\r\n"
30
+ "content": "{\n \"menu\": \"Menu\",\n \"features\": \"Features\",\n \"pricing\": \"Pricing\",\n \"blog\": \"Blog\",\n \"company\": \"Company\",\n \"signIn\": \"Sign in\",\n \"getStarted\": \"Get Started\"\n}\n"
31
31
  },
32
32
  {
33
33
  "path": "header-centered-pill/lang/tr.json",
34
34
  "type": "registry:lang",
35
35
  "target": "$modules$/header-centered-pill/lang/tr.json",
36
- "content": "{\r\n \"menu\": \"Menü\",\r\n \"features\": \"Özellikler\",\r\n \"pricing\": \"Fiyatlandırma\",\r\n \"blog\": \"Blog\",\r\n \"company\": \"Şirket\",\r\n \"signIn\": \"Giriş Yap\",\r\n \"getStarted\": \"Başla\"\r\n}\r\n"
36
+ "content": "{\n \"menu\": \"Menü\",\n \"features\": \"Özellikler\",\n \"pricing\": \"Fiyatlandırma\",\n \"blog\": \"Blog\",\n \"company\": \"Şirket\",\n \"signIn\": \"Giriş Yap\",\n \"getStarted\": \"Başla\"\n}\n"
37
37
  }
38
38
  ],
39
39
  "exports": {
@@ -14,7 +14,7 @@
14
14
  "path": "header-ecommerce/index.ts",
15
15
  "type": "registry:index",
16
16
  "target": "$modules$/header-ecommerce/index.ts",
17
- "content": "export * from './header-ecommerce';\r\n"
17
+ "content": "export * from './header-ecommerce';\n"
18
18
  },
19
19
  {
20
20
  "path": "header-ecommerce/header-ecommerce.tsx",
@@ -26,13 +26,13 @@
26
26
  "path": "header-ecommerce/lang/en.json",
27
27
  "type": "registry:lang",
28
28
  "target": "$modules$/header-ecommerce/lang/en.json",
29
- "content": "{\r\n \"menu\": \"Menu\",\r\n \"home\": \"Home\",\r\n \"products\": \"Products\",\r\n \"about\": \"About\",\r\n \"contact\": \"Contact\",\r\n \"cart\": \"Cart\",\r\n \"favorites\": \"Favorites\",\r\n \"searchProducts\": \"Search Products\",\r\n \"searchPlaceholder\": \"Search for products...\",\r\n \"searchButton\": \"Search\",\r\n \"result\": \"result\",\r\n \"results\": \"results\",\r\n \"noResults\": \"No products found\",\r\n \"tryDifferent\": \"Try different keywords\",\r\n \"viewAllResults\": \"View all results\"\r\n}\r\n"
29
+ "content": "{\n \"menu\": \"Menu\",\n \"home\": \"Home\",\n \"products\": \"Products\",\n \"about\": \"About\",\n \"contact\": \"Contact\",\n \"cart\": \"Cart\",\n \"favorites\": \"Favorites\",\n \"searchProducts\": \"Search Products\",\n \"searchPlaceholder\": \"Search for products...\",\n \"searchButton\": \"Search\",\n \"result\": \"result\",\n \"results\": \"results\",\n \"noResults\": \"No products found\",\n \"tryDifferent\": \"Try different keywords\",\n \"viewAllResults\": \"View all results\"\n}\n"
30
30
  },
31
31
  {
32
32
  "path": "header-ecommerce/lang/tr.json",
33
33
  "type": "registry:lang",
34
34
  "target": "$modules$/header-ecommerce/lang/tr.json",
35
- "content": "{\r\n \"menu\": \"Menü\",\r\n \"home\": \"Ana Sayfa\",\r\n \"products\": \"Ürünler\",\r\n \"about\": \"Hakkımızda\",\r\n \"contact\": \"İletişim\",\r\n \"cart\": \"Sepet\",\r\n \"favorites\": \"Favoriler\",\r\n \"searchProducts\": \"Ürün Ara\",\r\n \"searchPlaceholder\": \"Ürün ara...\",\r\n \"searchButton\": \"Ara\",\r\n \"result\": \"sonuç\",\r\n \"results\": \"sonuç\",\r\n \"noResults\": \"Ürün bulunamadı\",\r\n \"tryDifferent\": \"Farklı anahtar kelimeler deneyin\",\r\n \"viewAllResults\": \"Tüm sonuçları gör\"\r\n}\r\n"
35
+ "content": "{\n \"menu\": \"Menü\",\n \"home\": \"Ana Sayfa\",\n \"products\": \"Ürünler\",\n \"about\": \"Hakkımızda\",\n \"contact\": \"İletişim\",\n \"cart\": \"Sepet\",\n \"favorites\": \"Favoriler\",\n \"searchProducts\": \"Ürün Ara\",\n \"searchPlaceholder\": \"Ürün ara...\",\n \"searchButton\": \"Ara\",\n \"result\": \"sonuç\",\n \"results\": \"sonuç\",\n \"noResults\": \"Ürün bulunamadı\",\n \"tryDifferent\": \"Farklı anahtar kelimeler deneyin\",\n \"viewAllResults\": \"Tüm sonuçları gör\"\n}\n"
36
36
  }
37
37
  ],
38
38
  "exports": {
@@ -17,25 +17,25 @@
17
17
  "path": "header-mega/index.ts",
18
18
  "type": "registry:index",
19
19
  "target": "$modules$/header-mega/index.ts",
20
- "content": "export * from './header-mega';\r\n"
20
+ "content": "export * from './header-mega';\n"
21
21
  },
22
22
  {
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-50 py-4 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 overflow-visible\",\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 overflow-visible\">\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\";\nimport { Book, Menu, Sunset, Trees, Zap } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport { cn } from \"@/lib/utils\";\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/components/ui/accordion\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n NavigationMenu,\n NavigationMenuContent,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n NavigationMenuTrigger,\n} from \"@/components/ui/navigation-menu\";\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n SheetTitle,\n SheetTrigger,\n} from \"@/components/ui/sheet\";\nimport constants from \"@/constants/constants.json\";\n\ninterface MenuItem {\n title: string;\n url: string;\n description?: string;\n icon?: React.ReactNode;\n items?: MenuItem[];\n}\n\ninterface HeaderMegaProps {\n className?: string;\n}\n\nexport function HeaderMega({ className }: HeaderMegaProps) {\n const { t } = useTranslation(\"header-mega\");\n\n const menu: MenuItem[] = [\n { title: t(\"home\", \"Home\"), url: \"/\" },\n {\n title: t(\"products\", \"Products\"),\n url: \"/products\",\n items: [\n {\n title: t(\"allProducts\", \"All Products\"),\n description: t(\n \"allProductsDesc\",\n \"Browse our complete product catalog\"\n ),\n icon: <Book className=\"h-5 w-5 shrink-0\" />,\n url: \"/products\",\n },\n {\n title: t(\"featured\", \"Featured\"),\n description: t(\n \"featuredDesc\",\n \"Our handpicked selection of top products\"\n ),\n icon: <Trees className=\"h-5 w-5 shrink-0\" />,\n url: \"/products?featured=true\",\n },\n {\n title: t(\"newArrivals\", \"New Arrivals\"),\n description: t(\"newArrivalsDesc\", \"Check out the latest additions\"),\n icon: <Sunset className=\"h-5 w-5 shrink-0\" />,\n url: \"/products?is_new=true\",\n },\n {\n title: t(\"onSale\", \"On Sale\"),\n description: t(\"onSaleDesc\", \"Great deals and special offers\"),\n icon: <Zap className=\"h-5 w-5 shrink-0\" />,\n url: \"/products?on_sale=true\",\n },\n ],\n },\n {\n title: t(\"company\", \"Company\"),\n url: \"#\",\n items: [\n {\n title: t(\"aboutUs\", \"About Us\"),\n description: t(\n \"aboutUsDesc\",\n \"Learn more about our story and mission\"\n ),\n icon: <Trees className=\"h-5 w-5 shrink-0\" />,\n url: \"/about\",\n },\n {\n title: t(\"contact\", \"Contact\"),\n description: t(\"contactDesc\", \"Get in touch with our team\"),\n icon: <Sunset className=\"h-5 w-5 shrink-0\" />,\n url: \"/contact\",\n },\n {\n title: t(\"blog\", \"Blog\"),\n description: t(\"blogDesc\", \"Read our latest articles and updates\"),\n icon: <Book className=\"h-5 w-5 shrink-0\" />,\n url: \"/blog\",\n },\n ],\n },\n ];\n\n const renderMenuItem = (item: MenuItem) => {\n if (item.items) {\n return (\n <NavigationMenuItem key={item.title}>\n <NavigationMenuTrigger>{item.title}</NavigationMenuTrigger>\n <NavigationMenuContent className=\"z-50 bg-popover text-popover-foreground\">\n {item.items.map((subItem) => (\n <NavigationMenuLink asChild key={subItem.title} className=\"w-80\">\n <SubMenuLink item={subItem} />\n </NavigationMenuLink>\n ))}\n </NavigationMenuContent>\n </NavigationMenuItem>\n );\n }\n\n return (\n <NavigationMenuItem key={item.title}>\n <NavigationMenuLink asChild>\n <Link\n to={item.url}\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\"\n >\n {item.title}\n </Link>\n </NavigationMenuLink>\n </NavigationMenuItem>\n );\n };\n\n const renderMobileMenuItem = (item: MenuItem) => {\n if (item.items) {\n return (\n <AccordionItem\n key={item.title}\n value={item.title}\n className=\"border-b-0\"\n >\n <AccordionTrigger className=\"text-md py-0 font-semibold hover:no-underline\">\n {item.title}\n </AccordionTrigger>\n <AccordionContent className=\"mt-2\">\n {item.items.map((subItem) => (\n <SubMenuLink key={subItem.title} item={subItem} />\n ))}\n </AccordionContent>\n </AccordionItem>\n );\n }\n\n return (\n <Link key={item.title} to={item.url} className=\"text-md font-semibold\">\n {item.title}\n </Link>\n );\n };\n\n return (\n <header\n className={cn(\n \"relative z-50 py-4 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 overflow-visible\",\n className\n )}\n >\n <div className=\"container max-w-7xl mx-auto px-4\">\n {/* Desktop Menu */}\n <nav className=\"hidden items-center justify-between lg:flex overflow-visible\">\n <div className=\"flex items-center gap-6\">\n {/* Logo */}\n <Link to=\"/\" className=\"flex items-center gap-2\">\n <img\n src=\"/images/logo.png\"\n className=\"h-8 w-auto\"\n alt={constants.site.name}\n onError={(e) => {\n e.currentTarget.style.display = \"none\";\n }}\n />\n <span className=\"text-lg font-semibold tracking-tight\">\n {constants.site.name}\n </span>\n </Link>\n <div className=\"flex items-center\">\n <NavigationMenu>\n <NavigationMenuList>\n {menu.map((item) => renderMenuItem(item))}\n </NavigationMenuList>\n </NavigationMenu>\n </div>\n </div>\n <div className=\"flex gap-2\">\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link to=\"/login\">{t(\"login\", \"Login\")}</Link>\n </Button>\n <Button asChild size=\"sm\">\n <Link to=\"/register\">{t(\"signup\", \"Sign up\")}</Link>\n </Button>\n </div>\n </nav>\n\n {/* Mobile Menu */}\n <div className=\"block lg:hidden\">\n <div className=\"flex items-center justify-between\">\n {/* Logo */}\n <Link to=\"/\" className=\"flex items-center gap-2\">\n <img\n src=\"/images/logo.png\"\n className=\"h-8 w-auto\"\n alt={constants.site.name}\n onError={(e) => {\n e.currentTarget.style.display = \"none\";\n }}\n />\n <span className=\"text-lg font-semibold tracking-tight\">\n {constants.site.name}\n </span>\n </Link>\n <Sheet>\n <SheetTrigger asChild>\n <Button variant=\"outline\" size=\"icon\">\n <Menu className=\"h-4 w-4\" />\n </Button>\n </SheetTrigger>\n <SheetContent className=\"z-50 overflow-y-auto px-6\">\n <SheetHeader>\n <SheetTitle>\n <Link to=\"/\" className=\"flex items-center gap-2\">\n <img\n src=\"/images/logo.png\"\n className=\"h-8 w-auto\"\n alt={constants.site.name}\n onError={(e) => {\n e.currentTarget.style.display = \"none\";\n }}\n />\n </Link>\n </SheetTitle>\n </SheetHeader>\n <div className=\"flex flex-col gap-6 p-4\">\n <Accordion\n type=\"single\"\n collapsible\n className=\"flex w-full flex-col gap-4\"\n >\n {menu.map((item) => renderMobileMenuItem(item))}\n </Accordion>\n\n <div className=\"flex flex-col gap-3\">\n <Button asChild variant=\"outline\">\n <Link to=\"/login\">{t(\"login\", \"Login\")}</Link>\n </Button>\n <Button asChild>\n <Link to=\"/register\">{t(\"signup\", \"Sign up\")}</Link>\n </Button>\n </div>\n </div>\n </SheetContent>\n </Sheet>\n </div>\n </div>\n </div>\n </header>\n );\n}\n\nfunction SubMenuLink({ item }: { item: MenuItem }) {\n return (\n <Link\n to={item.url}\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\"\n >\n <div className=\"text-foreground\">{item.icon}</div>\n <div>\n <div className=\"text-sm font-semibold\">{item.title}</div>\n {item.description && (\n <p className=\"text-sm leading-snug text-muted-foreground\">\n {item.description}\n </p>\n )}\n </div>\n </Link>\n );\n}\n"
27
27
  },
28
28
  {
29
29
  "path": "header-mega/lang/en.json",
30
30
  "type": "registry:lang",
31
31
  "target": "$modules$/header-mega/lang/en.json",
32
- "content": "{\r\n \"home\": \"Home\",\r\n \"products\": \"Products\",\r\n \"allProducts\": \"All Products\",\r\n \"allProductsDesc\": \"Brief description that appears in the mega menu. Explain what visitors will find in your full product catalog. Use Promake to customize this menu text to guide navigation.\",\r\n \"featured\": \"Featured\",\r\n \"featuredDesc\": \"Menu description for your featured or highlighted products. Explain what makes these items special or recommended. Customize with Promake.\",\r\n \"newArrivals\": \"New Arrivals\",\r\n \"newArrivalsDesc\": \"Menu text describing your latest products. Create interest in what's new. Use Promake to customize this navigation description.\",\r\n \"onSale\": \"On Sale\",\r\n \"onSaleDesc\": \"Menu description for sale or discounted items. Highlight current promotions or deals. Customize with Promake to drive interest.\",\r\n \"company\": \"About\",\r\n \"aboutUs\": \"About Us\",\r\n \"aboutUsDesc\": \"Brief menu description of your about page. Tease what visitors will learn about your company, mission, or story. Customize with Promake.\",\r\n \"contact\": \"Contact\",\r\n \"contactDesc\": \"Menu text that encourages visitors to get in touch. Mention how you can help or your availability. Use Promake to create inviting contact text.\",\r\n \"blog\": \"Blog\",\r\n \"blogDesc\": \"Menu description for your blog section. Explain what type of content you publish or topics you cover. Customize with Promake.\",\r\n \"login\": \"Login\",\r\n \"signup\": \"Sign up\"\r\n}\r\n"
32
+ "content": "{\n \"home\": \"Home\",\n \"products\": \"Products\",\n \"allProducts\": \"All Products\",\n \"allProductsDesc\": \"Brief description that appears in the mega menu. Explain what visitors will find in your full product catalog. Use Promake to customize this menu text to guide navigation.\",\n \"featured\": \"Featured\",\n \"featuredDesc\": \"Menu description for your featured or highlighted products. Explain what makes these items special or recommended. Customize with Promake.\",\n \"newArrivals\": \"New Arrivals\",\n \"newArrivalsDesc\": \"Menu text describing your latest products. Create interest in what's new. Use Promake to customize this navigation description.\",\n \"onSale\": \"On Sale\",\n \"onSaleDesc\": \"Menu description for sale or discounted items. Highlight current promotions or deals. Customize with Promake to drive interest.\",\n \"company\": \"About\",\n \"aboutUs\": \"About Us\",\n \"aboutUsDesc\": \"Brief menu description of your about page. Tease what visitors will learn about your company, mission, or story. Customize with Promake.\",\n \"contact\": \"Contact\",\n \"contactDesc\": \"Menu text that encourages visitors to get in touch. Mention how you can help or your availability. Use Promake to create inviting contact text.\",\n \"blog\": \"Blog\",\n \"blogDesc\": \"Menu description for your blog section. Explain what type of content you publish or topics you cover. Customize with Promake.\",\n \"login\": \"Login\",\n \"signup\": \"Sign up\"\n}\n"
33
33
  },
34
34
  {
35
35
  "path": "header-mega/lang/tr.json",
36
36
  "type": "registry:lang",
37
37
  "target": "$modules$/header-mega/lang/tr.json",
38
- "content": "{\r\n \"home\": \"Ana Sayfa\",\r\n \"products\": \"Ürünler\",\r\n \"allProducts\": \"Tüm Ürünler\",\r\n \"allProductsDesc\": \"Mega menüde görünen kısa açıklama. Ziyaretçilerin tam ürün kataloğunuzda neleri bulacağını açıklayın. Promake ile bu menü metnini navigasyonu yönlendirmek için özelleştirin.\",\r\n \"featured\": \"Öne Çıkanlar\",\r\n \"featuredDesc\": \"Öne çıkan veya önerilen ürünleriniz için menü açıklaması. Bu ürünleri özel veya önerilen yapan şeyi açıklayın. Promake ile özelleştirin.\",\r\n \"newArrivals\": \"Yeni Gelenler\",\r\n \"newArrivalsDesc\": \"En son ürünlerinizi açıklayan menü metni. Yeni olanda ilgi yaratın. Promake ile bu navigasyon açıklamasını özelleştirin.\",\r\n \"onSale\": \"İndirimde\",\r\n \"onSaleDesc\": \"İndirimli veya promosyonlu ürünler için menü açıklaması. Güncel promosyonları veya fırsatları vurgulayın. Promake ile ilgi uyandırmak için özelleştirin.\",\r\n \"company\": \"Hakkında\",\r\n \"aboutUs\": \"Hakkımızda\",\r\n \"aboutUsDesc\": \"Hakkımızda sayfanızın kısa menü açıklaması. Ziyaretçilerin şirketiniz, misyonunuz veya hikayeniz hakkında ne öğreneceklerini vurgulayın. Promake ile özelleştirin.\",\r\n \"contact\": \"İletişim\",\r\n \"contactDesc\": \"Ziyaretçileri iletişime geçmeye teşvik eden menü metni. Nasıl yardımcı olabileceğinizden veya müsaitliğinizden bahsedin. Promake ile davetkar iletişim metni oluşturun.\",\r\n \"blog\": \"Blog\",\r\n \"blogDesc\": \"Blog bölümünüz için menü açıklaması. Ne tür içerik yayınladığınızı veya hangi konuları ele aldığınızı açıklayın. Promake ile özelleştirin.\",\r\n \"login\": \"Giriş Yap\",\r\n \"signup\": \"Kayıt Ol\"\r\n}\r\n"
38
+ "content": "{\n \"home\": \"Ana Sayfa\",\n \"products\": \"Ürünler\",\n \"allProducts\": \"Tüm Ürünler\",\n \"allProductsDesc\": \"Mega menüde görünen kısa açıklama. Ziyaretçilerin tam ürün kataloğunuzda neleri bulacağını açıklayın. Promake ile bu menü metnini navigasyonu yönlendirmek için özelleştirin.\",\n \"featured\": \"Öne Çıkanlar\",\n \"featuredDesc\": \"Öne çıkan veya önerilen ürünleriniz için menü açıklaması. Bu ürünleri özel veya önerilen yapan şeyi açıklayın. Promake ile özelleştirin.\",\n \"newArrivals\": \"Yeni Gelenler\",\n \"newArrivalsDesc\": \"En son ürünlerinizi açıklayan menü metni. Yeni olanda ilgi yaratın. Promake ile bu navigasyon açıklamasını özelleştirin.\",\n \"onSale\": \"İndirimde\",\n \"onSaleDesc\": \"İndirimli veya promosyonlu ürünler için menü açıklaması. Güncel promosyonları veya fırsatları vurgulayın. Promake ile ilgi uyandırmak için özelleştirin.\",\n \"company\": \"Hakkında\",\n \"aboutUs\": \"Hakkımızda\",\n \"aboutUsDesc\": \"Hakkımızda sayfanızın kısa menü açıklaması. Ziyaretçilerin şirketiniz, misyonunuz veya hikayeniz hakkında ne öğreneceklerini vurgulayın. Promake ile özelleştirin.\",\n \"contact\": \"İletişim\",\n \"contactDesc\": \"Ziyaretçileri iletişime geçmeye teşvik eden menü metni. Nasıl yardımcı olabileceğinizden veya müsaitliğinizden bahsedin. Promake ile davetkar iletişim metni oluşturun.\",\n \"blog\": \"Blog\",\n \"blogDesc\": \"Blog bölümünüz için menü açıklaması. Ne tür içerik yayınladığınızı veya hangi konuları ele aldığınızı açıklayın. Promake ile özelleştirin.\",\n \"login\": \"Giriş Yap\",\n \"signup\": \"Kayıt Ol\"\n}\n"
39
39
  }
40
40
  ],
41
41
  "exports": {
@@ -15,25 +15,25 @@
15
15
  "path": "header-minimal/index.ts",
16
16
  "type": "registry:index",
17
17
  "target": "$modules$/header-minimal/index.ts",
18
- "content": "export * from './header-minimal';\r\n"
18
+ "content": "export * from './header-minimal';\n"
19
19
  },
20
20
  {
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 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"
24
+ "content": "import { Link } from \"react-router\";\nimport { Menu } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n SheetTitle,\n SheetTrigger,\n} from \"@/components/ui/sheet\";\nimport constants from \"@/constants/constants.json\";\n\ninterface HeaderMinimalProps {\n className?: string;\n}\n\nexport function HeaderMinimal({ className }: HeaderMinimalProps) {\n const { t } = useTranslation(\"header-minimal\");\n\n const links = [\n { title: t(\"home\", \"Home\"), url: \"/\" },\n { title: t(\"about\", \"About\"), url: \"/about\" },\n ];\n\n return (\n <header className={cn(\"py-4 border-b bg-background\", className)}>\n <div className=\"container max-w-7xl mx-auto px-4\">\n <nav className=\"flex items-center justify-between\">\n {/* Logo */}\n <Link to=\"/\" className=\"flex items-center gap-2\">\n <img\n src=\"/images/logo.png\"\n className=\"h-8 w-auto\"\n alt={constants.site.name}\n onError={(e) => {\n e.currentTarget.style.display = \"none\";\n }}\n />\n <span className=\"text-xl font-bold tracking-tight\">\n {constants.site.name}\n </span>\n </Link>\n\n {/* Desktop Links */}\n <div className=\"hidden md:flex items-center gap-8\">\n {links.map((link) => (\n <Link\n key={link.title}\n to={link.url}\n className=\"text-sm font-medium text-muted-foreground hover:text-foreground transition-colors\"\n >\n {link.title}\n </Link>\n ))}\n </div>\n\n {/* CTA Button - Desktop */}\n <div className=\"hidden md:block\">\n <Button asChild>\n <Link to=\"/contact\">{t(\"cta\", \"Contact\")}</Link>\n </Button>\n </div>\n\n {/* Mobile Menu */}\n <div className=\"md:hidden\">\n <Sheet>\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=\"px-6\">\n <SheetHeader>\n <SheetTitle>\n <Link to=\"/\" className=\"flex items-center gap-2\">\n <span className=\"text-xl font-bold\">\n {constants.site.name}\n </span>\n </Link>\n </SheetTitle>\n </SheetHeader>\n <div className=\"flex flex-col gap-4 mt-8\">\n {links.map((link) => (\n <Link\n key={link.title}\n to={link.url}\n className=\"text-lg font-medium hover:text-primary transition-colors\"\n >\n {link.title}\n </Link>\n ))}\n <Button asChild className=\"mt-4\">\n <Link to=\"/contact\">{t(\"cta\", \"Contact\")}</Link>\n </Button>\n </div>\n </SheetContent>\n </Sheet>\n </div>\n </nav>\n </div>\n </header>\n );\n}\n"
25
25
  },
26
26
  {
27
27
  "path": "header-minimal/lang/en.json",
28
28
  "type": "registry:lang",
29
29
  "target": "$modules$/header-minimal/lang/en.json",
30
- "content": "{\r\n \"home\": \"Home\",\r\n \"about\": \"About\",\r\n \"cta\": \"Contact\"\r\n}\r\n"
30
+ "content": "{\n \"home\": \"Home\",\n \"about\": \"About\",\n \"cta\": \"Contact\"\n}\n"
31
31
  },
32
32
  {
33
33
  "path": "header-minimal/lang/tr.json",
34
34
  "type": "registry:lang",
35
35
  "target": "$modules$/header-minimal/lang/tr.json",
36
- "content": "{\r\n \"home\": \"Ana Sayfa\",\r\n \"about\": \"Hakkımızda\",\r\n \"cta\": \"İletişim\"\r\n}\r\n"
36
+ "content": "{\n \"home\": \"Ana Sayfa\",\n \"about\": \"Hakkımızda\",\n \"cta\": \"İletişim\"\n}\n"
37
37
  }
38
38
  ],
39
39
  "exports": {
@@ -13,7 +13,7 @@
13
13
  "path": "header-simple/index.ts",
14
14
  "type": "registry:index",
15
15
  "target": "$modules$/header-simple/index.ts",
16
- "content": "export * from './header-simple';\r\n"
16
+ "content": "export * from './header-simple';\n"
17
17
  },
18
18
  {
19
19
  "path": "header-simple/header-simple.tsx",
@@ -25,13 +25,13 @@
25
25
  "path": "header-simple/lang/en.json",
26
26
  "type": "registry:lang",
27
27
  "target": "$modules$/header-simple/lang/en.json",
28
- "content": "{\r\n \"home\": \"Home\",\r\n \"about\": \"About\",\r\n \"contact\": \"Contact\",\r\n \"menu\": \"Menu\"\r\n}\r\n"
28
+ "content": "{\n \"home\": \"Home\",\n \"about\": \"About\",\n \"contact\": \"Contact\",\n \"menu\": \"Menu\"\n}\n"
29
29
  },
30
30
  {
31
31
  "path": "header-simple/lang/tr.json",
32
32
  "type": "registry:lang",
33
33
  "target": "$modules$/header-simple/lang/tr.json",
34
- "content": "{\r\n \"home\": \"Ana Sayfa\",\r\n \"about\": \"Hakkımızda\",\r\n \"contact\": \"İletişim\",\r\n \"menu\": \"Menü\"\r\n}\r\n"
34
+ "content": "{\n \"home\": \"Ana Sayfa\",\n \"about\": \"Hakkımızda\",\n \"contact\": \"İletişim\",\n \"menu\": \"Menü\"\n}\n"
35
35
  }
36
36
  ],
37
37
  "exports": {
@@ -21,19 +21,19 @@
21
21
  "path": "hero-carousel/index.ts",
22
22
  "type": "registry:index",
23
23
  "target": "$modules$/hero-carousel/index.ts",
24
- "content": "export * from \"./hero-carousel\";\r\n"
24
+ "content": "export * from \"./hero-carousel\";\n"
25
25
  },
26
26
  {
27
27
  "path": "hero-carousel/lang/en.json",
28
28
  "type": "registry:lang",
29
29
  "target": "$modules$/hero-carousel/lang/en.json",
30
- "content": "{\r\n \"slides\": [\r\n {\r\n \"title\": \"Build Something Amazing\",\r\n \"description\": \"Edit these slides via Promake to match your brand message and call-to-action.\",\r\n \"primaryButton\": \"Get Started\",\r\n \"secondaryButton\": \"Learn More\"\r\n },\r\n {\r\n \"title\": \"Powerful Features\",\r\n \"description\": \"Discover tools and features that help you achieve more with less effort.\",\r\n \"primaryButton\": \"Explore Features\"\r\n },\r\n {\r\n \"title\": \"Ready to Transform?\",\r\n \"description\": \"Join thousands of satisfied customers who have already made the switch.\",\r\n \"primaryButton\": \"Contact Us\",\r\n \"secondaryButton\": \"See Demo\"\r\n }\r\n ]\r\n}\r\n"
30
+ "content": "{\n \"slides\": [\n {\n \"title\": \"Build Something Amazing\",\n \"description\": \"Edit these slides via Promake to match your brand message and call-to-action.\",\n \"primaryButton\": \"Get Started\",\n \"secondaryButton\": \"Learn More\"\n },\n {\n \"title\": \"Powerful Features\",\n \"description\": \"Discover tools and features that help you achieve more with less effort.\",\n \"primaryButton\": \"Explore Features\"\n },\n {\n \"title\": \"Ready to Transform?\",\n \"description\": \"Join thousands of satisfied customers who have already made the switch.\",\n \"primaryButton\": \"Contact Us\",\n \"secondaryButton\": \"See Demo\"\n }\n ]\n}\n"
31
31
  },
32
32
  {
33
33
  "path": "hero-carousel/lang/tr.json",
34
34
  "type": "registry:lang",
35
35
  "target": "$modules$/hero-carousel/lang/tr.json",
36
- "content": "{\r\n \"slides\": [\r\n {\r\n \"title\": \"Harika Bir Şey İnşa Edin\",\r\n \"description\": \"Bu slaytları marka mesajınıza ve eylem çağrınıza uyacak şekilde Promake üzerinden düzenleyin.\",\r\n \"primaryButton\": \"Başlayın\",\r\n \"secondaryButton\": \"Daha Fazla Bilgi\"\r\n },\r\n {\r\n \"title\": \"Güçlü Özellikler\",\r\n \"description\": \"Daha az çabayla daha fazlasını başarmanıza yardımcı olan araçları ve özellikleri keşfedin.\",\r\n \"primaryButton\": \"Özellikleri Keşfet\"\r\n },\r\n {\r\n \"title\": \"Dönüşüme Hazır mısınız?\",\r\n \"description\": \"Geçiş yapan binlerce memnun müşteriye katılın.\",\r\n \"primaryButton\": \"Bize Ulaşın\",\r\n \"secondaryButton\": \"Demo İzle\"\r\n }\r\n ]\r\n}\r\n"
36
+ "content": "{\n \"slides\": [\n {\n \"title\": \"Harika Bir Şey İnşa Edin\",\n \"description\": \"Bu slaytları marka mesajınıza ve eylem çağrınıza uyacak şekilde Promake üzerinden düzenleyin.\",\n \"primaryButton\": \"Başlayın\",\n \"secondaryButton\": \"Daha Fazla Bilgi\"\n },\n {\n \"title\": \"Güçlü Özellikler\",\n \"description\": \"Daha az çabayla daha fazlasını başarmanıza yardımcı olan araçları ve özellikleri keşfedin.\",\n \"primaryButton\": \"Özellikleri Keşfet\"\n },\n {\n \"title\": \"Dönüşüme Hazır mısınız?\",\n \"description\": \"Geçiş yapan binlerce memnun müşteriye katılın.\",\n \"primaryButton\": \"Bize Ulaşın\",\n \"secondaryButton\": \"Demo İzle\"\n }\n ]\n}\n"
37
37
  }
38
38
  ],
39
39
  "exports": {
@@ -12,25 +12,25 @@
12
12
  "path": "hero-cta/index.ts",
13
13
  "type": "registry:index",
14
14
  "target": "$modules$/hero-cta/index.ts",
15
- "content": "export * from './hero-cta';\r\n"
15
+ "content": "export * from './hero-cta';\n"
16
16
  },
17
17
  {
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-8 md:py-12 lg:py-26\", 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-2xl font-bold text-pretty sm:text-3xl lg:text-4xl xl:text-5xl leading-tight\">\r\n {t(\"heading\")}\r\n </h1>\r\n <p className=\"mb-8 max-w-xl text-muted-foreground text-base lg:text-lg\">\r\n {t(\"description\")}\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\")}\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\")}\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\")}\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\")}\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\";\nimport { ArrowRight, Star } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Avatar, AvatarImage, AvatarFallback } from \"@/components/ui/avatar\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\ninterface HeroCtaProps {\n className?: string;\n}\n\nexport function HeroCta({ className }: HeroCtaProps) {\n const { t } = useTranslation(\"hero-cta\");\n\n const avatars = [\n { src: \"/images/placeholder.png\", alt: \"User 1\", fallback: \"U1\" },\n { src: \"/images/placeholder.png\", alt: \"User 2\", fallback: \"U2\" },\n { src: \"/images/placeholder.png\", alt: \"User 3\", fallback: \"U3\" },\n { src: \"/images/placeholder.png\", alt: \"User 4\", fallback: \"U4\" },\n { src: \"/images/placeholder.png\", alt: \"User 5\", fallback: \"U5\" },\n ];\n\n return (\n <section className={cn(\"py-8 md:py-12 lg:py-26\", className)}>\n <div className=\"w-full max-w-[var(--container-max-width)] mx-auto px-4\">\n <div className=\"grid items-center gap-10 lg:grid-cols-2 lg:gap-16\">\n {/* Content Column */}\n <div className=\"flex flex-col items-center text-center lg:items-start lg:text-left\">\n <h1 className=\"mb-6 text-2xl font-bold text-pretty sm:text-3xl lg:text-4xl xl:text-5xl leading-tight\">\n {t(\"heading\")}\n </h1>\n <p className=\"mb-8 max-w-xl text-muted-foreground text-base lg:text-lg\">\n {t(\"description\")}\n </p>\n\n {/* Social Proof */}\n <div className=\"mb-10 flex flex-col items-center gap-4 sm:flex-row lg:items-start\">\n <div className=\"flex -space-x-3\">\n {avatars.map((avatar, index) => (\n <Avatar key={index} className=\"h-10 w-10 border-2 border-background\">\n <AvatarImage src={avatar.src} alt={avatar.alt} />\n <AvatarFallback className=\"text-xs\">{avatar.fallback}</AvatarFallback>\n </Avatar>\n ))}\n </div>\n <div>\n <div className=\"flex items-center gap-1\">\n {[...Array(5)].map((_, index) => (\n <Star\n key={index}\n className=\"h-4 w-4 fill-yellow-400 text-yellow-400\"\n />\n ))}\n <span className=\"ml-1 font-semibold text-sm\">5.0</span>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {t(\"reviews\")}\n </p>\n </div>\n </div>\n\n {/* CTA Buttons */}\n <div className=\"flex w-full flex-col gap-3 sm:flex-row sm:w-auto\">\n <Button asChild size=\"lg\" className=\"w-full sm:w-auto\">\n <Link to=\"/register\">\n {t(\"primaryCta\")}\n </Link>\n </Button>\n <Button asChild variant=\"outline\" size=\"lg\" className=\"w-full sm:w-auto\">\n <Link to=\"/about\">\n {t(\"secondaryCta\")}\n <ArrowRight className=\"ml-2 h-4 w-4\" />\n </Link>\n </Button>\n </div>\n </div>\n\n {/* Image Column */}\n <div className=\"relative order-first lg:order-last\">\n <div className=\"aspect-[4/3] overflow-hidden rounded-2xl bg-muted\">\n <img\n src=\"/images/placeholder.png\"\n alt={t(\"imageAlt\")}\n className=\"h-full w-full object-cover\"\n onError={(e) => {\n e.currentTarget.style.display = \"none\";\n }}\n />\n </div>\n {/* Decorative gradient blur */}\n <div className=\"absolute -z-10 -bottom-4 -right-4 h-72 w-72 rounded-full bg-primary/20 blur-3xl\" />\n </div>\n </div>\n </div>\n </section>\n );\n}\n"
22
22
  },
23
23
  {
24
24
  "path": "hero-cta/lang/en.json",
25
25
  "type": "registry:lang",
26
26
  "target": "$modules$/hero-cta/lang/en.json",
27
- "content": "{\r\n \"heading\": \"Build Something Amazing Today\",\r\n \"description\": \"Create powerful solutions that help you achieve your goals faster and more efficiently.\",\r\n \"reviews\": \"Trusted by 10,000+ users worldwide\",\r\n \"primaryCta\": \"Get Started\",\r\n \"secondaryCta\": \"Learn More\",\r\n \"imageAlt\": \"Hero image\"\r\n}\r\n"
27
+ "content": "{\n \"heading\": \"Build Something Amazing Today\",\n \"description\": \"Create powerful solutions that help you achieve your goals faster and more efficiently.\",\n \"reviews\": \"Trusted by 10,000+ users worldwide\",\n \"primaryCta\": \"Get Started\",\n \"secondaryCta\": \"Learn More\",\n \"imageAlt\": \"Hero image\"\n}\n"
28
28
  },
29
29
  {
30
30
  "path": "hero-cta/lang/tr.json",
31
31
  "type": "registry:lang",
32
32
  "target": "$modules$/hero-cta/lang/tr.json",
33
- "content": "{\r\n \"heading\": \"Bugün Harika Bir Şey İnşa Edin\",\r\n \"description\": \"Hedeflerinize daha hızlı ve verimli ulaşmanıza yardımcı olan güçlü çözümler oluşturun.\",\r\n \"reviews\": \"Dünya çapında 10.000+ kullanıcı tarafından güveniliyor\",\r\n \"primaryCta\": \"Başlayın\",\r\n \"secondaryCta\": \"Daha Fazla Bilgi\",\r\n \"imageAlt\": \"Hero görseli\"\r\n}\r\n"
33
+ "content": "{\n \"heading\": \"Bugün Harika Bir Şey İnşa Edin\",\n \"description\": \"Hedeflerinize daha hızlı ve verimli ulaşmanıza yardımcı olan güçlü çözümler oluşturun.\",\n \"reviews\": \"Dünya çapında 10.000+ kullanıcı tarafından güveniliyor\",\n \"primaryCta\": \"Başlayın\",\n \"secondaryCta\": \"Daha Fazla Bilgi\",\n \"imageAlt\": \"Hero görseli\"\n}\n"
34
34
  }
35
35
  ],
36
36
  "exports": {