@windrun-huaiin/third-ui 6.3.0 → 7.0.0

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 (76) hide show
  1. package/package.json +15 -46
  2. package/dist/chunk-52YUUCKV.js +0 -3190
  3. package/dist/chunk-52YUUCKV.js.map +0 -1
  4. package/dist/chunk-6MM7HLNX.js +0 -226
  5. package/dist/chunk-6MM7HLNX.js.map +0 -1
  6. package/dist/chunk-6PW67OXW.js +0 -967
  7. package/dist/chunk-6PW67OXW.js.map +0 -1
  8. package/dist/chunk-BZLOMDT7.mjs +0 -90
  9. package/dist/chunk-BZLOMDT7.mjs.map +0 -1
  10. package/dist/chunk-C3MW5ZUN.mjs +0 -967
  11. package/dist/chunk-C3MW5ZUN.mjs.map +0 -1
  12. package/dist/chunk-FOMCGWDM.mjs +0 -17
  13. package/dist/chunk-FOMCGWDM.mjs.map +0 -1
  14. package/dist/chunk-ICXWQI2S.mjs +0 -126
  15. package/dist/chunk-ICXWQI2S.mjs.map +0 -1
  16. package/dist/chunk-IOUCFIRG.mjs +0 -3190
  17. package/dist/chunk-IOUCFIRG.mjs.map +0 -1
  18. package/dist/chunk-J26XFRUS.js +0 -17
  19. package/dist/chunk-J26XFRUS.js.map +0 -1
  20. package/dist/chunk-LZLW5WCC.js +0 -90
  21. package/dist/chunk-LZLW5WCC.js.map +0 -1
  22. package/dist/chunk-NV3UQTCW.mjs +0 -226
  23. package/dist/chunk-NV3UQTCW.mjs.map +0 -1
  24. package/dist/chunk-TBXDOQXP.js +0 -126
  25. package/dist/chunk-TBXDOQXP.js.map +0 -1
  26. package/dist/chunk-TKLIIDBR.mjs +0 -2804
  27. package/dist/chunk-TKLIIDBR.mjs.map +0 -1
  28. package/dist/chunk-W7K5Y2WR.js +0 -2804
  29. package/dist/chunk-W7K5Y2WR.js.map +0 -1
  30. package/dist/clerk/index.d.mts +0 -15
  31. package/dist/clerk/index.d.ts +0 -15
  32. package/dist/clerk/index.js +0 -47
  33. package/dist/clerk/index.js.map +0 -1
  34. package/dist/clerk/index.mjs +0 -47
  35. package/dist/clerk/index.mjs.map +0 -1
  36. package/dist/clerk/server.d.mts +0 -28
  37. package/dist/clerk/server.d.ts +0 -28
  38. package/dist/clerk/server.js +0 -179
  39. package/dist/clerk/server.js.map +0 -1
  40. package/dist/clerk/server.mjs +0 -179
  41. package/dist/clerk/server.mjs.map +0 -1
  42. package/dist/cta.css +0 -16
  43. package/dist/fuma/mdx/index.d.mts +0 -133
  44. package/dist/fuma/mdx/index.d.ts +0 -133
  45. package/dist/fuma/mdx/index.js +0 -40
  46. package/dist/fuma/mdx/index.js.map +0 -1
  47. package/dist/fuma/mdx/index.mjs +0 -40
  48. package/dist/fuma/mdx/index.mjs.map +0 -1
  49. package/dist/fuma/server.d.mts +0 -77
  50. package/dist/fuma/server.d.ts +0 -77
  51. package/dist/fuma/server.js +0 -27041
  52. package/dist/fuma/server.js.map +0 -1
  53. package/dist/fuma/server.mjs +0 -27041
  54. package/dist/fuma/server.mjs.map +0 -1
  55. package/dist/fuma.css +0 -106
  56. package/dist/lib/server.d.mts +0 -4670
  57. package/dist/lib/server.d.ts +0 -4670
  58. package/dist/lib/server.js +0 -144
  59. package/dist/lib/server.js.map +0 -1
  60. package/dist/lib/server.mjs +0 -144
  61. package/dist/lib/server.mjs.map +0 -1
  62. package/dist/main/index.d.mts +0 -198
  63. package/dist/main/index.d.ts +0 -198
  64. package/dist/main/index.js +0 -32
  65. package/dist/main/index.js.map +0 -1
  66. package/dist/main/index.mjs +0 -32
  67. package/dist/main/index.mjs.map +0 -1
  68. package/dist/main/server.d.mts +0 -64
  69. package/dist/main/server.d.ts +0 -64
  70. package/dist/main/server.js +0 -602
  71. package/dist/main/server.js.map +0 -1
  72. package/dist/main/server.mjs +0 -602
  73. package/dist/main/server.mjs.map +0 -1
  74. package/dist/third-ui.css +0 -66
  75. package/dist/toc-base-BC7kXpDU.d.mts +0 -15
  76. package/dist/toc-base-BC7kXpDU.d.ts +0 -15
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/funeye/IdeaProjects/next-ai-build/packages/third-ui/dist/main/server.js","../../src/main/gallery.tsx","../../src/main/usage.tsx","../../src/main/features.tsx","../../src/main/tips.tsx","../../src/main/faq.tsx","../../src/main/seo-content.tsx","../../src/main/cta.tsx","../../src/main/footer.tsx","../../src/main/price-plan.tsx"],"names":["getTranslations","jsxs","jsx","_a","_b"],"mappings":"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","file":"/Users/funeye/IdeaProjects/next-ai-build/packages/third-ui/dist/main/server.js","sourcesContent":[null,"import { getTranslations } from 'next-intl/server';\nimport { cn } from '@lib/utils'\nimport Image from \"next/image\"\nimport { GalleryInteractive } from '@third-ui/main';\n\ninterface GalleryItem {\n id: string;\n url: string;\n altMsg: string;\n}\n\ninterface GalleryData {\n titleL: string;\n eyesOn: string;\n titleR: string;\n description: string;\n items: GalleryItem[];\n defaultImgUrl: string;\n downloadPrefix: string;\n}\n\ninterface GalleryProps {\n locale: string;\n sectionClassName?: string;\n button?: React.ReactNode;\n}\n\nexport async function Gallery({ locale, sectionClassName, button }: GalleryProps) {\n const t = await getTranslations({ locale, namespace: 'gallery' });\n \n // Process translation data\n const galleryItems = t.raw('prompts') as Array<{\n url: string;\n altMsg: string;\n }>;\n \n const data: GalleryData = {\n titleL: t('titleL'),\n eyesOn: t('eyesOn'),\n titleR: t('titleR'),\n description: t('description'),\n items: galleryItems.map((item, index) => ({\n id: `gallery-item-${index}`,\n url: item.url,\n altMsg: item.altMsg\n })),\n defaultImgUrl: t.raw('defaultImgUrl') as string,\n downloadPrefix: t('downloadPrefix')\n };\n\n return (\n <section id=\"gallery\" className={cn(\"container mx-auto px-4 py-20 scroll-mt-20\", sectionClassName)}>\n <h2 className=\"text-3xl md:text-4xl font-bold text-center mb-6\">\n {data.titleL} <span className=\"text-purple-500\">{data.eyesOn}</span> {data.titleR}\n </h2>\n <p className=\"text-center max-w-2xl mx-auto mb-16\">\n {data.description}\n </p>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6\">\n {data.items.map((item, index) => (\n <div \n key={item.id} \n className=\"group relative overflow-hidden rounded-xl\"\n data-gallery-item={item.id}\n data-gallery-index={index}\n >\n <Image\n src={item.url}\n alt={item.altMsg}\n width={600}\n height={600}\n className=\"w-full h-80 object-cover transition duration-300 group-hover:scale-105\"\n data-gallery-image={item.id}\n />\n <div className=\"absolute inset-0 flex items-end justify-end p-4 opacity-0 group-hover:opacity-100 transition duration-300\">\n <button\n className=\"p-2 rounded-full bg-black/50 hover:bg-black/70 text-white/80 hover:text-white transition-all duration-300\"\n data-gallery-download={item.id}\n aria-label={`Download ${item.altMsg}`}\n >\n <svg className=\"h-5 w-5 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n </button>\n </div>\n </div>\n ))}\n </div>\n {button && (\n <div className=\"text-center mt-12\">\n {button}\n </div>\n )}\n \n <GalleryInteractive data={data} />\n </section>\n )\n}\n","import { getTranslations } from 'next-intl/server';\nimport { cn } from '@lib/utils';\nimport { globalLucideIcons as icons, getGlobalIcon } from '@base-ui/components/global-icon'\nimport { richText } from '@third-ui/main/rich-text-expert';\n\ninterface UsageData {\n title: string;\n eyesOn: string;\n description: string;\n steps: Array<{\n id: string;\n title: string;\n description: string;\n iconKey: keyof typeof icons;\n stepNumber: number;\n }>;\n}\n\nexport async function Usage({ \n locale, \n sectionClassName \n}: { \n locale: string;\n sectionClassName?: string;\n}) {\n const t = await getTranslations({ locale, namespace: 'usage' });\n \n // Process translation data\n const steps = t.raw('steps') as Array<{\n title: string;\n description: string;\n iconKey: keyof typeof icons;\n }>;\n \n const data: UsageData = {\n title: t('title'),\n eyesOn: t('eyesOn'),\n description: richText(t, 'description'),\n steps: steps.map((step, index) => ({\n id: `usage-step-${index}`,\n title: step.title,\n description: richText(t, `steps.${index}.description`),\n iconKey: step.iconKey,\n stepNumber: index + 1\n }))\n };\n\n return (\n <section id=\"usage\" className={cn(\"px-16 py-10 mx-16 md:mx-32 scroll-mt-20\", sectionClassName)}>\n <h2 className=\"text-3xl md:text-4xl font-bold text-center mb-4\">\n {data.title} <span className=\"text-purple-500\">{data.eyesOn}</span>\n </h2>\n <p className=\"text-center text-gray-600 dark:text-gray-400 mb-12 text-base md:text-lg mx-auto whitespace-nowrap\">\n {data.description}\n </p>\n <div className=\"bg-gray-50 dark:bg-gray-800/60 border border-gray-200 dark:border-gray-700 rounded-2xl p-8 md:p-12 shadow-sm dark:shadow-none\">\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-8 gap-y-12\">\n {data.steps.map((step) => {\n const Icon = getGlobalIcon(step.iconKey);\n return (\n <div key={step.id} data-usage-step={step.id} className=\"flex items-start\">\n <div className=\"flex-shrink-0 mr-4\">\n <Icon className=\"w-8 h-8 text-purple-500\" />\n </div>\n <div>\n <h3 className=\"text-xl font-semibold mb-3 text-gray-900 dark:text-gray-100 flex items-center\">\n {`${step.stepNumber}. ${step.title}`}\n </h3>\n <p className=\"text-gray-700 dark:text-gray-300\">{step.description}</p>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </section>\n )\n}\n\n","import { getTranslations } from 'next-intl/server';\nimport { getGlobalIcon } from '@base-ui/components/global-icon';\nimport { globalLucideIcons as icons } from '@base-ui/components/global-icon';\nimport { cn } from '@lib/utils';\nimport { richText } from '@third-ui/main/rich-text-expert';\n\ninterface FeaturesData {\n title: string;\n eyesOn: string;\n description: string;\n items: Array<{\n id: string;\n title: string;\n description: string;\n iconKey: keyof typeof icons;\n }>;\n}\n\nexport async function Features({ \n locale, \n sectionClassName \n}: { \n locale: string;\n sectionClassName?: string;\n}) {\n const t = await getTranslations({ locale, namespace: 'features' });\n \n // Process translation data\n const featureItems = t.raw('items') as Array<{\n title: string;\n description: string;\n iconKey: keyof typeof icons;\n }>;\n \n const data: FeaturesData = {\n title: t('title'),\n eyesOn: t('eyesOn'),\n description: richText(t, 'description'),\n items: featureItems.map((feature, index) => ({\n id: `feature-item-${index}`,\n title: feature.title,\n description: richText(t, `items.${index}.description`),\n iconKey: feature.iconKey\n }))\n };\n\n return (\n <section id=\"features\" className={cn(\"px-16 py-10 mx-16 md:mx-32 scroll-mt-18\", sectionClassName)}>\n <h2 className=\"text-3xl md:text-4xl font-bold text-center mb-4\">\n {data.title} <span className=\"text-purple-500\">{data.eyesOn}</span>\n </h2>\n <p className=\"text-center text-gray-600 dark:text-gray-400 mb-12 text-base md:text-lg mx-auto whitespace-nowrap\">\n {data.description}\n </p>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-8 gap-y-12\">\n {data.items.map((feature) => {\n const Icon = getGlobalIcon(feature.iconKey);\n return (\n <div\n key={feature.id}\n data-feature-id={feature.id}\n className=\"bg-white dark:bg-gray-800/60 p-8 rounded-xl border border-gray-200 dark:border-gray-700 hover:border-purple-300 dark:hover:border-purple-500/50 transition shadow-sm dark:shadow-none\"\n >\n <div className=\"text-4xl mb-4 flex items-center justify-start\">\n <Icon className=\"w-8 h-8\" />\n </div>\n <h3 className=\"text-xl font-semibold mb-3 text-gray-900 dark:text-gray-100\">{feature.title}</h3>\n <p className=\"text-gray-700 dark:text-gray-300\">{feature.description}</p>\n </div>\n )\n })}\n </div>\n </section>\n )\n}\n\n","import { getTranslations } from 'next-intl/server';\nimport { cn } from '@lib/utils';\nimport { richText } from '@third-ui/main/rich-text-expert';\n\ninterface TipSection {\n id: string;\n title: string;\n description: string;\n}\n\ninterface TipsData {\n title: string;\n eyesOn: string;\n leftColumn: TipSection[];\n rightColumn: TipSection[];\n}\n\nexport async function Tips({ \n locale, \n sectionClassName \n}: { \n locale: string;\n sectionClassName?: string;\n}) {\n const t = await getTranslations({ locale, namespace: 'tips' });\n \n // Process translation data\n const sections = t.raw('sections') as Array<{\n title: string;\n description: string;\n }>;\n \n const processedSections = sections.map((section, index) => ({\n id: `tip-section-${index}`,\n title: section.title,\n description: richText(t, `sections.${index}.description`)\n }));\n \n const midPoint = Math.ceil(processedSections.length / 2);\n const leftColumn = processedSections.slice(0, midPoint);\n const rightColumn = processedSections.slice(midPoint);\n \n const data: TipsData = {\n title: t('title'),\n eyesOn: t('eyesOn'),\n leftColumn,\n rightColumn\n };\n\n return (\n <section id=\"tips\" className={cn(\"px-16 py-10 mx-16 md:mx-32 scroll-mt-20\", sectionClassName)}>\n <h2 className=\"text-3xl md:text-4xl font-bold text-center mb-16\">\n {data.title} <span className=\"text-purple-500\">{data.eyesOn}</span>\n </h2>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-12 bg-gray-50 dark:bg-gray-800/60 border border-gray-200 dark:border-gray-700 rounded-2xl p-8 md:p-12 shadow-sm dark:shadow-none\">\n {[data.leftColumn, data.rightColumn].map((column: TipSection[], colIndex) => (\n <div key={colIndex} className=\"space-y-8\">\n {column.map((tip: TipSection) => (\n <div key={tip.id} data-tip-id={tip.id} className=\"space-y-4\">\n <h3 className=\"text-2xl font-semibold\">{tip.title}</h3>\n <p className=\"\">{tip.description}</p>\n </div>\n ))}\n </div>\n ))}\n </div>\n </section>\n )\n}\n\n","import { getTranslations } from 'next-intl/server';\nimport { cn } from '@lib/utils';\nimport { richText } from '@third-ui/main/rich-text-expert';\nimport { FAQInteractive } from '@third-ui/main';\n\ninterface FAQData {\n title: string;\n description: string;\n items: Array<{\n id: string;\n question: string;\n answer: string;\n }>;\n}\n\nexport async function FAQ({ \n locale, \n sectionClassName \n}: { \n locale: string;\n sectionClassName?: string;\n}) {\n const t = await getTranslations({ locale, namespace: 'faq' });\n \n // Process translation data\n const rawItems = t.raw('items') as Array<{\n question: string;\n answer: string;\n }>;\n \n const data: FAQData = {\n title: t('title'),\n description: richText(t, 'description'),\n items: rawItems.map((item, index) => ({\n id: `faq-item-${index}`,\n question: item.question,\n answer: richText(t, `items.${index}.answer`)\n }))\n };\n\n return (\n <section id=\"faq\" className={cn(\"px-16 py-10 mx-16 md:mx-32 scroll-mt-20\", sectionClassName)}>\n <h2 className=\"text-3xl md:text-4xl font-bold text-center mb-4\">\n {data.title}\n </h2>\n <p className=\"text-center text-gray-600 dark:text-gray-400 mb-12 text-base md:text-lg mx-auto\">\n {data.description}\n </p>\n <div className=\"space-y-6\">\n {data.items.map((item) => (\n <div\n key={item.id}\n data-faq-id={item.id}\n className=\"bg-white dark:bg-gray-800/60 p-6 rounded-xl border border-gray-200 dark:border-gray-700 hover:border-purple-300 dark:hover:border-purple-500/50 transition shadow-sm dark:shadow-none\"\n >\n <button\n className=\"w-full flex items-center justify-between text-left focus:outline-none\"\n data-faq-toggle={item.id}\n aria-expanded=\"false\"\n >\n <span className=\"text-lg font-semibold text-gray-900 dark:text-gray-100\">{item.question}</span>\n <svg \n className=\"w-6 h-6 text-gray-400 ml-2 transition-transform duration-200\" \n data-faq-icon={item.id}\n fill=\"none\" \n stroke=\"currentColor\" \n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n <div \n className=\"mt-4 text-gray-700 dark:text-gray-300 text-base hidden\" \n data-faq-content={item.id}\n >\n {item.answer}\n </div>\n </div>\n ))}\n </div>\n \n <FAQInteractive data={data} />\n </section>\n );\n} ","/* eslint-disable react/no-unescaped-entities */\nimport { getTranslations } from 'next-intl/server';\nimport { cn } from '@lib/utils';\nimport { richText } from '@third-ui/main/rich-text-expert';\n\ninterface SeoSection {\n id: string;\n title: string;\n content: string;\n}\n\ninterface SeoContentData {\n title: string;\n eyesOn: string;\n description: string;\n intro: string;\n sections: SeoSection[];\n conclusion: string;\n}\n\nexport async function SeoContent({ \n locale, \n sectionClassName \n}: { \n locale: string;\n sectionClassName?: string;\n}) {\n const t = await getTranslations({ locale, namespace: 'seoContent' });\n \n // Process translation data\n const rawSections = t.raw('sections') as Array<{\n title: string;\n content: string;\n }>;\n \n const data: SeoContentData = {\n title: t('title'),\n eyesOn: t('eyesOn'),\n description: t('description'),\n intro: richText(t, 'intro'),\n sections: rawSections.map((section, index) => ({\n id: `seo-section-${index}`,\n title: section.title,\n content: richText(t, `sections.${index}.content`)\n })),\n conclusion: richText(t, 'conclusion')\n };\n\n return (\n <section id=\"seo\" className={cn(\"px-16 py-10 mx-16 md:mx-32 scroll-mt-20\", sectionClassName)}>\n <h2 className=\"text-3xl md:text-4xl font-bold text-center mb-8\">\n {data.title} <span className=\"text-purple-500\">{data.eyesOn}</span>\n </h2>\n <h3 className=\"text-center text-gray-600 dark:text-gray-400 mb-12 text-lg\">\n {data.description}\n </h3>\n <div className=\"bg-gray-50 dark:bg-gray-800/60 border border-gray-200 dark:border-gray-700 rounded-2xl p-8 md:p-12 shadow-sm dark:shadow-none\">\n <div className=\"space-y-10\">\n <p className=\"text-gray-600 dark:text-gray-400 text-lg\">\n {data.intro}\n </p>\n {data.sections.map((section) => (\n <div key={section.id} data-seo-section={section.id}>\n <h2 className=\"text-xl font-semibold mb-3 text-gray-900 dark:text-gray-100 flex items-center\">\n {section.title}\n </h2>\n <p className=\"text-gray-700 dark:text-gray-300\">{section.content}</p>\n </div>\n ))}\n </div>\n <p className=\"mt-10 text-gray-600 dark:text-gray-400 text-lg\">\n {data.conclusion}\n </p>\n </div>\n </section>\n )\n}\n\n","import { getTranslations } from 'next-intl/server';\nimport { GradientButton } from \"@third-ui/fuma/mdx/gradient-button\";\nimport { cn } from '@lib/utils';\nimport { richText } from '@third-ui/main/rich-text-expert';\n\ninterface CTAData {\n title: string;\n eyesOn: string;\n description1: string;\n description2: string;\n button: string;\n url: string;\n}\n\nexport async function CTA({ \n locale, \n sectionClassName \n}: { \n locale: string;\n sectionClassName?: string;\n}) {\n const t = await getTranslations({ locale, namespace: 'cta' });\n \n const data: CTAData = {\n title: t('title'),\n eyesOn: t('eyesOn'),\n description1: richText(t, 'description1'),\n description2: t('description2'),\n button: t('button'),\n url: t('url')\n };\n\n return (\n <section id=\"cta\" className={cn(\"px-16 py-20 mx-16 md:mx-32 scroll-mt-20\", sectionClassName)}>\n <div className=\"\n bg-gradient-to-r from-[#f7f8fa] via-[#e0c3fc] to-[#b2fefa]\n dark:bg-gradient-to-r dark:from-[#2d0b4e] dark:via-[#6a3fa0] dark:to-[#3a185a]\n rounded-2xl p-12 text-center\n bg-[length:200%_auto] animate-cta-gradient-wave\n \">\n <h2 className=\"text-3xl md:text-4xl font-bold mb-6\">\n {data.title} <span className=\"text-purple-400\">{data.eyesOn}</span>?\n </h2>\n <p className=\"text-2xl mx-auto mb-8\">\n {data.description1}\n <br />\n <span className=\"text-purple-400\">{data.description2}</span>\n </p>\n <GradientButton\n title={data.button}\n href={data.url}\n align=\"center\"\n />\n </div>\n </section>\n )\n}\n\n","import { getTranslations } from 'next-intl/server';\nimport { globalLucideIcons as icons } from '@base-ui/components/global-icon';\nimport Link from \"next/link\";\n\ninterface FooterData {\n terms: string;\n privacy: string;\n contactUs: string;\n email: string;\n copyright: string;\n company: string;\n}\n\nexport async function Footer({ locale }: { locale: string }) {\n const tFooter = await getTranslations({ locale, namespace: 'footer' });\n \n const data: FooterData = {\n terms: tFooter('terms', { defaultValue: 'Terms of Service' }),\n privacy: tFooter('privacy', { defaultValue: 'Privacy Policy' }),\n contactUs: tFooter('contactUs', { defaultValue: 'Contact Us' }),\n email: tFooter('email'),\n company: tFooter('company'),\n copyright: tFooter('copyright', { year: new Date().getFullYear(), name: tFooter('company') })\n };\n\n return (\n <div className=\"mb-10 w-full mx-auto border-t-purple-700/80 border-t-1\">\n <footer>\n <div className=\"w-full flex flex-col items-center justify-center px-4 py-8 space-y-3\">\n <div className=\"flex items-center justify-center space-x-6 text-xs\">\n <Link href={`/${locale}/legal/terms`} className=\"flex items-center space-x-1 hover:underline\">\n <icons.ReceiptText className=\"h-3.5 w-3.5\"/>\n <span>{data.terms}</span>\n </Link>\n <Link href={`/${locale}/legal/privacy`} className=\"flex items-center space-x-1 hover:underline\">\n <icons.ShieldUser className=\"h-3.5 w-3.5\"/>\n <span>{data.privacy}</span>\n </Link>\n <div className=\"relative group\">\n <div className=\"absolute left-2/3 -translate-x-1/4 bottom-full mb-1 hidden group-hover:block bg-zinc-600 text-white text-xs rounded px-3 py-1 whitespace-nowrap z-10 shadow-lg\">\n {data.email}\n </div>\n <a\n href={`mailto:${data.email}`}\n className=\"flex items-center space-x-1 underline cursor-pointer px-2\"\n >\n <icons.Mail className=\"h-3.5 w-3.5\"/>\n <span>{data.contactUs}</span>\n </a>\n </div>\n </div>\n <div className=\"text-xs text-center\">\n <span>{data.copyright}</span>\n </div>\n </div>\n </footer>\n </div>\n );\n}\n\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { cn } from '@lib/utils';\nimport { getTranslations } from 'next-intl/server';\nimport { PricePlanInteractive } from '@third-ui/main';\n\nexport interface PricePlanProps {\n locale: string\n currency?: string\n pricePlanConfig: PricePlanAppConfig\n sectionClassName?: string\n}\n\n// billing definition\nexport interface BillingOption {\n key: string\n discount: number\n}\n\nexport interface Prices {\n [key: string]: number | string\n}\n\nexport interface PricePlanAppConfig {\n billingOptions: BillingOption[]\n prices: Prices\n minPlanFeaturesCount: number\n}\n\ninterface PricePlanData {\n title: string;\n subtitle: string;\n billingSwitch: {\n options: Array<{\n key: string\n name: string\n unit: string\n discountText: string\n subTitle?: string\n }>\n defaultKey: string\n };\n plans: Array<any>;\n currency: string;\n pricePlanConfig: PricePlanAppConfig;\n}\n\nexport async function PricePlan({ \n locale, \n currency = '$', \n pricePlanConfig, \n sectionClassName \n}: PricePlanProps) {\n const t = await getTranslations({ locale, namespace: 'pricePlan' })\n \n const data: PricePlanData = {\n title: t('title'),\n subtitle: t('subtitle'),\n billingSwitch: t.raw('billingSwitch') as {\n options: Array<{\n key: string\n name: string\n unit: string\n discountText: string\n subTitle?: string\n }>\n defaultKey: string\n },\n plans: t.raw('plans') as Array<any>,\n currency,\n pricePlanConfig\n };\n\n // Static data processing for server-side rendering\n const billingOptions = data.pricePlanConfig.billingOptions;\n const prices = data.pricePlanConfig.prices;\n const minPlanFeaturesCount = data.pricePlanConfig.minPlanFeaturesCount;\n \n // Use default billing for static rendering\n const defaultBilling = billingOptions.find((opt: any) => opt.key === data.billingSwitch.defaultKey) || billingOptions[0];\n const defaultBillingDisplay = data.billingSwitch.options.find((opt: any) => opt.key === data.billingSwitch.defaultKey) || data.billingSwitch.options[0];\n\n // Calculate features count\n const maxFeaturesCount = Math.max(\n ...data.plans.map((plan: any) => plan.features?.length || 0),\n minPlanFeaturesCount || 0\n );\n\n // Handle card height alignment\n const getFeatureRows = (plan: any) => {\n const features = plan.features || [];\n const filled = [...features];\n while (filled.length < maxFeaturesCount) filled.push(null);\n return filled;\n };\n\n // Static price render logic for default billing\n function renderPrice(plan: any, billingKey = data.billingSwitch.defaultKey) {\n const priceValue = prices[plan.key];\n const currentBilling = billingOptions.find((opt: any) => opt.key === billingKey) || defaultBilling;\n const currentBillingDisplay = data.billingSwitch.options.find((opt: any) => opt.key === billingKey) || defaultBillingDisplay;\n const billingSubTitle = currentBillingDisplay?.subTitle || '';\n \n // Non-numeric (like 'Custom') directly display\n if (typeof priceValue !== 'number' || isNaN(priceValue)) {\n return (\n <div className=\"flex flex-col items-start w-full\" data-price-container={plan.key}>\n <div className=\"flex items-end gap-2\">\n <span className=\"text-4xl font-extrabold text-gray-900 dark:text-gray-100\" data-price-value={plan.key}>{priceValue}</span>\n </div>\n <div className=\"flex items-center gap-2 min-h-[24px] mt-1\">\n <span className={cn('text-xs text-gray-700 dark:text-gray-300 font-medium', plan.showBillingSubTitle === false && 'opacity-0 select-none')} data-price-subtitle={plan.key}>\n {plan.showBillingSubTitle === false ? '' : billingSubTitle}\n </span>\n </div>\n </div>\n );\n }\n \n // Numeric price logic\n const originValue = Number(priceValue);\n const discount = currentBilling.discount;\n const hasDiscount = discount !== 0;\n const saleValue = originValue * (1 - discount);\n const formatPrice = (v: number) => Number(v.toFixed(2)).toString();\n const unit = currentBillingDisplay.unit || '';\n let discountText = '';\n if (hasDiscount && currentBillingDisplay.discountText) {\n discountText = currentBillingDisplay.discountText.replace('{percent}', String(Math.round(Math.abs(discount) * 100)));\n }\n const showNaN = saleValue < 0;\n \n return (\n <div className=\"flex flex-col items-start w-full\" data-price-container={plan.key}>\n <div className=\"flex items-end gap-2\">\n <span className=\"text-4xl font-extrabold text-gray-900 dark:text-gray-100\" data-price-value={plan.key}>\n {data.currency}{showNaN ? 'NaN' : (hasDiscount ? formatPrice(saleValue) : formatPrice(originValue))}\n </span>\n <span className=\"text-lg text-gray-700 dark:text-gray-300 font-medium mb-1\" data-price-unit={plan.key}>{unit}</span>\n </div>\n <div className=\"flex items-center gap-2 min-h-[24px] mt-1\">\n {hasDiscount && (\n <>\n <span className=\"text-base text-gray-400 line-through\" data-price-original={plan.key}>\n {data.currency}{showNaN ? 'NaN' : formatPrice(originValue)}\n </span>\n {discountText && (\n <span className=\"px-2 py-0.5 text-xs rounded bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 font-semibold align-middle\" data-price-discount={plan.key}>\n {discountText}\n </span>\n )}\n </>\n )}\n <span className={cn('text-xs text-gray-700 dark:text-gray-300 font-medium', plan.showBillingSubTitle === false && 'opacity-0 select-none')} data-price-subtitle={plan.key}>\n {plan.showBillingSubTitle === false ? '' : billingSubTitle}\n </span>\n </div>\n </div>\n );\n }\n\n return (\n <section id=\"pricing\" className={cn(\"px-4 py-10 md:px-16 md:py-16 mx-auto max-w-7xl scroll-mt-10\", sectionClassName)}>\n {/* title and subtitle */}\n <h2 className=\"text-3xl md:text-4xl font-bold text-center mb-3\">\n {data.title}\n </h2>\n <p className=\"text-center text-gray-600 dark:text-gray-400 mb-8 text-base md:text-lg mx-auto\">\n {data.subtitle}\n </p>\n\n {/* billing switch button */}\n <div className=\"flex flex-col items-center\">\n <div className=\"flex items-center relative mb-3\">\n <div className=\"flex bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-full p-1\" data-billing-switch>\n <button\n className={cn(\n 'min-w-[120px] px-6 py-2 font-medium transition text-lg relative',\n data.billingSwitch.defaultKey === 'monthly'\n ? 'text-white bg-gradient-to-r from-purple-400 to-pink-500 hover:from-purple-500 hover:to-pink-600 dark:from-purple-500 dark:to-pink-600 dark:hover:from-purple-600 rounded-full shadow-sm'\n : 'text-gray-800 dark:text-gray-200 hover:text-gray-900 dark:hover:text-gray-100 rounded-full'\n )}\n data-billing-button=\"monthly\"\n type=\"button\"\n >\n {(data.billingSwitch.options.find((opt: any) => opt.key === 'monthly')?.name) || 'Monthly'}\n </button>\n <button\n className={cn(\n 'min-w-[120px] px-6 py-2 font-medium transition text-lg relative',\n data.billingSwitch.defaultKey === 'yearly'\n ? 'text-white bg-gradient-to-r from-purple-400 to-pink-500 hover:from-purple-500 hover:to-pink-600 dark:from-purple-500 dark:to-pink-600 dark:hover:from-purple-600 rounded-full shadow-sm'\n : 'text-gray-800 dark:text-gray-200 hover:text-gray-900 dark:hover:text-gray-100 rounded-full'\n )}\n data-billing-button=\"yearly\"\n type=\"button\"\n >\n {(data.billingSwitch.options.find((opt: any) => opt.key === 'yearly')?.name) || 'Yearly'}\n </button>\n </div>\n </div>\n \n {/* Discount info - static for default billing */}\n <div className=\"h-8 flex items-center justify-center mb-3\" data-discount-info>\n {(() => {\n const opt = data.billingSwitch.options.find((opt: any) => opt.key === data.billingSwitch.defaultKey);\n const bOpt = billingOptions.find((opt: any) => opt.key === data.billingSwitch.defaultKey);\n if (!(opt && bOpt && opt.discountText && bOpt.discount !== 0)) return null;\n return (\n <span className=\"px-2 py-1 text-xs rounded bg-yellow-100 text-yellow-800 font-semibold align-middle text-center inline-flex items-center justify-center whitespace-nowrap\">\n {opt.discountText.replace(\n '{percent}',\n String(Math.round(Math.abs(bOpt.discount) * 100))\n )}\n </span>\n );\n })()}\n </div>\n </div>\n\n {/* price card area */}\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-8\">\n {data.plans.map((plan: any, _idx: number) => (\n <div\n key={plan.key}\n data-price-plan={plan.key}\n className={cn(\n 'flex flex-col bg-white dark:bg-gray-800/60 rounded-2xl border border-gray-300 dark:border-[#7c3aed40] transition p-8 h-full shadow-sm dark:shadow-none',\n 'hover:border-2 hover:border-purple-500',\n 'focus-within:border-2 focus-within:border-purple-500'\n )}\n style={{ minHeight: maxFeaturesCount*100 }}\n >\n {/* main title and tag */}\n <div className=\"flex items-center gap-2 mb-2\">\n <span className=\"text-xl font-bold text-gray-900 dark:text-gray-100\">{plan.title}</span>\n {plan.titleTags && plan.titleTags.map((tag: string, i: number) => (\n <span key={i} className=\"px-2 py-0.5 text-xs rounded bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200 font-semibold align-middle\">{tag}</span>\n ))}\n </div>\n {/* price and unit/discount */}\n {renderPrice(plan)}\n {/* feature list */}\n <ul className=\"flex-1 mb-6 mt-4\">\n {getFeatureRows(plan).map((feature: any, i: number) => (\n <li key={i} className=\"flex items-center gap-2 mb-2 min-h-[28px]\" data-feature-item={`${plan.key}-${i}`}>\n {/* icon */}\n {feature ? (\n <span className=\"inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-200 mr-1\">\n {feature.icon ? <span>{feature.icon}</span> : <span className=\"font-bold\">✓</span>}\n </span>\n ) : (\n <span className=\"inline-flex items-center justify-center w-5 h-5 rounded-full mr-1\">&nbsp;</span>\n )}\n {/* tag */}\n {feature && feature.tag && (\n <span className=\"px-1 py-0.5 text-[6px] rounded bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 font-semibold align-middle\">{feature.tag}</span>\n )}\n {/* description + tooltip */}\n {feature ? (\n <span className=\"relative group cursor-pointer text-sm text-gray-800 dark:text-gray-200\">\n {feature.description}\n {feature.tooltip && (\n <span\n className=\"ml-1 align-middle inline-flex\"\n data-tooltip-trigger={`${plan.key}-${i}`}\n data-tooltip-content={feature.tooltip}\n >\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n </span>\n )}\n </span>\n ) : (\n <span>&nbsp;</span>\n )}\n </li>\n ))}\n </ul>\n {/* placeholder, ensure card height consistency */}\n <div className=\"flex-1\" />\n {/* button */}\n <button\n className={cn(\n 'w-full py-2 mt-auto text-white text-base font-bold shadow-lg hover:shadow-xl transition-all duration-300 rounded-full',\n plan.button?.disabled\n ? 'bg-gray-400 cursor-not-allowed'\n : 'bg-gradient-to-r from-purple-400 to-pink-500 hover:from-purple-500 hover:to-pink-600 dark:from-purple-500 dark:to-pink-600 dark:hover:from-purple-600 dark:hover:to-pink-700'\n )}\n disabled={plan.button?.disabled}\n type=\"button\"\n data-plan-button={plan.key}\n >\n {plan.button?.text || '--'}\n </button>\n </div>\n ))}\n </div>\n \n <PricePlanInteractive data={data} />\n </section>\n )\n} "]}