xertica-ui 2.7.0 → 2.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (480) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/README.md +20 -12
  3. package/bin/cli.ts +327 -87
  4. package/bin/generate-tokens.ts +25 -9
  5. package/bin/language-config.ts +58 -18
  6. package/components/assistant/xertica-assistant/xertica-assistant.tsx +1 -1
  7. package/components/blocks/auth/AuthPageShell.tsx +63 -18
  8. package/components/blocks/auth/SocialLoginButtons.tsx +3 -3
  9. package/components/blocks/index.ts +1 -0
  10. package/components/blocks/marketing/CTASection.tsx +73 -0
  11. package/components/blocks/marketing/ComplianceBadgeRow.tsx +49 -0
  12. package/components/blocks/marketing/EvidenceTimeline.tsx +91 -0
  13. package/components/blocks/marketing/FeatureRow.tsx +78 -0
  14. package/components/blocks/marketing/Hero.tsx +125 -0
  15. package/components/blocks/marketing/HowItWorksSteps.tsx +90 -0
  16. package/components/blocks/marketing/LogoCloud.tsx +47 -0
  17. package/components/blocks/marketing/MarketingFooter.tsx +109 -0
  18. package/components/blocks/marketing/MarketingNavbar.tsx +192 -0
  19. package/components/blocks/marketing/PillBadge.tsx +96 -0
  20. package/components/blocks/marketing/SectionHeading.tsx +82 -0
  21. package/components/blocks/marketing/ServiceCardGrid.tsx +238 -0
  22. package/components/blocks/marketing/StatBand.tsx +99 -0
  23. package/components/blocks/marketing/TopAccentCards.tsx +91 -0
  24. package/components/blocks/marketing/index.ts +41 -0
  25. package/components/brand/index.ts +1 -0
  26. package/components/brand/isotype/Isotype.tsx +64 -0
  27. package/components/brand/isotype/IsotypeDiagonal.tsx +51 -0
  28. package/components/brand/isotype/IsotypeFrames.tsx +82 -0
  29. package/components/brand/isotype/IsotypeMini.tsx +65 -0
  30. package/components/brand/isotype/IsotypeTwist.tsx +68 -0
  31. package/components/brand/isotype/frame-variants.ts +20 -0
  32. package/components/brand/isotype/index.ts +9 -0
  33. package/components/brand/isotype/isotype-diagonal.mdx +52 -0
  34. package/components/brand/isotype/isotype-diagonal.stories.tsx +44 -0
  35. package/components/brand/isotype/isotype-diagonal.test.tsx +180 -0
  36. package/components/brand/isotype/isotype-frames.mdx +50 -0
  37. package/components/brand/isotype/isotype-frames.stories.tsx +63 -0
  38. package/components/brand/isotype/isotype-frames.test.tsx +92 -0
  39. package/components/brand/isotype/isotype-mini.mdx +61 -0
  40. package/components/brand/isotype/isotype-mini.stories.tsx +75 -0
  41. package/components/brand/isotype/isotype-mini.test.tsx +45 -0
  42. package/components/brand/isotype/isotype-twist.test.tsx +71 -0
  43. package/components/brand/isotype/isotype.mdx +61 -0
  44. package/components/brand/isotype/isotype.stories.tsx +74 -0
  45. package/components/brand/isotype/isotype.test.tsx +41 -0
  46. package/components/brand/isotype/mini-patterns.ts +50 -0
  47. package/components/brand/isotype/patterns.ts +83 -0
  48. package/components/brand/isotype/twist-variants.ts +20 -0
  49. package/components/pages/forgot-password-page/ForgotPasswordPage.tsx +3 -6
  50. package/components/pages/index.ts +1 -0
  51. package/components/pages/landing-page/LandingPage.tsx +360 -0
  52. package/components/pages/landing-page/index.ts +1 -0
  53. package/components/pages/login-page/LoginPage.tsx +3 -6
  54. package/components/pages/reset-password-page/ResetPasswordPage.tsx +1 -4
  55. package/components/pages/verify-email-page/VerifyEmailPage.tsx +2 -5
  56. package/components/ui/button/button.test.tsx +3 -3
  57. package/components/ui/button/button.tsx +5 -4
  58. package/components/ui/card/card.test.tsx +12 -0
  59. package/components/ui/card/card.tsx +16 -2
  60. package/components/ui/input/input.tsx +1 -1
  61. package/components/ui/input-otp/input-otp.tsx +1 -1
  62. package/components/ui/search/search.tsx +1 -1
  63. package/components/ui/select/select.tsx +2 -2
  64. package/components/ui/switch/switch.tsx +1 -1
  65. package/components/ui/textarea/textarea.tsx +1 -1
  66. package/contexts/BrandColorsContext.tsx +59 -7
  67. package/contexts/theme-data.ts +127 -3
  68. package/dist/AssistantChart-BFBJXVcm.js +3383 -0
  69. package/dist/AssistantChart-BTnE94FR.cjs +3551 -0
  70. package/dist/AssistantChart-BU48lxL2.js +3383 -0
  71. package/dist/AssistantChart-BvccsQMx.cjs +3551 -0
  72. package/dist/AssistantChart-CkskcBVD.js +3383 -0
  73. package/dist/AssistantChart-CoN6ga6Z.js +3383 -0
  74. package/dist/AssistantChart-CrPkO9ip.js +3383 -0
  75. package/dist/AssistantChart-DIRYJ7WY.js +3383 -0
  76. package/dist/AssistantChart-DKz2O1R8.cjs +3551 -0
  77. package/dist/AssistantChart-DOnY1ZlD.cjs +3551 -0
  78. package/dist/AssistantChart-DYL6UEvo.cjs +3551 -0
  79. package/dist/AssistantChart-DjM3qnp5.cjs +3551 -0
  80. package/dist/AssistantChart-hxPyE1S9.cjs +3551 -0
  81. package/dist/AssistantChart-keo-ogKi.js +3383 -0
  82. package/dist/AudioPlayer-AoU5MTiM.cjs +1282 -0
  83. package/dist/AudioPlayer-Bx1vrblm.js +1278 -0
  84. package/dist/AudioPlayer-CpihsbaD.js +1278 -0
  85. package/dist/AudioPlayer-CvGajzMC.cjs +1282 -0
  86. package/dist/AudioPlayer-CvHpFqDG.cjs +1282 -0
  87. package/dist/AudioPlayer-D0-I6J3J.cjs +1282 -0
  88. package/dist/AudioPlayer-D4S7GQou.js +1278 -0
  89. package/dist/AudioPlayer-DIWX_Yg7.cjs +1282 -0
  90. package/dist/AudioPlayer-DrWJnS7c.js +1278 -0
  91. package/dist/AudioPlayer-_P-Z7pAK.js +1278 -0
  92. package/dist/BrandColorsContext-B25Bpr3b.cjs +819 -0
  93. package/dist/BrandColorsContext-BCieATdW.js +812 -0
  94. package/dist/BrandColorsContext-BNKLUVcU.js +829 -0
  95. package/dist/BrandColorsContext-DNZGHItQ.cjs +836 -0
  96. package/dist/BrandColorsContext-DP0DXAXS.js +824 -0
  97. package/dist/BrandColorsContext-DjpC9wR_.cjs +798 -0
  98. package/dist/BrandColorsContext-MpXFhte7.cjs +831 -0
  99. package/dist/BrandColorsContext-Ug_TZ8yn.cjs +846 -0
  100. package/dist/BrandColorsContext-V3tOc-Zw.js +791 -0
  101. package/dist/BrandColorsContext-z0O2LlZz.js +839 -0
  102. package/dist/CodeBlock-BkaZf-R8.cjs +223 -0
  103. package/dist/CodeBlock-CK4rO6lM.js +221 -0
  104. package/dist/CodeBlock-CKXamfVd.cjs +223 -0
  105. package/dist/CodeBlock-CKu8LgbP.cjs +223 -0
  106. package/dist/CodeBlock-CVmE7isS.cjs +223 -0
  107. package/dist/CodeBlock-D7i5-cMv.js +221 -0
  108. package/dist/CodeBlock-Dg56j2ut.cjs +223 -0
  109. package/dist/CodeBlock-DiLS5LLI.js +221 -0
  110. package/dist/CodeBlock-Dt6nUQoo.js +221 -0
  111. package/dist/CodeBlock-zdylBGdZ.js +221 -0
  112. package/dist/CustomTooltipContent-BAR5qCQg.js +33 -0
  113. package/dist/CustomTooltipContent-Bxynuq7T.js +33 -0
  114. package/dist/CustomTooltipContent-BzjOSA0P.cjs +54 -0
  115. package/dist/CustomTooltipContent-C-ZeCNsf.js +33 -0
  116. package/dist/CustomTooltipContent-CBLHBxX8.cjs +54 -0
  117. package/dist/CustomTooltipContent-CON_QrXm.cjs +54 -0
  118. package/dist/CustomTooltipContent-CjWm3jjV.js +33 -0
  119. package/dist/CustomTooltipContent-DTV9MN9E.cjs +54 -0
  120. package/dist/CustomTooltipContent-UR_n2QfW.js +33 -0
  121. package/dist/CustomTooltipContent-v1SXjoFn.cjs +54 -0
  122. package/dist/EvidenceTimeline-DrRk4yqb.cjs +560 -0
  123. package/dist/EvidenceTimeline-l4MaV4C7.js +546 -0
  124. package/dist/FeatureCard-4n_8a63v.cjs +497 -0
  125. package/dist/FeatureCard-BLiAWT3w.js +485 -0
  126. package/dist/FeatureCard-BXRW97Ef.cjs +497 -0
  127. package/dist/FeatureCard-CDgLlWE2.js +485 -0
  128. package/dist/FeatureCard-CIbBHqeY.cjs +497 -0
  129. package/dist/FeatureCard-CgQ8lq-I.cjs +497 -0
  130. package/dist/FeatureCard-Cp8cVC6T.cjs +497 -0
  131. package/dist/FeatureCard-D0MwrTRP.js +485 -0
  132. package/dist/FeatureCard-DtoKPSfW.cjs +497 -0
  133. package/dist/FeatureCard-P4iEpBmB.js +485 -0
  134. package/dist/FeatureCard-e3f8bnF0.js +485 -0
  135. package/dist/FeatureCard-uE5i0in_.js +485 -0
  136. package/dist/ImageWithFallback-BOh1FM3I.js +98 -0
  137. package/dist/ImageWithFallback-BQO7952C.js +98 -0
  138. package/dist/ImageWithFallback-BkMXHCvV.cjs +122 -0
  139. package/dist/ImageWithFallback-C1ww9Hg3.cjs +122 -0
  140. package/dist/ImageWithFallback-C72nwszA.cjs +122 -0
  141. package/dist/ImageWithFallback-CBrkAEo3.cjs +122 -0
  142. package/dist/ImageWithFallback-CCUMDuEC.cjs +122 -0
  143. package/dist/ImageWithFallback-CGk5zPH-.js +98 -0
  144. package/dist/ImageWithFallback-CfnoFFSP.js +98 -0
  145. package/dist/ImageWithFallback-DQD5TTlY.js +98 -0
  146. package/dist/Isotype--fRZWwS6.js +85 -0
  147. package/dist/Isotype-0dpLqetB.js +85 -0
  148. package/dist/Isotype-B8XLEXSB.cjs +92 -0
  149. package/dist/Isotype-ChKwN7e-.cjs +91 -0
  150. package/dist/IsotypeDiagonal-CuPYPP4f.js +84 -0
  151. package/dist/IsotypeDiagonal-eNcOXRAc.cjs +91 -0
  152. package/dist/IsotypeDiagonal-oiwpXZhE.js +104 -0
  153. package/dist/IsotypeDiagonal-xMFoFXkb.cjs +109 -0
  154. package/dist/IsotypeFrames-BcWtyAWp.cjs +83 -0
  155. package/dist/IsotypeFrames-BnvSJKiH.cjs +73 -0
  156. package/dist/IsotypeFrames-iDRTRuIu.js +79 -0
  157. package/dist/IsotypeFrames-qoXOvOJt.js +69 -0
  158. package/dist/IsotypeMini-CQtWVo3h.js +126 -0
  159. package/dist/IsotypeMini-Cu_sW5yN.cjs +134 -0
  160. package/dist/IsotypeTwist-BTdNL4iV.js +106 -0
  161. package/dist/IsotypeTwist-DvsUgZs_.cjs +115 -0
  162. package/dist/LanguageContext-B1aOXO-K.js +1987 -0
  163. package/dist/LanguageContext-BP0k7AzI.js +1993 -0
  164. package/dist/LanguageContext-CChcIHIG.cjs +1998 -0
  165. package/dist/LanguageContext-ubC7TSs_.cjs +1992 -0
  166. package/dist/LanguageSelector-1XhM7R1i.cjs +48 -0
  167. package/dist/LanguageSelector-B3ZVNc55.js +46 -0
  168. package/dist/LanguageSelector-BLFPXGo8.cjs +48 -0
  169. package/dist/LanguageSelector-CYRzWkRZ.cjs +48 -0
  170. package/dist/LanguageSelector-Cj6zl0CM.js +46 -0
  171. package/dist/LanguageSelector-CyHjZgC4.cjs +48 -0
  172. package/dist/LanguageSelector-DE8lIySO.js +46 -0
  173. package/dist/LanguageSelector-DK1zD4VH.cjs +48 -0
  174. package/dist/LanguageSelector-DUr1hjBW.js +46 -0
  175. package/dist/LanguageSelector-DjbWIKWC.js +46 -0
  176. package/dist/LanguageSelector-DseCAa0p.cjs +48 -0
  177. package/dist/LanguageSelector-Du09anfM.js +46 -0
  178. package/dist/LanguageSelector-PZHlFfEs.cjs +48 -0
  179. package/dist/LanguageSelector-SB-NJSmx.js +46 -0
  180. package/dist/LogoCloud-C_uMKVNg.cjs +513 -0
  181. package/dist/LogoCloud-DJsMPNPh.js +500 -0
  182. package/dist/MarketingFooter-B_ycEdTJ.cjs +727 -0
  183. package/dist/MarketingFooter-Bhx-2Vlr.cjs +727 -0
  184. package/dist/MarketingFooter-Br1MGK9e.js +699 -0
  185. package/dist/MarketingFooter-BwE1vmeX.cjs +700 -0
  186. package/dist/MarketingFooter-CsZ1_xL9.js +709 -0
  187. package/dist/MarketingFooter-DCwf78Q4.cjs +716 -0
  188. package/dist/MarketingFooter-KH2r-OOL.js +709 -0
  189. package/dist/MarketingFooter-nB7G7gQ5.js +682 -0
  190. package/dist/PasswordStrengthMeter-B3S6i_k4.cjs +179 -0
  191. package/dist/PasswordStrengthMeter-B8ky1nJI.js +173 -0
  192. package/dist/PasswordStrengthMeter-C5VEopH-.cjs +179 -0
  193. package/dist/PasswordStrengthMeter-CIm7_jNT.js +173 -0
  194. package/dist/PasswordStrengthMeter-DKSAbQzu.js +173 -0
  195. package/dist/PasswordStrengthMeter-DxLu54p-.cjs +179 -0
  196. package/dist/PasswordStrengthMeter-k-e9Pole.cjs +179 -0
  197. package/dist/PasswordStrengthMeter-pAi2viq5.js +173 -0
  198. package/dist/SectionHeading-DEeOKcAd.cjs +857 -0
  199. package/dist/SectionHeading-DMNObcwm.js +838 -0
  200. package/dist/ThemeToggle--CGJjQJv.cjs +219 -0
  201. package/dist/ThemeToggle-4pQbVkpK.js +215 -0
  202. package/dist/ThemeToggle-B6rIVLvC.cjs +219 -0
  203. package/dist/ThemeToggle-BUOTps5l.cjs +219 -0
  204. package/dist/ThemeToggle-Bn_7Pmfe.js +215 -0
  205. package/dist/ThemeToggle-CO5mPl6e.js +215 -0
  206. package/dist/ThemeToggle-CoL8Ady7.js +215 -0
  207. package/dist/ThemeToggle-D2Wzm5bn.cjs +219 -0
  208. package/dist/ThemeToggle-DbZQ0JSV.cjs +219 -0
  209. package/dist/ThemeToggle-vLXEq2TS.js +215 -0
  210. package/dist/VerifyEmailPage-90lK6pP4.js +3258 -0
  211. package/dist/VerifyEmailPage-BJX1Rter.cjs +3320 -0
  212. package/dist/VerifyEmailPage-BSWvOgry.js +3310 -0
  213. package/dist/VerifyEmailPage-BTjI2c9n.js +2954 -0
  214. package/dist/VerifyEmailPage-CDqIkhx-.js +3224 -0
  215. package/dist/VerifyEmailPage-CJGfDSOx.js +2954 -0
  216. package/dist/VerifyEmailPage-Crxje3ZB.js +3323 -0
  217. package/dist/VerifyEmailPage-D2ShbuEN.cjs +3333 -0
  218. package/dist/VerifyEmailPage-DEBZXQ7c.cjs +3310 -0
  219. package/dist/VerifyEmailPage-DGaX-jZv.cjs +3268 -0
  220. package/dist/VerifyEmailPage-DOlZUNc0.cjs +2963 -0
  221. package/dist/VerifyEmailPage-DQPRl_RJ.js +2954 -0
  222. package/dist/VerifyEmailPage-DrdqMbLC.cjs +2963 -0
  223. package/dist/VerifyEmailPage-ZtOPkgOA.cjs +3234 -0
  224. package/dist/VerifyEmailPage-hyDfeCRa.cjs +2963 -0
  225. package/dist/VerifyEmailPage-kKSXl8vu.cjs +2963 -0
  226. package/dist/VerifyEmailPage-s927GSiR.js +3300 -0
  227. package/dist/VerifyEmailPage-w4N-bDhU.js +2954 -0
  228. package/dist/XerticaOrbe-B9tegV1n.js +1925 -0
  229. package/dist/XerticaOrbe-BHex09xs.js +1925 -0
  230. package/dist/XerticaOrbe-BKW3LJEz.js +1925 -0
  231. package/dist/XerticaOrbe-BQ_NjwPS.cjs +1927 -0
  232. package/dist/XerticaOrbe-BdUX171Q.cjs +1927 -0
  233. package/dist/XerticaOrbe-BdlKXRHU.cjs +1927 -0
  234. package/dist/XerticaOrbe-Br2i99U_.cjs +1927 -0
  235. package/dist/XerticaOrbe-CByPAFE5.js +1925 -0
  236. package/dist/XerticaOrbe-Ccu9eFMu.js +1925 -0
  237. package/dist/XerticaOrbe-kjFmuyx-.cjs +1927 -0
  238. package/dist/XerticaProvider-BVid1oqn.cjs +46 -0
  239. package/dist/XerticaProvider-Bi5lKC9N.js +44 -0
  240. package/dist/XerticaProvider-BrPMVhiv.js +44 -0
  241. package/dist/XerticaProvider-Bz_YfNY4.js +44 -0
  242. package/dist/XerticaProvider-CnX5kt5W.cjs +46 -0
  243. package/dist/XerticaProvider-CtvYfRbZ.cjs +46 -0
  244. package/dist/XerticaProvider-DEKNJTlN.js +44 -0
  245. package/dist/XerticaProvider-DMiyExQS.js +44 -0
  246. package/dist/XerticaProvider-DP2lzKip.cjs +46 -0
  247. package/dist/XerticaProvider-De79hhgp.js +44 -0
  248. package/dist/XerticaProvider-Dkk1Vbsy.js +44 -0
  249. package/dist/XerticaProvider-EdzH9Nrw.cjs +46 -0
  250. package/dist/XerticaProvider-X_wavDYA.cjs +46 -0
  251. package/dist/XerticaProvider-b3n_oL8w.cjs +46 -0
  252. package/dist/alert-dialog--qdlmB5i.cjs +872 -0
  253. package/dist/alert-dialog-9XYAn5z5.js +819 -0
  254. package/dist/alert-dialog-B281hud0.cjs +872 -0
  255. package/dist/alert-dialog-BVWbrcrw.cjs +872 -0
  256. package/dist/alert-dialog-B_Ko1xpu.js +819 -0
  257. package/dist/alert-dialog-C48TOdYU.cjs +872 -0
  258. package/dist/alert-dialog-CEPpnpXt.js +819 -0
  259. package/dist/alert-dialog-CIxE8T-J.cjs +872 -0
  260. package/dist/alert-dialog-DW-_iPuf.js +819 -0
  261. package/dist/alert-dialog-NjflitDa.js +819 -0
  262. package/dist/assistant.cjs.js +2 -2
  263. package/dist/assistant.es.js +2 -2
  264. package/dist/avatar-BJwIMbZ_.js +54 -0
  265. package/dist/avatar-C4Zh5fAJ.cjs +77 -0
  266. package/dist/avatar-CTEUKZUT.js +54 -0
  267. package/dist/avatar-CtEKgg7s.cjs +77 -0
  268. package/dist/avatar-D03MNQxs.js +54 -0
  269. package/dist/avatar-D1bZhlhL.cjs +77 -0
  270. package/dist/avatar-DKIxHeKG.cjs +77 -0
  271. package/dist/avatar-Df7KgSvs.js +54 -0
  272. package/dist/avatar-Gy0_Xu9i.cjs +77 -0
  273. package/dist/avatar-v16eZC8p.js +54 -0
  274. package/dist/blocks.cjs.js +33 -18
  275. package/dist/blocks.es.js +2 -2
  276. package/dist/brand.cjs.js +110 -4
  277. package/dist/brand.es.js +98 -4
  278. package/dist/breadcrumb-B1mUiaWB.cjs +98 -0
  279. package/dist/breadcrumb-BGO5PZPG.js +90 -0
  280. package/dist/breadcrumb-BIRgmem-.js +90 -0
  281. package/dist/breadcrumb-BSng-oUf.cjs +98 -0
  282. package/dist/breadcrumb-BvGAY4ne.cjs +98 -0
  283. package/dist/breadcrumb-CES7furU.js +90 -0
  284. package/dist/breadcrumb-CP275kbF.cjs +98 -0
  285. package/dist/breadcrumb-CU-punra.js +90 -0
  286. package/dist/breadcrumb-D7hr1EvJ.js +90 -0
  287. package/dist/breadcrumb-DjV9wfX1.cjs +98 -0
  288. package/dist/button-B05czY_8.js +62 -0
  289. package/dist/button-B3SE1liJ.js +62 -0
  290. package/dist/button-BMDlWZR8.cjs +85 -0
  291. package/dist/button-BYtQygX5.cjs +85 -0
  292. package/dist/button-BnAW-a_w.js +62 -0
  293. package/dist/button-CUPDQews.js +62 -0
  294. package/dist/button-DFa-rtPy.js +62 -0
  295. package/dist/button-DV1G6XrI.cjs +85 -0
  296. package/dist/button-DVhloDtr.cjs +85 -0
  297. package/dist/button-Kd9Fj53S.cjs +85 -0
  298. package/dist/cli.js +367 -65
  299. package/dist/components/blocks/auth/AuthPageShell.d.ts +21 -5
  300. package/dist/components/blocks/index.d.ts +1 -0
  301. package/dist/components/blocks/marketing/CTASection.d.ts +28 -0
  302. package/dist/components/blocks/marketing/ComplianceBadgeRow.d.ts +23 -0
  303. package/dist/components/blocks/marketing/EvidenceTimeline.d.ts +26 -0
  304. package/dist/components/blocks/marketing/FeatureRow.d.ts +25 -0
  305. package/dist/components/blocks/marketing/Hero.d.ts +35 -0
  306. package/dist/components/blocks/marketing/HowItWorksSteps.d.ts +29 -0
  307. package/dist/components/blocks/marketing/LogoCloud.d.ts +22 -0
  308. package/dist/components/blocks/marketing/MarketingFooter.d.ts +42 -0
  309. package/dist/components/blocks/marketing/MarketingNavbar.d.ts +47 -0
  310. package/dist/components/blocks/marketing/PillBadge.d.ts +21 -0
  311. package/dist/components/blocks/marketing/SectionHeading.d.ts +23 -0
  312. package/dist/components/blocks/marketing/ServiceCardGrid.d.ts +65 -0
  313. package/dist/components/blocks/marketing/StatBand.d.ts +25 -0
  314. package/dist/components/blocks/marketing/TopAccentCards.d.ts +29 -0
  315. package/dist/components/blocks/marketing/index.d.ts +28 -0
  316. package/dist/components/brand/index.d.ts +1 -0
  317. package/dist/components/brand/isotype/Isotype.d.ts +27 -0
  318. package/dist/components/brand/isotype/IsotypeDiagonal.d.ts +19 -0
  319. package/dist/components/brand/isotype/IsotypeFrames.d.ts +21 -0
  320. package/dist/components/brand/isotype/IsotypeMini.d.ts +26 -0
  321. package/dist/components/brand/isotype/IsotypeTwist.d.ts +22 -0
  322. package/dist/components/brand/isotype/frame-variants.d.ts +11 -0
  323. package/dist/components/brand/isotype/index.d.ts +9 -0
  324. package/dist/components/brand/isotype/mini-patterns.d.ts +25 -0
  325. package/dist/components/brand/isotype/patterns.d.ts +42 -0
  326. package/dist/components/brand/isotype/twist-variants.d.ts +11 -0
  327. package/dist/components/pages/forgot-password-page/ForgotPasswordPage.d.ts +2 -2
  328. package/dist/components/pages/index.d.ts +1 -0
  329. package/dist/components/pages/landing-page/LandingPage.d.ts +18 -0
  330. package/dist/components/pages/landing-page/index.d.ts +1 -0
  331. package/dist/components/pages/login-page/LoginPage.d.ts +2 -2
  332. package/dist/components/pages/verify-email-page/VerifyEmailPage.d.ts +1 -1
  333. package/dist/components/ui/card/card.d.ts +13 -1
  334. package/dist/contexts/theme-data.d.ts +21 -1
  335. package/dist/dropdown-menu-B9wTZ0uX.cjs +225 -0
  336. package/dist/dropdown-menu-BeBtZOrs.cjs +225 -0
  337. package/dist/dropdown-menu-ChQa9zW3.cjs +225 -0
  338. package/dist/dropdown-menu-D7mRDGis.js +190 -0
  339. package/dist/dropdown-menu-D8ZmqHB7.js +190 -0
  340. package/dist/dropdown-menu-DRvnsQAt.cjs +225 -0
  341. package/dist/dropdown-menu-DUk81i5Y.js +190 -0
  342. package/dist/dropdown-menu-NlUHhVmK.js +190 -0
  343. package/dist/dropdown-menu-_AWBeOts.cjs +225 -0
  344. package/dist/dropdown-menu-qGzLO_HO.js +190 -0
  345. package/dist/hooks.cjs.js +2 -2
  346. package/dist/hooks.es.js +2 -2
  347. package/dist/index.cjs.js +57 -41
  348. package/dist/index.es.js +25 -25
  349. package/dist/input-B53E6K8G.js +65 -0
  350. package/dist/input-B7Q7vcoG.cjs +91 -0
  351. package/dist/input-BysqLMK1.js +65 -0
  352. package/dist/input-CStdFsaH.cjs +91 -0
  353. package/dist/input-CXYth6nW.cjs +91 -0
  354. package/dist/input-CX_fWE2D.cjs +91 -0
  355. package/dist/input-CitUVnEn.js +65 -0
  356. package/dist/input-Csp_Metb.cjs +91 -0
  357. package/dist/input-DVRwGVLx.js +65 -0
  358. package/dist/input-Dqyj7Hdw.cjs +91 -0
  359. package/dist/input-dOgrFQ-3.js +65 -0
  360. package/dist/input-wkBYTp-B.js +65 -0
  361. package/dist/layout.cjs.js +1 -1
  362. package/dist/layout.es.js +1 -1
  363. package/dist/media.cjs.js +1 -1
  364. package/dist/media.es.js +1 -1
  365. package/dist/pages.cjs.js +2 -1
  366. package/dist/pages.es.js +1 -1
  367. package/dist/rich-text-editor-7K7UjLJN.cjs +2968 -0
  368. package/dist/rich-text-editor-B3jLP2bm.cjs +2968 -0
  369. package/dist/rich-text-editor-BHiRUzWZ.js +2894 -0
  370. package/dist/rich-text-editor-BWMRUMJ2.js +2894 -0
  371. package/dist/rich-text-editor-BntMVQsB.js +2894 -0
  372. package/dist/rich-text-editor-BoE6Ks5x.cjs +2968 -0
  373. package/dist/rich-text-editor-BzuEwR_X.js +2894 -0
  374. package/dist/rich-text-editor-CcopGbQ-.js +2894 -0
  375. package/dist/rich-text-editor-CmxSRJIi.cjs +2968 -0
  376. package/dist/rich-text-editor-Diz_onyB.js +2894 -0
  377. package/dist/rich-text-editor-DyYAu28v.cjs +2968 -0
  378. package/dist/rich-text-editor-JS_eMQCC.cjs +2968 -0
  379. package/dist/rich-text-editor-RWvK4hd3.cjs +2968 -0
  380. package/dist/rich-text-editor-gauEkzPM.js +2894 -0
  381. package/dist/select-B6PygS38.cjs +161 -0
  382. package/dist/select-BD763J5Y.cjs +161 -0
  383. package/dist/select-BNfFJwYp.js +130 -0
  384. package/dist/select-CN8IDjGB.js +130 -0
  385. package/dist/select-CwRzQHA7.cjs +161 -0
  386. package/dist/select-CwgD3nMD.js +130 -0
  387. package/dist/select-DEHUm_AC.cjs +161 -0
  388. package/dist/select-DJDgpVm3.cjs +161 -0
  389. package/dist/select-DSLWQLmo.cjs +161 -0
  390. package/dist/select-QJDKZITN.js +130 -0
  391. package/dist/select-YFx0wCYT.js +130 -0
  392. package/dist/select-q7aDfuPn.js +130 -0
  393. package/dist/sidebar-BF7JEL7U.js +1151 -0
  394. package/dist/sidebar-Bjr2doX5.cjs +1154 -0
  395. package/dist/sidebar-Bkk1YAsD.cjs +1154 -0
  396. package/dist/sidebar-CMrNCmhb.cjs +1154 -0
  397. package/dist/sidebar-CO9x8AVn.cjs +1154 -0
  398. package/dist/sidebar-Cn_KB4c6.js +1151 -0
  399. package/dist/sidebar-CuzYeOSz.cjs +1154 -0
  400. package/dist/sidebar-CwlW3LXE.js +1151 -0
  401. package/dist/sidebar-DNkf-Ug6.js +1151 -0
  402. package/dist/sidebar-DaS3fplw.cjs +1154 -0
  403. package/dist/sidebar-Db_C30ph.cjs +1154 -0
  404. package/dist/sidebar-FDCY42oP.js +1151 -0
  405. package/dist/sidebar-miPHsRz4.js +1151 -0
  406. package/dist/sidebar-pZF8mLLu.js +1151 -0
  407. package/dist/skeleton-BX2XTjMO.cjs +87 -0
  408. package/dist/skeleton-BoLK0iV7.js +78 -0
  409. package/dist/skeleton-BtBwJ39W.js +79 -0
  410. package/dist/skeleton-Bysq8yeB.js +79 -0
  411. package/dist/skeleton-C7nspYnC.cjs +87 -0
  412. package/dist/skeleton-CJyg0eJ1.cjs +88 -0
  413. package/dist/skeleton-D8WaauK0.cjs +88 -0
  414. package/dist/skeleton-DBYtjaZW.cjs +88 -0
  415. package/dist/skeleton-DL4V5Vub.cjs +87 -0
  416. package/dist/skeleton-DSMhdqp1.js +78 -0
  417. package/dist/skeleton-DY_lSFWf.js +79 -0
  418. package/dist/skeleton-Df65Ox10.js +79 -0
  419. package/dist/skeleton-DhJswvTW.cjs +88 -0
  420. package/dist/skeleton-DicUfozA.js +78 -0
  421. package/dist/slider-77T_Eqw4.js +56 -0
  422. package/dist/slider-B6puMLXS.cjs +78 -0
  423. package/dist/slider-B785N7lZ.js +56 -0
  424. package/dist/slider-BKV_vvsh.cjs +78 -0
  425. package/dist/slider-B_lUjFNa.cjs +78 -0
  426. package/dist/slider-C6yssKyZ.cjs +78 -0
  427. package/dist/slider-CKZO9gVh.cjs +78 -0
  428. package/dist/slider-Cn-ImSze.js +56 -0
  429. package/dist/slider-CtBpIaU4.js +56 -0
  430. package/dist/slider-KgWmSJbx.js +56 -0
  431. package/dist/tooltip-BPttuPxU.js +48 -0
  432. package/dist/tooltip-BiJVGob3.cjs +72 -0
  433. package/dist/tooltip-CIKRzQqE.cjs +72 -0
  434. package/dist/tooltip-CoDByjE_.cjs +72 -0
  435. package/dist/tooltip-D2OPn-1v.cjs +72 -0
  436. package/dist/tooltip-DlCHQuh1.js +48 -0
  437. package/dist/tooltip-_MAwsiOL.js +48 -0
  438. package/dist/tooltip-fQ2Va0G8.cjs +72 -0
  439. package/dist/tooltip-oAw00FX2.js +48 -0
  440. package/dist/tooltip-u147L0wD.js +48 -0
  441. package/dist/ui.cjs.js +13 -13
  442. package/dist/ui.es.js +13 -13
  443. package/dist/xertica-assistant-B1xAl2Vn.js +2173 -0
  444. package/dist/xertica-assistant-BBUMaUXw.js +2173 -0
  445. package/dist/xertica-assistant-C2A0R94j.js +2173 -0
  446. package/dist/xertica-assistant-CSUprvTR.js +2173 -0
  447. package/dist/xertica-assistant-CWuBwfzt.cjs +2180 -0
  448. package/dist/xertica-assistant-Caubm0HR.js +2173 -0
  449. package/dist/xertica-assistant-D2hlwiEP.js +2173 -0
  450. package/dist/xertica-assistant-DEexPM2u.cjs +2180 -0
  451. package/dist/xertica-assistant-DN2J_sQQ.cjs +2180 -0
  452. package/dist/xertica-assistant-DdYS6WXT.cjs +2180 -0
  453. package/dist/xertica-assistant-Dh1dmEx3.cjs +2180 -0
  454. package/dist/xertica-assistant-GGcyHEZG.cjs +2180 -0
  455. package/dist/xertica-assistant-USefPe2L.js +2173 -0
  456. package/dist/xertica-assistant-cwSHFwfv.cjs +2180 -0
  457. package/dist/xertica-ui.css +1 -1
  458. package/llms-compact.txt +1 -1
  459. package/llms.txt +1 -1
  460. package/package.json +3 -2
  461. package/styles/xertica/base.css +46 -0
  462. package/styles/xertica/tokens.css +10 -0
  463. package/templates/package.json +1 -1
  464. package/templates/src/app/App.tsx +5 -1
  465. package/templates/src/app/components/AuthGuard.tsx +6 -0
  466. package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +1 -4
  467. package/templates/src/features/auth/ui/LoginContent.tsx +1 -4
  468. package/templates/src/features/auth/ui/ResetPasswordContent.tsx +1 -4
  469. package/templates/src/features/auth/ui/VerifyEmailContent.tsx +1 -4
  470. package/templates/src/features/home/ui/HomeContent.tsx +12 -13
  471. package/templates/src/features/template/ui/TemplateContent.tsx +569 -26
  472. package/templates/src/locales/en/pages/landing.json +175 -0
  473. package/templates/src/locales/en/pages/templates.json +112 -4
  474. package/templates/src/locales/es/pages/landing.json +175 -0
  475. package/templates/src/locales/es/pages/templates.json +112 -4
  476. package/templates/src/locales/pt-BR/pages/landing.json +175 -0
  477. package/templates/src/locales/pt-BR/pages/templates.json +112 -4
  478. package/templates/src/pages/LandingPage.tsx +3 -0
  479. package/templates/src/styles/xertica/tokens.css +10 -0
  480. package/templates/vite.config.ts +25 -0
@@ -441,7 +441,7 @@ export function XerticaAssistant({
441
441
  {/* Main Assistant Container */}
442
442
  <div
443
443
  className={cn(
444
- `${containerHeight} flex flex-col bg-background relative`,
444
+ `${containerHeight} flex flex-col bg-card relative`,
445
445
  !isFullPage && 'border-l border-border shadow-sm',
446
446
  isMobile && isExpanded && 'fixed inset-0 z-[100] h-[100dvh] w-full border-l-0 shadow-2xl',
447
447
  className
@@ -1,35 +1,80 @@
1
1
  import React from 'react';
2
2
  import { ImageWithFallback } from '../../figma/ImageWithFallback';
3
3
  import { LanguageSelector } from '../../brand/language-selector';
4
+ import { IsotypeTwist } from '../../brand/isotype';
5
+ import { cn } from '../../shared/utils';
4
6
 
5
- export interface AuthPageShellProps {
6
- imageSrc: string;
7
- imageAlt: string;
8
- children: React.ReactNode;
9
- }
7
+ export type AuthPageShellProps =
8
+ | {
9
+ /** Hero photo on the left (default). Requires `imageSrc`/`imageAlt`. */
10
+ leftPanel?: 'image';
11
+ imageSrc: string;
12
+ imageAlt: string;
13
+ /**
14
+ * Background classes for the hero image overlay gradient. Defaults to the
15
+ * shared `--gradient-diagonal` theme token; pass a Tailwind gradient to
16
+ * override it for a specific auth page without affecting the others.
17
+ */
18
+ gradientClassName?: string;
19
+ children: React.ReactNode;
20
+ }
21
+ | {
22
+ /**
23
+ * Brand isotype mark on a solid `bg-muted` panel — no photo, no
24
+ * gradient. Pairs with a lighter `bg-card` form panel on the right,
25
+ * the inverse of the `image` variant's `bg-muted` form panel.
26
+ */
27
+ leftPanel: 'isotype';
28
+ children: React.ReactNode;
29
+ };
10
30
 
11
31
  /**
12
32
  * Shared two-column shell used by every auth page (Login, ForgotPassword,
13
- * ResetPassword, VerifyEmail): hero image on the left, centered form panel
14
- * with a language selector on the right.
33
+ * ResetPassword, VerifyEmail): a left panel (hero image or brand isotype) and
34
+ * a centered form panel with a language selector on the right.
15
35
  */
16
- export function AuthPageShell({ imageSrc, imageAlt, children }: AuthPageShellProps) {
36
+ export function AuthPageShell(props: AuthPageShellProps) {
37
+ const { children } = props;
38
+
17
39
  return (
18
40
  <div className="h-screen w-full flex overflow-y-auto">
19
- <div className="hidden lg:flex lg:flex-1 relative overflow-hidden">
20
- <ImageWithFallback
21
- src={imageSrc}
22
- alt={imageAlt}
23
- className="absolute inset-0 w-full h-full object-cover"
24
- />
25
- <div className="absolute inset-0 bg-[image:var(--gradient-diagonal)] opacity-80" />
26
- </div>
41
+ {props.leftPanel === 'isotype' ? (
42
+ <div className="hidden lg:flex lg:flex-1 items-center justify-center bg-muted">
43
+ <IsotypeTwist variant="magenta-blue" className="w-full max-w-sm" />
44
+ </div>
45
+ ) : (
46
+ <div className="hidden lg:flex lg:flex-1 relative overflow-hidden">
47
+ <ImageWithFallback
48
+ src={props.imageSrc}
49
+ alt={props.imageAlt}
50
+ className="absolute inset-0 w-full h-full object-cover"
51
+ />
52
+ <div
53
+ className={cn(
54
+ 'absolute inset-0 opacity-80',
55
+ props.gradientClassName ?? 'bg-[image:var(--gradient-diagonal)]'
56
+ )}
57
+ />
58
+ </div>
59
+ )}
27
60
 
28
- <div className="flex-1 flex items-center justify-center px-4 sm:px-6 lg:px-8 lg:flex-none lg:w-1/2 relative bg-muted">
61
+ <div
62
+ className={cn(
63
+ 'flex-1 flex items-center justify-center px-4 sm:px-6 lg:px-8 lg:flex-none lg:w-1/2 relative',
64
+ props.leftPanel === 'isotype' ? 'bg-card' : 'bg-muted'
65
+ )}
66
+ >
29
67
  <div className="absolute top-4 right-4 z-20">
30
68
  <LanguageSelector variant="minimal" showIcon={false} />
31
69
  </div>
32
- <div className="absolute inset-0 lg:hidden bg-[image:var(--gradient-diagonal)] opacity-10 dark:opacity-5" />
70
+ {props.leftPanel !== 'isotype' && (
71
+ <div
72
+ className={cn(
73
+ 'absolute inset-0 lg:hidden opacity-10 dark:opacity-5',
74
+ props.gradientClassName ?? 'bg-[image:var(--gradient-diagonal)]'
75
+ )}
76
+ />
77
+ )}
33
78
  <div className="w-full max-w-sm space-y-6 relative z-10">{children}</div>
34
79
  </div>
35
80
  </div>
@@ -37,7 +37,7 @@ export function SocialLoginButtons({
37
37
  <Button
38
38
  type="button"
39
39
  variant="outline"
40
- className="w-full justify-center"
40
+ className="w-full justify-center shadow-xs"
41
41
  onClick={() => onSocialLogin('Google')}
42
42
  >
43
43
  <svg className="w-5 h-5 mr-2" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
@@ -67,7 +67,7 @@ export function SocialLoginButtons({
67
67
  <Button
68
68
  type="button"
69
69
  variant="outline"
70
- className="w-full justify-center"
70
+ className="w-full justify-center shadow-xs"
71
71
  onClick={() => onSocialLogin('MT Login')}
72
72
  >
73
73
  <Lock className="w-5 h-5 mr-2 text-[var(--chart-4)]" />
@@ -79,7 +79,7 @@ export function SocialLoginButtons({
79
79
  <Button
80
80
  type="button"
81
81
  variant="outline"
82
- className="w-full justify-center font-normal"
82
+ className="w-full justify-center font-normal shadow-xs"
83
83
  onClick={() => onSocialLogin('gov.br')}
84
84
  >
85
85
  <span>
@@ -1,2 +1,3 @@
1
1
  export * from './card-patterns';
2
2
  export * from './auth';
3
+ export * from './marketing';
@@ -0,0 +1,73 @@
1
+ import * as React from 'react';
2
+ import { Button } from '../../ui/button';
3
+ import { cn } from '../../shared/utils';
4
+
5
+ export interface CTASectionAction {
6
+ label: string;
7
+ href?: string;
8
+ onClick?: () => void;
9
+ }
10
+
11
+ export interface CTASectionProps extends React.HTMLAttributes<HTMLElement> {
12
+ title: string;
13
+ description?: string;
14
+ cta: CTASectionAction;
15
+ secondaryCta?: CTASectionAction;
16
+ }
17
+
18
+ /**
19
+ * Full-width dark band prompting a primary conversion action.
20
+ *
21
+ * @description
22
+ * A high-impact closing section for marketing pages: a bold left-aligned
23
+ * headline, optional supporting copy, and up to two CTA buttons on a flat
24
+ * `bg-sidebar` surface — the same token-driven dark surface used elsewhere
25
+ * on this page (e.g. the methodology section) — so it stays legible across
26
+ * all Xertica-ui themes without per-theme contrast tuning or a gradient.
27
+ *
28
+ * @ai-rules
29
+ * 1. The background is a flat `bg-sidebar` surface with a `border-sidebar-border` hairline — never reintroduce a gradient or hardcode colors here.
30
+ * 2. Both buttons use their natural variants (`default` for `cta`, `outline` for `secondaryCta`) with no color overrides — they already contrast correctly against `bg-sidebar`; do not force-style them with one-off colors.
31
+ * 3. Each `cta`/`secondaryCta` needs either `href` (renders an `<a>`) or `onClick`.
32
+ */
33
+ export function CTASection({
34
+ title,
35
+ description,
36
+ cta,
37
+ secondaryCta,
38
+ className,
39
+ ...props
40
+ }: CTASectionProps) {
41
+ return (
42
+ <section
43
+ className={cn(
44
+ 'w-full rounded-[var(--radius-card)] border border-sidebar-border bg-sidebar px-6 py-16 md:py-20',
45
+ className
46
+ )}
47
+ {...props}
48
+ >
49
+ <div className="flex flex-col gap-8 md:flex-row md:items-center md:justify-between">
50
+ <div className="max-w-xl">
51
+ <h2 className="text-2xl font-bold text-sidebar-foreground md:text-4xl">{title}</h2>
52
+ {description && <p className="mt-6 text-sidebar-foreground/70">{description}</p>}
53
+ </div>
54
+
55
+ <div className="flex flex-col gap-3 sm:flex-row md:shrink-0">
56
+ <Button asChild={!!cta.href} onClick={cta.onClick}>
57
+ {cta.href ? <a href={cta.href}>{cta.label}</a> : cta.label}
58
+ </Button>
59
+
60
+ {secondaryCta && (
61
+ <Button variant="outline" asChild={!!secondaryCta.href} onClick={secondaryCta.onClick}>
62
+ {secondaryCta.href ? (
63
+ <a href={secondaryCta.href}>{secondaryCta.label}</a>
64
+ ) : (
65
+ secondaryCta.label
66
+ )}
67
+ </Button>
68
+ )}
69
+ </div>
70
+ </div>
71
+ </section>
72
+ );
73
+ }
@@ -0,0 +1,49 @@
1
+ import * as React from 'react';
2
+ import { cn } from '../../shared/utils';
3
+
4
+ export interface ComplianceBadge {
5
+ icon: React.ReactNode;
6
+ label: string;
7
+ description?: string;
8
+ }
9
+
10
+ export interface ComplianceBadgeRowProps extends React.HTMLAttributes<HTMLDivElement> {
11
+ badges: ComplianceBadge[];
12
+ }
13
+
14
+ /**
15
+ * A row of certification/compliance badges (e.g. SOC 2, GDPR, WCAG 2.1 AA).
16
+ *
17
+ * @description
18
+ * Renders a left-aligned grid where each badge pairs a token-radius outlined
19
+ * icon chip with a label and an optional short description, built entirely
20
+ * from theme tokens so it reskins across all Xertica-ui themes and dark mode.
21
+ *
22
+ * @ai-rules
23
+ * 1. Provide `badges` as `{ icon, label, description? }` — `icon` should be a small lucide-react element.
24
+ * 2. Keep `label` and `description` short — badges sit in a `grid-cols-2 sm:grid-cols-4` layout, so each column has limited width.
25
+ * 3. Do not hand-roll badge styling elsewhere — this component owns the icon-chip/label/description layout.
26
+ */
27
+ export function ComplianceBadgeRow({ badges, className, ...props }: ComplianceBadgeRowProps) {
28
+ return (
29
+ <div
30
+ className={cn('grid grid-cols-2 gap-x-8 gap-y-10 sm:grid-cols-4', className)}
31
+ {...props}
32
+ >
33
+ {badges.map((badge, index) => (
34
+ <div
35
+ key={`${badge.label}-${index}`}
36
+ className="flex flex-col items-start gap-3 text-left"
37
+ >
38
+ <div className="flex items-center justify-center rounded-[var(--radius)] border border-border bg-background p-3 [&>svg]:size-6">
39
+ {badge.icon}
40
+ </div>
41
+ <p className="text-sm font-medium text-foreground">{badge.label}</p>
42
+ {badge.description && (
43
+ <p className="text-xs text-muted-foreground">{badge.description}</p>
44
+ )}
45
+ </div>
46
+ ))}
47
+ </div>
48
+ );
49
+ }
@@ -0,0 +1,91 @@
1
+ import * as React from 'react';
2
+ import { cn } from '../../shared/utils';
3
+
4
+ export type BlockColor =
5
+ | 'primary'
6
+ | 'chart-1'
7
+ | 'chart-2'
8
+ | 'chart-3'
9
+ | 'chart-4'
10
+ | 'chart-5'
11
+ | 'success'
12
+ | 'info'
13
+ | 'warning'
14
+ | 'destructive';
15
+
16
+ const colorTokens: Record<BlockColor, { bg: string; icon: string }> = {
17
+ primary: { bg: 'bg-primary/10', icon: 'text-primary' },
18
+ 'chart-1': { bg: 'bg-[var(--chart-1)]/15', icon: 'text-[var(--chart-1)]' },
19
+ 'chart-2': { bg: 'bg-[var(--chart-2)]/15', icon: 'text-[var(--chart-2)]' },
20
+ 'chart-3': { bg: 'bg-[var(--chart-3)]/15', icon: 'text-[var(--chart-3)]' },
21
+ 'chart-4': { bg: 'bg-[var(--chart-4)]/15', icon: 'text-[var(--chart-4)]' },
22
+ 'chart-5': { bg: 'bg-[var(--chart-5)]/15', icon: 'text-[var(--chart-5)]' },
23
+ success: { bg: 'bg-success/10', icon: 'text-success' },
24
+ info: { bg: 'bg-info/10', icon: 'text-info' },
25
+ warning: { bg: 'bg-warning/10', icon: 'text-warning' },
26
+ destructive: { bg: 'bg-destructive/10', icon: 'text-destructive' },
27
+ };
28
+
29
+ export interface EvidenceTimelineItem {
30
+ number?: string | number;
31
+ icon?: React.ReactNode;
32
+ title: string;
33
+ description: string;
34
+ color?: BlockColor;
35
+ }
36
+
37
+ export interface EvidenceTimelineProps extends React.HTMLAttributes<HTMLDivElement> {
38
+ items: EvidenceTimelineItem[];
39
+ }
40
+
41
+ /**
42
+ * Vertical numbered timeline with a connecting line and colored step dots.
43
+ *
44
+ * @description
45
+ * Renders a "how our methodology works" style list: each item gets a
46
+ * colored dot (icon or step number) on a shared vertical line, with a
47
+ * title and description to its right.
48
+ *
49
+ * @ai-rules
50
+ * 1. Provide `icon` for a lucide-react icon in the dot, or `number` for a step label; if neither is set the 1-based index is used.
51
+ * 2. Each item's `color` maps to `colorTokens` — never hardcode colors.
52
+ * 3. This block has no outer card chrome; wrap it in a `<Card>` or section if chrome is needed.
53
+ */
54
+ export function EvidenceTimeline({ items, className, ...props }: EvidenceTimelineProps) {
55
+ return (
56
+ <div className={cn('relative pl-12', className)} {...props}>
57
+ <div aria-hidden="true" className="absolute left-4 top-4 bottom-4 w-px bg-border" />
58
+
59
+ <ol className="relative">
60
+ {items.map((item, index) => {
61
+ const { bg, icon: iconColor } = colorTokens[item.color ?? 'primary'];
62
+
63
+ return (
64
+ <li key={index} className="relative flex items-start gap-4 pb-10 last:pb-0">
65
+ <div
66
+ className={cn(
67
+ 'absolute -left-12 top-0 flex size-8 shrink-0 items-center justify-center rounded-[var(--radius)] z-10 border border-current/20',
68
+ bg
69
+ )}
70
+ >
71
+ <span
72
+ className={cn(
73
+ 'flex items-center justify-center text-sm font-semibold [&>svg]:size-4',
74
+ iconColor
75
+ )}
76
+ >
77
+ {item.icon ?? (item.number ?? index + 1)}
78
+ </span>
79
+ </div>
80
+
81
+ <div className="min-w-0">
82
+ <p className="font-semibold">{item.title}</p>
83
+ <p className="mt-2 text-sm opacity-70">{item.description}</p>
84
+ </div>
85
+ </li>
86
+ );
87
+ })}
88
+ </ol>
89
+ </div>
90
+ );
91
+ }
@@ -0,0 +1,78 @@
1
+ import * as React from 'react';
2
+ import { CheckCircle2 } from 'lucide-react';
3
+ import { cn } from '../../shared/utils';
4
+
5
+ export interface FeatureRowProps extends React.HTMLAttributes<HTMLElement> {
6
+ eyebrow?: string;
7
+ title: string;
8
+ description?: string;
9
+ bullets?: string[];
10
+ visual: React.ReactNode;
11
+ reverse?: boolean;
12
+ tone?: 'default' | 'muted' | 'card';
13
+ }
14
+
15
+ /**
16
+ * Alternating text + visual marketing section.
17
+ *
18
+ * @description
19
+ * A two-column "how it works" / definition row: a text block (eyebrow,
20
+ * title, description, optional checklist) paired with a consumer-supplied
21
+ * visual (image, illustration, or custom node). Stacks on mobile and
22
+ * alternates sides on desktop via `reverse`.
23
+ *
24
+ * @ai-rules
25
+ * 1. Chain multiple `FeatureRow`s and alternate `reverse` to build a "how it works" narrative.
26
+ * 2. Pass the visual as `<ImageWithFallback />` or any custom `ReactNode`; this component never renders an image itself.
27
+ * 3. Use `tone="muted"` on every other row to create a subtle section break instead of adding manual dividers; use `tone="card"` when a theme needs a stronger, genuinely lighter break (some themes set `--muted` equal to `--background`).
28
+ */
29
+ export function FeatureRow({
30
+ eyebrow,
31
+ title,
32
+ description,
33
+ bullets,
34
+ visual,
35
+ reverse = false,
36
+ tone = 'default',
37
+ className,
38
+ ...props
39
+ }: FeatureRowProps) {
40
+ return (
41
+ <section
42
+ className={cn(
43
+ 'py-16 md:py-24',
44
+ tone === 'muted' ? 'bg-muted' : tone === 'card' ? 'bg-card' : 'bg-background',
45
+ className
46
+ )}
47
+ {...props}
48
+ >
49
+ <div className="mx-auto grid max-w-6xl gap-12 px-4 sm:px-6 lg:grid-cols-2 lg:items-center lg:px-8">
50
+ <div className={cn(reverse ? 'lg:order-last' : 'lg:order-first')}>
51
+ {eyebrow && (
52
+ <p className="text-sm font-semibold uppercase tracking-wide text-primary">
53
+ {eyebrow}
54
+ </p>
55
+ )}
56
+ <h2 className={cn('text-2xl font-bold text-foreground md:text-3xl', eyebrow && 'mt-2')}>
57
+ {title}
58
+ </h2>
59
+ {description && (
60
+ <p className="mt-6 text-muted-foreground leading-relaxed">{description}</p>
61
+ )}
62
+ {bullets && bullets.length > 0 && (
63
+ <ul className="mt-4 space-y-2">
64
+ {bullets.map(bullet => (
65
+ <li key={bullet} className="flex items-start gap-2">
66
+ <CheckCircle2 className="size-5 shrink-0 text-primary" />
67
+ <span className="text-foreground">{bullet}</span>
68
+ </li>
69
+ ))}
70
+ </ul>
71
+ )}
72
+ </div>
73
+
74
+ <div className={cn(reverse ? 'lg:order-first' : 'lg:order-last')}>{visual}</div>
75
+ </div>
76
+ </section>
77
+ );
78
+ }
@@ -0,0 +1,125 @@
1
+ import * as React from 'react';
2
+ import { Button } from '../../ui/button';
3
+ import { PillBadge } from './PillBadge';
4
+ import { cn } from '../../shared/utils';
5
+
6
+ export interface HeroCta {
7
+ label: string;
8
+ href?: string;
9
+ onClick?: () => void;
10
+ }
11
+
12
+ export interface HeroProps extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {
13
+ eyebrow?: { label: string; icon?: React.ReactNode };
14
+ title: React.ReactNode;
15
+ description?: React.ReactNode;
16
+ primaryCta?: HeroCta;
17
+ secondaryCta?: HeroCta;
18
+ visual?: React.ReactNode;
19
+ align?: 'left' | 'center';
20
+ decorative?: boolean;
21
+ }
22
+
23
+ function HeroCtaButton({
24
+ cta,
25
+ variant,
26
+ }: {
27
+ cta: HeroCta;
28
+ variant: React.ComponentProps<typeof Button>['variant'];
29
+ }) {
30
+ if (cta.href) {
31
+ return (
32
+ <Button asChild variant={variant} size="lg">
33
+ <a href={cta.href} onClick={cta.onClick}>
34
+ {cta.label}
35
+ </a>
36
+ </Button>
37
+ );
38
+ }
39
+
40
+ return (
41
+ <Button variant={variant} size="lg" onClick={cta.onClick}>
42
+ {cta.label}
43
+ </Button>
44
+ );
45
+ }
46
+
47
+ /**
48
+ * Full-width, above-the-fold marketing hero section.
49
+ *
50
+ * @description
51
+ * The lead block for landing and marketing pages: an optional `PillBadge`
52
+ * eyebrow, a very large headline, supporting copy, and up to two `<Button>`
53
+ * CTAs. Automatically switches from a single column to a two-column layout
54
+ * once a `visual` (screenshot, illustration, collage) is supplied.
55
+ *
56
+ * @ai-rules
57
+ * 1. Pass `visual` for the two-column desktop layout; omit it for a single-column hero.
58
+ * 2. `primaryCta` renders as `default` (primary/brand) and `secondaryCta` as `secondary`, both via `<Button>` (`size="lg"`) — never hand-roll buttons.
59
+ * 3. Set `decorative` to add a token-based gradient blob backdrop; it is purely visual and never shifts layout.
60
+ * 4. `align="center"` centers the eyebrow/heading/copy/CTAs — pair it with omitting `visual` for a classic centered hero.
61
+ */
62
+ export function Hero({
63
+ eyebrow,
64
+ title,
65
+ description,
66
+ primaryCta,
67
+ secondaryCta,
68
+ visual,
69
+ align = 'left',
70
+ decorative = false,
71
+ className,
72
+ ...props
73
+ }: HeroProps) {
74
+ const isCentered = align === 'center';
75
+
76
+ return (
77
+ <section className={cn('relative overflow-hidden py-16 md:py-24', className)} {...props}>
78
+ {decorative && (
79
+ <div
80
+ className="pointer-events-none absolute inset-0 z-0 overflow-hidden"
81
+ aria-hidden="true"
82
+ >
83
+ <div className="absolute left-1/2 top-1/2 h-72 w-72 -translate-x-1/2 -translate-y-1/2 rounded-full bg-[linear-gradient(135deg,var(--gradient-start),var(--gradient-end))] opacity-20 blur-3xl md:h-[28rem] md:w-[28rem] lg:h-[36rem] lg:w-[36rem]" />
84
+ </div>
85
+ )}
86
+
87
+ <div className="relative z-10 mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
88
+ <div
89
+ className={cn('grid items-center gap-12', visual ? 'lg:grid-cols-2' : 'mx-auto max-w-3xl')}
90
+ >
91
+ <div
92
+ className={cn(
93
+ 'flex flex-col gap-6',
94
+ isCentered ? 'items-center text-center' : 'items-start text-left'
95
+ )}
96
+ >
97
+ {eyebrow && <PillBadge icon={eyebrow.icon}>{eyebrow.label}</PillBadge>}
98
+
99
+ <h1 className="text-4xl font-bold tracking-tight text-foreground md:text-5xl lg:text-6xl">
100
+ {title}
101
+ </h1>
102
+
103
+ {description && (
104
+ <p className="max-w-2xl text-lg text-muted-foreground">{description}</p>
105
+ )}
106
+
107
+ {(primaryCta || secondaryCta) && (
108
+ <div
109
+ className={cn(
110
+ 'flex flex-col gap-3 pt-2 sm:flex-row',
111
+ isCentered && 'sm:justify-center'
112
+ )}
113
+ >
114
+ {primaryCta && <HeroCtaButton cta={primaryCta} variant="default" />}
115
+ {secondaryCta && <HeroCtaButton cta={secondaryCta} variant="secondary" />}
116
+ </div>
117
+ )}
118
+ </div>
119
+
120
+ {visual && <div className="relative">{visual}</div>}
121
+ </div>
122
+ </div>
123
+ </section>
124
+ );
125
+ }
@@ -0,0 +1,90 @@
1
+ import * as React from 'react';
2
+ import { cn } from '../../shared/utils';
3
+
4
+ export type BlockColor =
5
+ | 'primary'
6
+ | 'chart-1'
7
+ | 'chart-2'
8
+ | 'chart-3'
9
+ | 'chart-4'
10
+ | 'chart-5'
11
+ | 'success'
12
+ | 'info'
13
+ | 'warning'
14
+ | 'destructive';
15
+
16
+ const colorTokens: Record<BlockColor, { bg: string; icon: string }> = {
17
+ primary: { bg: 'bg-primary/10', icon: 'text-primary' },
18
+ 'chart-1': { bg: 'bg-[var(--chart-1)]/15', icon: 'text-[var(--chart-1)]' },
19
+ 'chart-2': { bg: 'bg-[var(--chart-2)]/15', icon: 'text-[var(--chart-2)]' },
20
+ 'chart-3': { bg: 'bg-[var(--chart-3)]/15', icon: 'text-[var(--chart-3)]' },
21
+ 'chart-4': { bg: 'bg-[var(--chart-4)]/15', icon: 'text-[var(--chart-4)]' },
22
+ 'chart-5': { bg: 'bg-[var(--chart-5)]/15', icon: 'text-[var(--chart-5)]' },
23
+ success: { bg: 'bg-success/10', icon: 'text-success' },
24
+ info: { bg: 'bg-info/10', icon: 'text-info' },
25
+ warning: { bg: 'bg-warning/10', icon: 'text-warning' },
26
+ destructive: { bg: 'bg-destructive/10', icon: 'text-destructive' },
27
+ };
28
+
29
+ export interface HowItWorksStepItem {
30
+ number?: string | number;
31
+ icon?: React.ReactNode;
32
+ title: string;
33
+ description: string;
34
+ color?: BlockColor;
35
+ }
36
+
37
+ export interface HowItWorksStepsProps {
38
+ items: HowItWorksStepItem[];
39
+ className?: string;
40
+ }
41
+
42
+ /**
43
+ * Horizontal numbered process row — the horizontal counterpart to `EvidenceTimeline`.
44
+ *
45
+ * @description
46
+ * Renders a "how it works" style row of steps: each item gets a colored
47
+ * badge (icon or step number) above a title and description, laid out
48
+ * side by side in a responsive grid instead of `EvidenceTimeline`'s
49
+ * vertical connecting line.
50
+ *
51
+ * @ai-rules
52
+ * 1. Provide `icon` for a lucide-react icon in the badge, or `number` for a step label; if neither is set the 1-based index is used.
53
+ * 2. Each item's `color` maps to `colorTokens` — never hardcode colors.
54
+ * 3. There is no connecting line between steps (unlike `EvidenceTimeline`) — this avoids awkward line fragments when steps wrap to a new row on narrow screens.
55
+ * 4. This block has no outer card chrome; wrap it in a `<Card>` or section if chrome is needed.
56
+ */
57
+ export function HowItWorksSteps({ items, className }: HowItWorksStepsProps) {
58
+ return (
59
+ <ol className={cn('grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-4', className)}>
60
+ {items.map((item, index) => {
61
+ const { bg, icon: iconColor } = colorTokens[item.color ?? 'primary'];
62
+
63
+ return (
64
+ <li key={index} className="flex flex-col gap-4">
65
+ <div
66
+ className={cn(
67
+ 'flex size-10 shrink-0 items-center justify-center rounded-[var(--radius)] border border-current/20 md:size-12',
68
+ bg
69
+ )}
70
+ >
71
+ <span
72
+ className={cn(
73
+ 'flex items-center justify-center text-sm font-semibold [&>svg]:size-5',
74
+ iconColor
75
+ )}
76
+ >
77
+ {item.icon ?? (item.number ?? index + 1)}
78
+ </span>
79
+ </div>
80
+
81
+ <div className="min-w-0">
82
+ <p className="font-semibold">{item.title}</p>
83
+ <p className="mt-2 text-sm opacity-70">{item.description}</p>
84
+ </div>
85
+ </li>
86
+ );
87
+ })}
88
+ </ol>
89
+ );
90
+ }