kofi-stack-template-generator 2.1.37 → 2.1.38

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 (323) hide show
  1. package/.turbo/turbo-build.log +6 -6
  2. package/dist/index.js +8057 -440
  3. package/package.json +1 -1
  4. package/src/templates.generated.ts +248 -94
  5. package/templates/integrations/posthog/src/components/providers/posthog-provider.tsx.hbs +4 -1
  6. package/templates/marketing/payload/package.json.hbs +41 -26
  7. package/templates/marketing/payload/src/Footer/Component.client.tsx +288 -0
  8. package/templates/marketing/payload/src/Footer/Component.tsx +11 -0
  9. package/templates/marketing/payload/src/Footer/RowLabel.tsx +15 -0
  10. package/templates/marketing/payload/src/Footer/config.ts +178 -0
  11. package/templates/marketing/payload/src/Footer/hooks/{revalidateFooter.ts.hbs → revalidateFooter.ts} +5 -5
  12. package/templates/marketing/payload/src/Header/Component.client.tsx +94 -0
  13. package/templates/marketing/payload/src/Header/Component.tsx +10 -0
  14. package/templates/marketing/payload/src/Header/MegaMenu/index.tsx +197 -0
  15. package/templates/marketing/payload/src/Header/MobileMenu/HamburgerIcon.tsx +48 -0
  16. package/templates/marketing/payload/src/Header/MobileMenu/index.tsx +299 -0
  17. package/templates/marketing/payload/src/Header/Nav/index.tsx +76 -0
  18. package/templates/marketing/payload/src/Header/RowLabel.tsx +21 -0
  19. package/templates/marketing/payload/src/Header/config.ts +208 -0
  20. package/templates/marketing/payload/src/Header/hooks/{revalidateHeader.ts.hbs → revalidateHeader.ts} +5 -5
  21. package/templates/marketing/payload/src/access/{authenticated.ts.hbs → authenticated.ts} +1 -1
  22. package/templates/marketing/payload/src/access/{authenticatedOrPublished.ts.hbs → authenticatedOrPublished.ts} +8 -8
  23. package/templates/marketing/payload/src/app/(docs)/docs/[[...slug]]/page.tsx +117 -0
  24. package/templates/marketing/payload/src/app/(docs)/docs/layout.tsx +39 -0
  25. package/templates/marketing/payload/src/app/(docs)/layout.tsx +44 -0
  26. package/templates/marketing/payload/src/app/(frontend)/(sitemaps)/pages-sitemap.xml/route.ts +68 -0
  27. package/templates/marketing/payload/src/app/(frontend)/(sitemaps)/posts-sitemap.xml/route.ts +55 -0
  28. package/templates/marketing/payload/src/app/(frontend)/[slug]/page.client.tsx +15 -0
  29. package/templates/marketing/payload/src/app/(frontend)/[slug]/page.tsx +114 -0
  30. package/templates/marketing/payload/src/app/(frontend)/api/docs-search/route.ts +67 -0
  31. package/templates/marketing/payload/src/app/(frontend)/api/newsletter/route.ts +260 -0
  32. package/templates/marketing/payload/src/app/(frontend)/api/pricing/route.ts +266 -0
  33. package/templates/marketing/payload/src/app/(frontend)/globals.css +1019 -0
  34. package/templates/marketing/payload/src/app/(frontend)/layout.tsx +114 -0
  35. package/templates/marketing/payload/src/app/(frontend)/next/exit-preview/route.ts +7 -0
  36. package/templates/marketing/payload/src/app/(frontend)/next/preview/route.ts +56 -0
  37. package/templates/marketing/payload/src/app/(frontend)/next/seed/route.ts +31 -0
  38. package/templates/marketing/payload/src/app/(frontend)/not-found.tsx +17 -0
  39. package/templates/marketing/payload/src/app/(frontend)/page.tsx +5 -0
  40. package/templates/marketing/payload/src/app/(frontend)/posts/BlogPageClient.tsx +190 -0
  41. package/templates/marketing/payload/src/app/(frontend)/posts/[slug]/BlogPostContent.tsx +67 -0
  42. package/templates/marketing/payload/src/app/(frontend)/posts/[slug]/page.client.tsx +15 -0
  43. package/templates/marketing/payload/src/app/(frontend)/posts/[slug]/page.tsx +118 -0
  44. package/templates/marketing/payload/src/app/(frontend)/posts/page/[pageNumber]/page.client.tsx +15 -0
  45. package/templates/marketing/payload/src/app/(frontend)/posts/page/[pageNumber]/page.tsx +87 -0
  46. package/templates/marketing/payload/src/app/(frontend)/posts/page.tsx +49 -0
  47. package/templates/marketing/payload/src/app/(frontend)/search/page.client.tsx +15 -0
  48. package/templates/marketing/payload/src/app/(frontend)/search/page.tsx +87 -0
  49. package/templates/marketing/payload/src/app/(payload)/admin/[[...segments]]/not-found.tsx +24 -0
  50. package/templates/marketing/payload/src/app/(payload)/admin/[[...segments]]/page.tsx +24 -0
  51. package/templates/marketing/payload/src/app/(payload)/admin/importMap.js +83 -0
  52. package/templates/marketing/payload/src/app/(payload)/api/[...slug]/{route.ts.hbs → route.ts} +13 -9
  53. package/templates/marketing/payload/src/app/(payload)/api/graphql/{route.ts.hbs → route.ts} +2 -2
  54. package/templates/marketing/payload/src/app/(payload)/api/graphql-playground/{route.ts.hbs → route.ts} +3 -3
  55. package/templates/marketing/payload/src/app/(payload)/custom.scss +0 -0
  56. package/templates/marketing/payload/src/app/(payload)/layout.tsx +31 -0
  57. package/templates/marketing/payload/src/blocks/ArchiveBlock/Component.tsx +65 -0
  58. package/templates/marketing/payload/src/blocks/ArchiveBlock/config.ts +120 -0
  59. package/templates/marketing/payload/src/blocks/Banner/Component.tsx +26 -0
  60. package/templates/marketing/payload/src/blocks/Banner/config.ts +67 -0
  61. package/templates/marketing/payload/src/blocks/BentoFeatures/Component.tsx +243 -0
  62. package/templates/marketing/payload/src/blocks/BentoFeatures/config.ts +147 -0
  63. package/templates/marketing/payload/src/blocks/CallToAction/Component.tsx +31 -0
  64. package/templates/marketing/payload/src/blocks/CallToAction/config.ts +68 -0
  65. package/templates/marketing/payload/src/blocks/Code/Component.client.tsx +33 -0
  66. package/templates/marketing/payload/src/blocks/Code/Component.tsx +21 -0
  67. package/templates/marketing/payload/src/blocks/Code/CopyButton.tsx +33 -0
  68. package/templates/marketing/payload/src/blocks/Code/config.ts +33 -0
  69. package/templates/marketing/payload/src/blocks/Content/Component.tsx +41 -0
  70. package/templates/marketing/payload/src/blocks/Content/config.ts +105 -0
  71. package/templates/marketing/payload/src/blocks/FAQAccordion/Component.tsx +90 -0
  72. package/templates/marketing/payload/src/blocks/FAQAccordion/config.ts +75 -0
  73. package/templates/marketing/payload/src/blocks/FeatureGrid/Component.tsx +108 -0
  74. package/templates/marketing/payload/src/blocks/FeatureGrid/config.ts +109 -0
  75. package/templates/marketing/payload/src/blocks/FeatureShowcase/Component.tsx +107 -0
  76. package/templates/marketing/payload/src/blocks/FeatureShowcase/config.ts +111 -0
  77. package/templates/marketing/payload/src/blocks/FinalCTA/Component.tsx +117 -0
  78. package/templates/marketing/payload/src/blocks/FinalCTA/config.ts +50 -0
  79. package/templates/marketing/payload/src/blocks/Form/Checkbox/index.tsx +45 -0
  80. package/templates/marketing/payload/src/blocks/Form/Component.tsx +170 -0
  81. package/templates/marketing/payload/src/blocks/Form/Country/index.tsx +65 -0
  82. package/templates/marketing/payload/src/blocks/Form/Country/options.ts +982 -0
  83. package/templates/marketing/payload/src/blocks/Form/Email/index.tsx +38 -0
  84. package/templates/marketing/payload/src/blocks/Form/Error/index.tsx +13 -0
  85. package/templates/marketing/payload/src/blocks/Form/Message/index.tsx +13 -0
  86. package/templates/marketing/payload/src/blocks/Form/Number/index.tsx +36 -0
  87. package/templates/marketing/payload/src/blocks/Form/Select/index.tsx +63 -0
  88. package/templates/marketing/payload/src/blocks/Form/State/index.tsx +64 -0
  89. package/templates/marketing/payload/src/blocks/Form/State/options.ts +52 -0
  90. package/templates/marketing/payload/src/blocks/Form/Text/index.tsx +32 -0
  91. package/templates/marketing/payload/src/blocks/Form/Textarea/index.tsx +40 -0
  92. package/templates/marketing/payload/src/blocks/Form/Width/index.tsx +13 -0
  93. package/templates/marketing/payload/src/blocks/Form/config.ts +77 -0
  94. package/templates/marketing/payload/src/blocks/Form/fields.tsx +21 -0
  95. package/templates/marketing/payload/src/blocks/HowItWorks/Component.tsx +59 -0
  96. package/templates/marketing/payload/src/blocks/HowItWorks/config.ts +88 -0
  97. package/templates/marketing/payload/src/blocks/IndustryTabs/Component.tsx +132 -0
  98. package/templates/marketing/payload/src/blocks/IndustryTabs/config.ts +77 -0
  99. package/templates/marketing/payload/src/blocks/LogoBanner/Component.tsx +95 -0
  100. package/templates/marketing/payload/src/blocks/LogoBanner/config.ts +48 -0
  101. package/templates/marketing/payload/src/blocks/MediaBlock/Component.tsx +67 -0
  102. package/templates/marketing/payload/src/blocks/MediaBlock/config.ts +14 -0
  103. package/templates/marketing/payload/src/blocks/Personas/Component.tsx +69 -0
  104. package/templates/marketing/payload/src/blocks/Personas/config.ts +96 -0
  105. package/templates/marketing/payload/src/blocks/PricingTable/ComparisonTable.tsx +250 -0
  106. package/templates/marketing/payload/src/blocks/PricingTable/Component.tsx +443 -0
  107. package/templates/marketing/payload/src/blocks/PricingTable/config.ts +142 -0
  108. package/templates/marketing/payload/src/blocks/ProofBanner/Component.tsx +65 -0
  109. package/templates/marketing/payload/src/blocks/ProofBanner/config.ts +42 -0
  110. package/templates/marketing/payload/src/blocks/RelatedPosts/Component.tsx +32 -0
  111. package/templates/marketing/payload/src/blocks/RenderBlocks.tsx +92 -0
  112. package/templates/marketing/payload/src/blocks/TestimonialsGrid/Component.tsx +107 -0
  113. package/templates/marketing/payload/src/blocks/TestimonialsGrid/config.ts +76 -0
  114. package/templates/marketing/payload/src/blocks/TrustColumns/Component.tsx +83 -0
  115. package/templates/marketing/payload/src/blocks/TrustColumns/config.ts +70 -0
  116. package/templates/marketing/payload/src/collections/Categories.ts +28 -0
  117. package/templates/marketing/payload/src/collections/FAQs/index.ts +100 -0
  118. package/templates/marketing/payload/src/collections/Media.ts +160 -0
  119. package/templates/marketing/payload/src/collections/Pages/hooks/revalidatePage.ts +43 -0
  120. package/templates/marketing/payload/src/collections/Pages/index.ts +168 -0
  121. package/templates/marketing/payload/src/collections/Posts/hooks/populateAuthors.ts +41 -0
  122. package/templates/marketing/payload/src/collections/Posts/hooks/revalidatePost.ts +44 -0
  123. package/templates/marketing/payload/src/collections/Posts/index.ts +259 -0
  124. package/templates/marketing/payload/src/collections/Users/index.ts +26 -0
  125. package/templates/marketing/payload/src/components/AdminBar/index.scss +7 -0
  126. package/templates/marketing/payload/src/components/AdminBar/index.tsx +89 -0
  127. package/templates/marketing/payload/src/components/Analytics/CTATracker.tsx +33 -0
  128. package/templates/marketing/payload/src/components/Analytics/FeatureSectionTracker.tsx +47 -0
  129. package/templates/marketing/payload/src/components/Analytics/PricingViewTracker.tsx +46 -0
  130. package/templates/marketing/payload/src/components/Analytics/index.tsx +3 -0
  131. package/templates/marketing/payload/src/components/BeforeDashboard/SeedButton/index.tsx +89 -0
  132. package/templates/marketing/payload/src/components/BeforeDashboard/index.tsx +69 -0
  133. package/templates/marketing/payload/src/components/BeforeLogin/index.tsx +14 -0
  134. package/templates/marketing/payload/src/components/BlogCTA/index.tsx +77 -0
  135. package/templates/marketing/payload/src/components/Card/index.tsx +85 -0
  136. package/templates/marketing/payload/src/components/CollectionArchive/index.tsx +32 -0
  137. package/templates/marketing/payload/src/components/JsonLd/index.tsx +138 -0
  138. package/templates/marketing/payload/src/components/Link/index.tsx +66 -0
  139. package/templates/marketing/payload/src/components/LivePreviewListener/index.tsx +10 -0
  140. package/templates/marketing/payload/src/components/Logo/Logo.tsx +46 -0
  141. package/templates/marketing/payload/src/components/Media/ImageMedia/index.tsx +80 -0
  142. package/templates/marketing/payload/src/components/Media/VideoMedia/index.tsx +47 -0
  143. package/templates/marketing/payload/src/components/Media/index.tsx +26 -0
  144. package/templates/marketing/payload/src/components/Media/types.ts +22 -0
  145. package/templates/marketing/payload/src/components/PageRange/index.tsx +57 -0
  146. package/templates/marketing/payload/src/components/Pagination/index.tsx +101 -0
  147. package/templates/marketing/payload/src/components/PayloadRedirects/index.tsx +48 -0
  148. package/templates/marketing/payload/src/components/RichText/index.tsx +152 -0
  149. package/templates/marketing/payload/src/components/TableOfContents/index.tsx +128 -0
  150. package/templates/marketing/payload/src/components/ui/accordion.tsx +64 -0
  151. package/templates/marketing/payload/src/components/ui/button.tsx +52 -0
  152. package/templates/marketing/payload/src/components/ui/card.tsx +48 -0
  153. package/templates/marketing/payload/src/components/ui/checkbox.tsx +27 -0
  154. package/templates/marketing/payload/src/components/ui/input.tsx +22 -0
  155. package/templates/marketing/payload/src/components/ui/label.tsx +19 -0
  156. package/templates/marketing/payload/src/components/ui/pagination.tsx +92 -0
  157. package/templates/marketing/payload/src/components/ui/select.tsx +144 -0
  158. package/templates/marketing/payload/src/components/ui/textarea.tsx +21 -0
  159. package/templates/marketing/payload/src/endpoints/seed/contact-form.ts +111 -0
  160. package/templates/marketing/payload/src/endpoints/seed/contact-page.ts +56 -0
  161. package/templates/marketing/payload/src/endpoints/seed/directoryhub/about.ts +281 -0
  162. package/templates/marketing/payload/src/endpoints/seed/directoryhub/faqs.ts +224 -0
  163. package/templates/marketing/payload/src/endpoints/seed/directoryhub/features/automation.ts +229 -0
  164. package/templates/marketing/payload/src/endpoints/seed/directoryhub/features/custom-fields.ts +229 -0
  165. package/templates/marketing/payload/src/endpoints/seed/directoryhub/features/dashboard.ts +228 -0
  166. package/templates/marketing/payload/src/endpoints/seed/directoryhub/features/index.ts +6 -0
  167. package/templates/marketing/payload/src/endpoints/seed/directoryhub/features/monetization.ts +230 -0
  168. package/templates/marketing/payload/src/endpoints/seed/directoryhub/features/seo.ts +229 -0
  169. package/templates/marketing/payload/src/endpoints/seed/directoryhub/features/templates.ts +218 -0
  170. package/templates/marketing/payload/src/endpoints/seed/directoryhub/home.ts +555 -0
  171. package/templates/marketing/payload/src/endpoints/seed/directoryhub/index.ts +767 -0
  172. package/templates/marketing/payload/src/endpoints/seed/directoryhub/posts.ts +623 -0
  173. package/templates/marketing/payload/src/endpoints/seed/directoryhub/pricing.ts +251 -0
  174. package/templates/marketing/payload/src/endpoints/seed/directoryhub/privacy.ts +457 -0
  175. package/templates/marketing/payload/src/endpoints/seed/directoryhub/richtext-helper.ts +88 -0
  176. package/templates/marketing/payload/src/endpoints/seed/directoryhub/terms.ts +478 -0
  177. package/templates/marketing/payload/src/endpoints/seed/directoryhub/use-cases/b2b-vendor-hubs.ts +229 -0
  178. package/templates/marketing/payload/src/endpoints/seed/directoryhub/use-cases/communities.ts +230 -0
  179. package/templates/marketing/payload/src/endpoints/seed/directoryhub/use-cases/index.ts +4 -0
  180. package/templates/marketing/payload/src/endpoints/seed/directoryhub/use-cases/local-services.ts +230 -0
  181. package/templates/marketing/payload/src/endpoints/seed/directoryhub/use-cases/marketplaces.ts +230 -0
  182. package/templates/marketing/payload/src/endpoints/seed/home-static.ts +691 -0
  183. package/templates/marketing/payload/src/endpoints/seed/home.ts +675 -0
  184. package/templates/marketing/payload/src/endpoints/seed/image-1.ts +67 -0
  185. package/templates/marketing/payload/src/endpoints/seed/image-2.ts +67 -0
  186. package/templates/marketing/payload/src/endpoints/seed/image-3.ts +67 -0
  187. package/templates/marketing/payload/src/endpoints/seed/image-hero-1.ts +5 -0
  188. package/templates/marketing/payload/src/endpoints/seed/image-hero1.webp +0 -0
  189. package/templates/marketing/payload/src/endpoints/seed/image-post1.webp +0 -0
  190. package/templates/marketing/payload/src/endpoints/seed/image-post2.webp +0 -0
  191. package/templates/marketing/payload/src/endpoints/seed/image-post3.webp +0 -0
  192. package/templates/marketing/payload/src/endpoints/seed/index.ts +335 -0
  193. package/templates/marketing/payload/src/endpoints/seed/post-1.ts +315 -0
  194. package/templates/marketing/payload/src/endpoints/seed/post-2.ts +232 -0
  195. package/templates/marketing/payload/src/endpoints/seed/post-3.ts +268 -0
  196. package/templates/marketing/payload/src/fields/defaultLexical.ts +73 -0
  197. package/templates/marketing/payload/src/fields/link.ts +139 -0
  198. package/templates/marketing/payload/src/fields/linkGroup.ts +28 -0
  199. package/templates/marketing/payload/src/heros/HighImpact/index.tsx +56 -0
  200. package/templates/marketing/payload/src/heros/LowImpact/index.tsx +48 -0
  201. package/templates/marketing/payload/src/heros/MediumImpact/index.tsx +50 -0
  202. package/templates/marketing/payload/src/heros/PostHero/index.tsx +73 -0
  203. package/templates/marketing/payload/src/heros/ProductShowcase/AnimatedMockup.tsx +241 -0
  204. package/templates/marketing/payload/src/heros/ProductShowcase/index.tsx +108 -0
  205. package/templates/marketing/payload/src/heros/{RenderHero.tsx.hbs → RenderHero.tsx} +9 -9
  206. package/templates/marketing/payload/src/heros/config.ts +121 -0
  207. package/templates/marketing/payload/src/hooks/populatePublishedAt.ts +15 -0
  208. package/templates/marketing/payload/src/hooks/{revalidateRedirects.ts.hbs → revalidateRedirects.ts} +3 -3
  209. package/templates/marketing/payload/src/lib/convex.ts +13 -0
  210. package/templates/marketing/payload/src/lib/docs-source.ts +138 -0
  211. package/templates/marketing/payload/src/lib/mdx.tsx +191 -0
  212. package/templates/marketing/payload/src/payload.config.ts.hbs +95 -145
  213. package/templates/marketing/payload/src/plugins/index.ts +107 -0
  214. package/templates/marketing/payload/src/providers/HeaderTheme/index.tsx +34 -0
  215. package/templates/marketing/payload/src/providers/PostHogProvider.tsx +33 -0
  216. package/templates/marketing/payload/src/providers/Theme/InitTheme/{index.tsx.hbs → index.tsx} +11 -10
  217. package/templates/marketing/payload/src/providers/Theme/ThemeSelector/index.tsx +133 -0
  218. package/templates/marketing/payload/src/providers/Theme/ThemeSelector/types.ts +7 -0
  219. package/templates/marketing/payload/src/providers/Theme/index.tsx +60 -0
  220. package/templates/marketing/payload/src/providers/Theme/shared.ts +17 -0
  221. package/templates/marketing/payload/src/providers/Theme/{types.ts.hbs → types.ts} +3 -3
  222. package/templates/marketing/payload/src/providers/index.tsx +17 -0
  223. package/templates/marketing/payload/src/search/Component.tsx +42 -0
  224. package/templates/marketing/payload/src/search/beforeSync.ts +56 -0
  225. package/templates/marketing/payload/src/search/fieldOverrides.ts +61 -0
  226. package/templates/marketing/payload/src/utilities/deepMerge.ts +35 -0
  227. package/templates/marketing/payload/src/utilities/extractHeadings.ts +78 -0
  228. package/templates/marketing/payload/src/utilities/formatAuthors.ts +24 -0
  229. package/templates/marketing/payload/src/utilities/formatDateTime.ts +20 -0
  230. package/templates/marketing/payload/src/utilities/generateMeta.ts +93 -0
  231. package/templates/marketing/payload/src/utilities/generatePreviewPath.ts +33 -0
  232. package/templates/marketing/payload/src/utilities/getDocument.ts +32 -0
  233. package/templates/marketing/payload/src/utilities/getGlobals.ts +26 -0
  234. package/templates/marketing/payload/src/utilities/getMeUser.ts +43 -0
  235. package/templates/marketing/payload/src/utilities/getMediaUrl.ts +24 -0
  236. package/templates/marketing/payload/src/utilities/getRedirects.ts +26 -0
  237. package/templates/marketing/payload/src/utilities/getURL.ts +26 -0
  238. package/templates/marketing/payload/src/utilities/mergeOpenGraph.ts +26 -0
  239. package/templates/marketing/payload/src/utilities/toKebabCase.ts +5 -0
  240. package/templates/marketing/payload/src/utilities/ui.ts +12 -0
  241. package/templates/marketing/payload/src/utilities/useClickableCard.ts +108 -0
  242. package/templates/marketing/payload/src/utilities/useDebounce.ts +17 -0
  243. package/templates/packages/ui/src/components/button.tsx.hbs +53 -0
  244. package/templates/packages/ui/src/components/card.tsx.hbs +76 -0
  245. package/templates/packages/ui/src/components/separator.tsx.hbs +26 -0
  246. package/templates/marketing/payload/src/Footer/config.ts.hbs +0 -178
  247. package/templates/marketing/payload/src/Footer/index.ts.hbs +0 -1
  248. package/templates/marketing/payload/src/Header/RowLabel.tsx.hbs +0 -21
  249. package/templates/marketing/payload/src/Header/config.ts.hbs +0 -208
  250. package/templates/marketing/payload/src/Header/index.ts.hbs +0 -1
  251. package/templates/marketing/payload/src/access/index.ts.hbs +0 -3
  252. package/templates/marketing/payload/src/app/(frontend)/layout.tsx.hbs +0 -19
  253. package/templates/marketing/payload/src/app/(frontend)/next/seed/route.ts.hbs +0 -31
  254. package/templates/marketing/payload/src/app/(frontend)/page.tsx.hbs +0 -83
  255. package/templates/marketing/payload/src/app/(payload)/admin/[[...segments]]/not-found.tsx.hbs +0 -24
  256. package/templates/marketing/payload/src/app/(payload)/admin/[[...segments]]/page.tsx.hbs +0 -24
  257. package/templates/marketing/payload/src/app/(payload)/admin/importMap.js.hbs +0 -1
  258. package/templates/marketing/payload/src/app/(payload)/custom.scss.hbs +0 -1
  259. package/templates/marketing/payload/src/app/(payload)/layout.tsx.hbs +0 -31
  260. package/templates/marketing/payload/src/app/globals.css.hbs +0 -83
  261. package/templates/marketing/payload/src/app/layout.tsx.hbs +0 -10
  262. package/templates/marketing/payload/src/blocks/Benefits.ts.hbs +0 -34
  263. package/templates/marketing/payload/src/blocks/CTA.ts.hbs +0 -39
  264. package/templates/marketing/payload/src/blocks/Content.ts.hbs +0 -9
  265. package/templates/marketing/payload/src/blocks/FAQ.ts.hbs +0 -18
  266. package/templates/marketing/payload/src/blocks/Features.ts.hbs +0 -34
  267. package/templates/marketing/payload/src/blocks/Hero.ts.hbs +0 -40
  268. package/templates/marketing/payload/src/blocks/LogoBanner.ts.hbs +0 -17
  269. package/templates/marketing/payload/src/blocks/Pricing.ts.hbs +0 -37
  270. package/templates/marketing/payload/src/blocks/Testimonials.ts.hbs +0 -21
  271. package/templates/marketing/payload/src/blocks/index.ts.hbs +0 -9
  272. package/templates/marketing/payload/src/collections/Categories/index.ts.hbs +0 -28
  273. package/templates/marketing/payload/src/collections/FAQs/index.ts.hbs +0 -100
  274. package/templates/marketing/payload/src/collections/Media.ts.hbs +0 -164
  275. package/templates/marketing/payload/src/collections/Pages/hooks/revalidatePage.ts.hbs +0 -43
  276. package/templates/marketing/payload/src/collections/Pages/index.ts.hbs +0 -142
  277. package/templates/marketing/payload/src/collections/Posts/hooks/populateAuthors.ts.hbs +0 -41
  278. package/templates/marketing/payload/src/collections/Posts/hooks/revalidatePost.ts.hbs +0 -44
  279. package/templates/marketing/payload/src/collections/Posts/index.ts.hbs +0 -244
  280. package/templates/marketing/payload/src/collections/Users/index.ts.hbs +0 -26
  281. package/templates/marketing/payload/src/collections/index.ts.hbs +0 -6
  282. package/templates/marketing/payload/src/components/BeforeDashboard/SeedButton/index.tsx.hbs +0 -89
  283. package/templates/marketing/payload/src/components/BeforeDashboard/index.tsx.hbs +0 -69
  284. package/templates/marketing/payload/src/components/BeforeLogin/index.tsx.hbs +0 -14
  285. package/templates/marketing/payload/src/components/Link/index.tsx.hbs +0 -79
  286. package/templates/marketing/payload/src/components/Media/index.tsx.hbs +0 -67
  287. package/templates/marketing/payload/src/components/RichText/index.tsx.hbs +0 -44
  288. package/templates/marketing/payload/src/endpoints/seed/home.ts.hbs +0 -76
  289. package/templates/marketing/payload/src/endpoints/seed/image-1.ts.hbs +0 -5
  290. package/templates/marketing/payload/src/endpoints/seed/image-2.ts.hbs +0 -5
  291. package/templates/marketing/payload/src/endpoints/seed/image-hero.ts.hbs +0 -5
  292. package/templates/marketing/payload/src/endpoints/seed/index.ts.hbs +0 -235
  293. package/templates/marketing/payload/src/endpoints/seed/post-1.ts.hbs +0 -252
  294. package/templates/marketing/payload/src/fields/defaultLexical.ts.hbs +0 -73
  295. package/templates/marketing/payload/src/fields/link.ts.hbs +0 -139
  296. package/templates/marketing/payload/src/fields/linkGroup.ts.hbs +0 -28
  297. package/templates/marketing/payload/src/globals/index.ts.hbs +0 -2
  298. package/templates/marketing/payload/src/heros/HighImpact/index.tsx.hbs +0 -53
  299. package/templates/marketing/payload/src/heros/LowImpact/index.tsx.hbs +0 -48
  300. package/templates/marketing/payload/src/heros/MediumImpact/index.tsx.hbs +0 -46
  301. package/templates/marketing/payload/src/heros/PostHero/index.tsx.hbs +0 -68
  302. package/templates/marketing/payload/src/heros/ProductShowcase/index.tsx.hbs +0 -88
  303. package/templates/marketing/payload/src/heros/config.ts.hbs +0 -112
  304. package/templates/marketing/payload/src/heros/index.ts.hbs +0 -7
  305. package/templates/marketing/payload/src/hooks/index.ts.hbs +0 -2
  306. package/templates/marketing/payload/src/hooks/populatePublishedAt.ts.hbs +0 -15
  307. package/templates/marketing/payload/src/providers/HeaderTheme/index.tsx.hbs +0 -34
  308. package/templates/marketing/payload/src/providers/Theme/index.tsx.hbs +0 -60
  309. package/templates/marketing/payload/src/providers/Theme/shared.ts.hbs +0 -17
  310. package/templates/marketing/payload/src/providers/index.tsx.hbs +0 -18
  311. package/templates/marketing/payload/src/utilities/deepMerge.ts.hbs +0 -35
  312. package/templates/marketing/payload/src/utilities/formatAuthors.ts.hbs +0 -24
  313. package/templates/marketing/payload/src/utilities/formatDateTime.ts.hbs +0 -13
  314. package/templates/marketing/payload/src/utilities/generateMeta.ts.hbs +0 -87
  315. package/templates/marketing/payload/src/utilities/generatePreviewPath.ts.hbs +0 -33
  316. package/templates/marketing/payload/src/utilities/getURL.ts.hbs +0 -26
  317. package/templates/marketing/payload/src/utilities/index.ts.hbs +0 -8
  318. package/templates/marketing/payload/src/utilities/mergeOpenGraph.ts.hbs +0 -26
  319. /package/templates/marketing/payload/src/access/{anyone.ts.hbs → anyone.ts} +0 -0
  320. /package/templates/marketing/payload/src/components/BeforeDashboard/SeedButton/{index.scss.hbs → index.scss} +0 -0
  321. /package/templates/marketing/payload/src/components/BeforeDashboard/{index.scss.hbs → index.scss} +0 -0
  322. /package/templates/marketing/payload/src/fields/{index.ts.hbs → index.ts} +0 -0
  323. /package/templates/marketing/payload/src/utilities/{canUseDOM.ts.hbs → canUseDOM.ts} +0 -0
@@ -0,0 +1,94 @@
1
+ "use client"
2
+ import { useHeaderTheme } from "@/providers/HeaderTheme"
3
+ import Link from "next/link"
4
+ import type React from "react"
5
+ import { useEffect, useMemo, useState } from "react"
6
+
7
+ import type { Header, Page, Post } from "@/payload-types"
8
+
9
+ import { Logo } from "@/components/Logo/Logo"
10
+ import { Button } from "@/components/ui/button"
11
+ import { MobileMenu } from "./MobileMenu"
12
+ import { HeaderNav } from "./Nav"
13
+
14
+ interface HeaderClientProps {
15
+ data: Header
16
+ }
17
+
18
+ // Helper to get href from link data
19
+ const getLinkHref = (link: {
20
+ type?: "custom" | "reference" | null
21
+ reference?: {
22
+ relationTo: "pages" | "posts"
23
+ value: Page | Post | string | number
24
+ } | null
25
+ url?: string | null
26
+ }): string => {
27
+ if (link.type === "reference" && link.reference) {
28
+ const { relationTo, value } = link.reference
29
+ if (typeof value === "object" && value.slug) {
30
+ return relationTo === "pages" ? `/${value.slug}` : `/${relationTo}/${value.slug}`
31
+ }
32
+ }
33
+ return link.url || "#"
34
+ }
35
+
36
+ export const HeaderClient: React.FC<HeaderClientProps> = ({ data }) => {
37
+ /* Storing the value in a useState to avoid hydration errors */
38
+ const [theme, setTheme] = useState<string | null>(null)
39
+ const { headerTheme, setHeaderTheme } = useHeaderTheme()
40
+
41
+ useEffect(() => {
42
+ setHeaderTheme(null)
43
+ }, [setHeaderTheme])
44
+
45
+ useEffect(() => {
46
+ if (headerTheme && headerTheme !== theme) setTheme(headerTheme)
47
+ }, [headerTheme, theme])
48
+
49
+ // Get the primary CTA (first right-positioned button item) for mobile view
50
+ const primaryCta = useMemo(() => {
51
+ const rightButtonItems = data?.navItems?.filter(
52
+ (item) =>
53
+ (item.position || "left") === "right" &&
54
+ item.type === "link" &&
55
+ (item.appearance || "button") === "button",
56
+ )
57
+ return rightButtonItems?.[0]
58
+ }, [data?.navItems])
59
+
60
+ return (
61
+ <header
62
+ className="sticky top-0 z-20 border-b border-border bg-background"
63
+ {...(theme ? { "data-theme": theme } : {})}
64
+ >
65
+ <div className="container mx-auto px-4 h-16 flex justify-between items-center">
66
+ {/* Left section: Logo + Left Nav Links */}
67
+ <div className="flex items-center gap-8">
68
+ <Link href="/" className="flex items-center gap-2">
69
+ <Logo loading="eager" priority="high" variant="auto" />
70
+ <span className="text-xl font-semibold hidden sm:inline">DirectoryHub</span>
71
+ </Link>
72
+ {/* Left nav - hidden on tablet and below, visible on desktop */}
73
+ <HeaderNav data={data} position="left" className="hidden lg:flex gap-6 items-center" />
74
+ </div>
75
+
76
+ {/* Right section: Right Nav Links (CTAs) */}
77
+ <div className="flex items-center gap-3">
78
+ {/* Full right nav - hidden on mobile and tablet, visible on desktop */}
79
+ <HeaderNav data={data} position="right" className="hidden lg:flex gap-4 items-center" />
80
+
81
+ {/* Primary CTA for tablet/mobile - visible on tablet and below, hidden on desktop */}
82
+ {primaryCta?.link && (
83
+ <Button asChild className="lg:hidden" size="sm">
84
+ <Link href={getLinkHref(primaryCta.link)}>{primaryCta.label}</Link>
85
+ </Button>
86
+ )}
87
+
88
+ {/* Mobile menu hamburger - visible on tablet and below */}
89
+ <MobileMenu data={data} />
90
+ </div>
91
+ </div>
92
+ </header>
93
+ )
94
+ }
@@ -0,0 +1,10 @@
1
+ import { getCachedGlobal } from "@/utilities/getGlobals"
2
+ import { HeaderClient } from "./Component.client"
3
+
4
+ import type { Header as HeaderType } from "@/payload-types"
5
+
6
+ export async function Header() {
7
+ const headerData: HeaderType = await getCachedGlobal("header", 1)()
8
+
9
+ return <HeaderClient data={headerData} />
10
+ }
@@ -0,0 +1,197 @@
1
+ "use client"
2
+
3
+ import { Media } from "@/components/Media"
4
+ import { cn } from "@/utilities/ui"
5
+ import {
6
+ BarChart3,
7
+ Building,
8
+ ChevronDown,
9
+ Database,
10
+ DollarSign,
11
+ Globe,
12
+ Layers,
13
+ Layout,
14
+ type LucideIcon,
15
+ Rocket,
16
+ Search,
17
+ Settings,
18
+ Shield,
19
+ Store,
20
+ Target,
21
+ Users,
22
+ Zap,
23
+ } from "lucide-react"
24
+ import Link from "next/link"
25
+ import type React from "react"
26
+ import { useState } from "react"
27
+
28
+ import type { Header, Media as MediaType, Page, Post } from "@/payload-types"
29
+
30
+ type NavItem = NonNullable<Header["navItems"]>[number]
31
+
32
+ const iconMap: Record<string, LucideIcon> = {
33
+ layout: Layout,
34
+ dollarSign: DollarSign,
35
+ search: Search,
36
+ settings: Settings,
37
+ zap: Zap,
38
+ layers: Layers,
39
+ users: Users,
40
+ building: Building,
41
+ globe: Globe,
42
+ store: Store,
43
+ rocket: Rocket,
44
+ target: Target,
45
+ barChart: BarChart3,
46
+ shield: Shield,
47
+ database: Database,
48
+ }
49
+
50
+ // Helper to get href from link data
51
+ const getLinkHref = (link: {
52
+ type?: "custom" | "reference" | null
53
+ reference?: {
54
+ relationTo: "pages" | "posts"
55
+ value: Page | Post | string | number
56
+ } | null
57
+ url?: string | null
58
+ }): string => {
59
+ if (link.type === "reference" && link.reference) {
60
+ const { relationTo, value } = link.reference
61
+ if (typeof value === "object" && value.slug) {
62
+ return relationTo === "pages" ? `/${value.slug}` : `/${relationTo}/${value.slug}`
63
+ }
64
+ }
65
+ return link.url || "#"
66
+ }
67
+
68
+ interface MegaMenuProps {
69
+ item: NavItem
70
+ }
71
+
72
+ export const MegaMenu: React.FC<MegaMenuProps> = ({ item }) => {
73
+ const [isOpen, setIsOpen] = useState(false)
74
+
75
+ const columns = item.megaMenuColumns || []
76
+ const featuredItem = item.featuredItem
77
+
78
+ return (
79
+ <div
80
+ className="relative"
81
+ onMouseEnter={() => setIsOpen(true)}
82
+ onMouseLeave={() => setIsOpen(false)}
83
+ >
84
+ {/* Trigger */}
85
+ <button
86
+ type="button"
87
+ className={cn(
88
+ "flex items-center gap-1 text-sm font-medium transition-colors hover:text-primary",
89
+ isOpen && "text-primary",
90
+ )}
91
+ onClick={() => setIsOpen(!isOpen)}
92
+ >
93
+ {item.label}
94
+ <ChevronDown
95
+ className={cn("h-4 w-4 transition-transform duration-200", isOpen && "rotate-180")}
96
+ />
97
+ </button>
98
+
99
+ {/* Dropdown */}
100
+ {isOpen && (
101
+ <div className="absolute left-1/2 -translate-x-1/2 top-full pt-4 z-50">
102
+ <div
103
+ className={cn(
104
+ "bg-background border border-border rounded-xl shadow-xl overflow-hidden",
105
+ "animate-in fade-in-0 zoom-in-95 duration-200",
106
+ featuredItem?.enabled ? "min-w-[700px]" : "min-w-[500px]",
107
+ )}
108
+ >
109
+ <div className="flex">
110
+ {/* Menu Columns */}
111
+ <div className={cn("flex-1 p-6", columns.length > 1 ? "grid grid-cols-2 gap-8" : "")}>
112
+ {columns.map((column) => (
113
+ <div key={column.columnLabel || "column"}>
114
+ {column.columnLabel && (
115
+ <div className="mb-4">
116
+ <h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
117
+ {column.columnLabel}
118
+ </h3>
119
+ {column.columnDescription && (
120
+ <p className="text-xs text-muted-foreground mt-1">
121
+ {column.columnDescription}
122
+ </p>
123
+ )}
124
+ </div>
125
+ )}
126
+ <ul className="space-y-1">
127
+ {column.items?.map((menuItem) => {
128
+ const Icon =
129
+ menuItem.icon && menuItem.icon !== "none" ? iconMap[menuItem.icon] : null
130
+ const href = menuItem.link ? getLinkHref(menuItem.link) : "#"
131
+
132
+ return (
133
+ <li key={menuItem.label}>
134
+ <Link
135
+ href={href}
136
+ className="flex items-start gap-3 p-2 rounded-lg hover:bg-muted transition-colors group"
137
+ onClick={() => setIsOpen(false)}
138
+ >
139
+ {Icon && (
140
+ <div className="flex-shrink-0 w-9 h-9 rounded-lg bg-primary/10 flex items-center justify-center group-hover:bg-primary/20 transition-colors">
141
+ <Icon className="w-4 h-4 text-primary" />
142
+ </div>
143
+ )}
144
+ <div className="flex-1 min-w-0">
145
+ <div className="text-sm font-medium group-hover:text-primary transition-colors">
146
+ {menuItem.label}
147
+ </div>
148
+ {menuItem.description && (
149
+ <div className="text-xs text-muted-foreground mt-0.5 line-clamp-2">
150
+ {menuItem.description}
151
+ </div>
152
+ )}
153
+ </div>
154
+ </Link>
155
+ </li>
156
+ )
157
+ })}
158
+ </ul>
159
+ </div>
160
+ ))}
161
+ </div>
162
+
163
+ {/* Featured Section */}
164
+ {featuredItem?.enabled && (
165
+ <div className="w-64 bg-muted/50 p-6 border-l border-border">
166
+ {featuredItem.image && typeof featuredItem.image === "object" && (
167
+ <div className="rounded-lg overflow-hidden mb-4 aspect-video">
168
+ <Media
169
+ resource={featuredItem.image as MediaType}
170
+ imgClassName="w-full h-full object-cover"
171
+ />
172
+ </div>
173
+ )}
174
+ {featuredItem.heading && (
175
+ <h4 className="font-semibold text-sm mb-2">{featuredItem.heading}</h4>
176
+ )}
177
+ {featuredItem.description && (
178
+ <p className="text-xs text-muted-foreground mb-4">{featuredItem.description}</p>
179
+ )}
180
+ {featuredItem.link && (
181
+ <Link
182
+ href={getLinkHref(featuredItem.link)}
183
+ className="text-xs font-medium text-primary hover:underline"
184
+ onClick={() => setIsOpen(false)}
185
+ >
186
+ {featuredItem.link.label || "Learn more"} →
187
+ </Link>
188
+ )}
189
+ </div>
190
+ )}
191
+ </div>
192
+ </div>
193
+ </div>
194
+ )}
195
+ </div>
196
+ )
197
+ }
@@ -0,0 +1,48 @@
1
+ "use client"
2
+
3
+ import { cn } from "@/utilities/ui"
4
+ import type React from "react"
5
+
6
+ interface HamburgerIconProps {
7
+ isOpen: boolean
8
+ onClick: () => void
9
+ className?: string
10
+ }
11
+
12
+ /**
13
+ * Animated 2-line hamburger icon that morphs into an X when open
14
+ */
15
+ export const HamburgerIcon: React.FC<HamburgerIconProps> = ({ isOpen, onClick, className }) => {
16
+ return (
17
+ <button
18
+ type="button"
19
+ onClick={onClick}
20
+ className={cn(
21
+ "relative w-8 h-8 flex items-center justify-center focus:outline-none",
22
+ "lg:hidden", // Only show on tablet and below
23
+ className,
24
+ )}
25
+ aria-label={isOpen ? "Close menu" : "Open menu"}
26
+ aria-expanded={isOpen}
27
+ >
28
+ <div className="relative w-6 h-4 flex flex-col justify-between">
29
+ {/* Top line */}
30
+ <span
31
+ className={cn(
32
+ "absolute left-0 w-full h-0.5 bg-foreground rounded-full",
33
+ "transition-all duration-300 ease-in-out origin-center",
34
+ isOpen ? "top-1/2 -translate-y-1/2 rotate-45" : "top-0 translate-y-0 rotate-0",
35
+ )}
36
+ />
37
+ {/* Bottom line */}
38
+ <span
39
+ className={cn(
40
+ "absolute left-0 w-full h-0.5 bg-foreground rounded-full",
41
+ "transition-all duration-300 ease-in-out origin-center",
42
+ isOpen ? "top-1/2 -translate-y-1/2 -rotate-45" : "bottom-0 translate-y-0 rotate-0",
43
+ )}
44
+ />
45
+ </div>
46
+ </button>
47
+ )
48
+ }
@@ -0,0 +1,299 @@
1
+ "use client"
2
+
3
+ import { Button } from "@/components/ui/button"
4
+ import { cn } from "@/utilities/ui"
5
+ import {
6
+ BarChart3,
7
+ Building,
8
+ ChevronRight,
9
+ Database,
10
+ DollarSign,
11
+ Globe,
12
+ Layers,
13
+ Layout,
14
+ type LucideIcon,
15
+ Rocket,
16
+ Search,
17
+ Settings,
18
+ Shield,
19
+ Store,
20
+ Target,
21
+ Users,
22
+ Zap,
23
+ } from "lucide-react"
24
+ import Link from "next/link"
25
+ import type React from "react"
26
+ import { useEffect, useState } from "react"
27
+
28
+ import type { Header, Page, Post } from "@/payload-types"
29
+ import { HamburgerIcon } from "./HamburgerIcon"
30
+
31
+ const iconMap: Record<string, LucideIcon> = {
32
+ layout: Layout,
33
+ dollarSign: DollarSign,
34
+ search: Search,
35
+ settings: Settings,
36
+ zap: Zap,
37
+ layers: Layers,
38
+ users: Users,
39
+ building: Building,
40
+ globe: Globe,
41
+ store: Store,
42
+ rocket: Rocket,
43
+ target: Target,
44
+ barChart: BarChart3,
45
+ shield: Shield,
46
+ database: Database,
47
+ }
48
+
49
+ // Helper to get href from link data
50
+ const getLinkHref = (link: {
51
+ type?: "custom" | "reference" | null
52
+ reference?: {
53
+ relationTo: "pages" | "posts"
54
+ value: Page | Post | string | number
55
+ } | null
56
+ url?: string | null
57
+ }): string => {
58
+ if (link.type === "reference" && link.reference) {
59
+ const { relationTo, value } = link.reference
60
+ if (typeof value === "object" && value.slug) {
61
+ return relationTo === "pages" ? `/${value.slug}` : `/${relationTo}/${value.slug}`
62
+ }
63
+ }
64
+ return link.url || "#"
65
+ }
66
+
67
+ interface MobileMenuProps {
68
+ data: Header
69
+ }
70
+
71
+ export const MobileMenu: React.FC<MobileMenuProps> = ({ data }) => {
72
+ const [isOpen, setIsOpen] = useState(false)
73
+ const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set())
74
+
75
+ const navItems = data?.navItems || []
76
+ const leftItems = navItems.filter((item) => (item.position || "left") === "left")
77
+ const rightItems = navItems.filter((item) => (item.position || "left") === "right")
78
+
79
+ // Separate CTA items (typically the primary action buttons)
80
+ const ctaItems = rightItems.filter((item) => item.type === "link")
81
+
82
+ // Prevent body scroll when menu is open
83
+ useEffect(() => {
84
+ if (isOpen) {
85
+ document.body.style.overflow = "hidden"
86
+ } else {
87
+ document.body.style.overflow = ""
88
+ }
89
+ return () => {
90
+ document.body.style.overflow = ""
91
+ }
92
+ }, [isOpen])
93
+
94
+ const toggleExpanded = (id: string) => {
95
+ setExpandedItems((prev) => {
96
+ const next = new Set(prev)
97
+ if (next.has(id)) {
98
+ next.delete(id)
99
+ } else {
100
+ next.add(id)
101
+ }
102
+ return next
103
+ })
104
+ }
105
+
106
+ const closeMenu = () => {
107
+ setIsOpen(false)
108
+ setExpandedItems(new Set())
109
+ }
110
+
111
+ return (
112
+ <>
113
+ {/* Hamburger button - visible on tablet and below */}
114
+ <HamburgerIcon isOpen={isOpen} onClick={() => setIsOpen(!isOpen)} />
115
+
116
+ {/* Mobile menu overlay */}
117
+ <div
118
+ className={cn(
119
+ "fixed inset-0 z-50 lg:hidden",
120
+ "transition-opacity duration-300",
121
+ isOpen ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none",
122
+ )}
123
+ >
124
+ {/* Backdrop */}
125
+ <div
126
+ className="absolute inset-0 bg-background/80 backdrop-blur-sm"
127
+ onClick={closeMenu}
128
+ onKeyDown={(e) => {
129
+ if (e.key === "Enter" || e.key === " ") {
130
+ e.preventDefault()
131
+ closeMenu()
132
+ }
133
+ }}
134
+ role="button"
135
+ tabIndex={0}
136
+ aria-label="Close menu"
137
+ />
138
+
139
+ {/* Menu panel */}
140
+ <div
141
+ className={cn(
142
+ "absolute top-0 right-0 h-full w-full max-w-md bg-background border-l border-border",
143
+ "flex flex-col",
144
+ "transition-transform duration-300 ease-out",
145
+ isOpen ? "translate-x-0" : "translate-x-full",
146
+ )}
147
+ >
148
+ {/* Header with close button */}
149
+ <div className="flex items-center justify-between p-4 border-b border-border">
150
+ <Link href="/" onClick={closeMenu} className="text-xl font-semibold">
151
+ DirectoryHub
152
+ </Link>
153
+ <HamburgerIcon isOpen={isOpen} onClick={closeMenu} className="lg:block" />
154
+ </div>
155
+
156
+ {/* Nav items */}
157
+ <div className="flex-1 overflow-y-auto p-4">
158
+ <nav className="space-y-1">
159
+ {leftItems.map((item, index) => {
160
+ const itemId = item.id || `item-${index}`
161
+ const isExpanded = expandedItems.has(itemId)
162
+ const hasMegaMenu = item.type === "megaMenu"
163
+
164
+ if (hasMegaMenu) {
165
+ return (
166
+ <div key={itemId}>
167
+ {/* Expandable item */}
168
+ <button
169
+ type="button"
170
+ onClick={() => toggleExpanded(itemId)}
171
+ className={cn(
172
+ "w-full flex items-center justify-between py-4 text-lg font-medium",
173
+ "border-b border-border/50 transition-colors hover:text-primary",
174
+ )}
175
+ >
176
+ <span>{item.label}</span>
177
+ <ChevronRight
178
+ className={cn(
179
+ "w-5 h-5 transition-transform duration-200",
180
+ isExpanded && "rotate-90",
181
+ )}
182
+ />
183
+ </button>
184
+
185
+ {/* Expanded content */}
186
+ <div
187
+ className={cn(
188
+ "overflow-hidden transition-all duration-300",
189
+ isExpanded ? "max-h-[1000px] opacity-100" : "max-h-0 opacity-0",
190
+ )}
191
+ >
192
+ <div className="py-2 pl-4 space-y-4">
193
+ {item.megaMenuColumns?.map((column, colIndex) => (
194
+ <div key={column.columnLabel || `col-${colIndex}`}>
195
+ {column.columnLabel && (
196
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-2">
197
+ {column.columnLabel}
198
+ </p>
199
+ )}
200
+ <ul className="space-y-1">
201
+ {column.items?.map((menuItem) => {
202
+ const Icon =
203
+ menuItem.icon && menuItem.icon !== "none"
204
+ ? iconMap[menuItem.icon]
205
+ : null
206
+ const href = menuItem.link ? getLinkHref(menuItem.link) : "#"
207
+
208
+ return (
209
+ <li key={menuItem.label}>
210
+ <Link
211
+ href={href}
212
+ onClick={closeMenu}
213
+ className="flex items-center gap-3 py-2 text-sm hover:text-primary transition-colors"
214
+ >
215
+ {Icon && <Icon className="w-4 h-4 text-muted-foreground" />}
216
+ <span>{menuItem.label}</span>
217
+ </Link>
218
+ </li>
219
+ )
220
+ })}
221
+ </ul>
222
+ </div>
223
+ ))}
224
+ </div>
225
+ </div>
226
+ </div>
227
+ )
228
+ }
229
+
230
+ // Simple link item
231
+ const link = item.link
232
+ if (!link) return null
233
+ const href = getLinkHref(link)
234
+
235
+ return (
236
+ <Link
237
+ key={itemId}
238
+ href={href}
239
+ onClick={closeMenu}
240
+ className={cn(
241
+ "block py-4 text-lg font-medium",
242
+ "border-b border-border/50 transition-colors hover:text-primary",
243
+ )}
244
+ >
245
+ {item.label}
246
+ </Link>
247
+ )
248
+ })}
249
+ </nav>
250
+ </div>
251
+
252
+ {/* Bottom CTA section */}
253
+ <div className="p-4 border-t border-border space-y-3">
254
+ {ctaItems.map((item, index) => {
255
+ const link = item.link
256
+ if (!link) return null
257
+ const href = getLinkHref(link)
258
+ const itemAppearance = item.appearance || "button"
259
+ const isButton = itemAppearance === "button"
260
+
261
+ if (isButton) {
262
+ // First button item is primary (filled), others are outline
263
+ const buttonItems = ctaItems.filter((i) => (i.appearance || "button") === "button")
264
+ const buttonIndex = buttonItems.findIndex((i) => i.id === item.id)
265
+ const isPrimary = buttonIndex === 0
266
+
267
+ return (
268
+ <Button
269
+ key={item.id || `cta-${index}`}
270
+ asChild
271
+ variant={isPrimary ? "default" : "outline"}
272
+ className="w-full"
273
+ size="lg"
274
+ >
275
+ <Link href={href} onClick={closeMenu}>
276
+ {item.label}
277
+ </Link>
278
+ </Button>
279
+ )
280
+ }
281
+
282
+ // Link appearance - render as text link
283
+ return (
284
+ <Link
285
+ key={item.id || `cta-${index}`}
286
+ href={href}
287
+ onClick={closeMenu}
288
+ className="block w-full text-center py-3 text-sm font-medium hover:text-primary transition-colors"
289
+ >
290
+ {item.label}
291
+ </Link>
292
+ )
293
+ })}
294
+ </div>
295
+ </div>
296
+ </div>
297
+ </>
298
+ )
299
+ }