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
package/bin/cli.ts CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  syncLocaleFiles,
18
18
  generateI18nFile,
19
19
  generateAppTsx,
20
+ generateLandingAppTsx,
20
21
  } from './language-config';
21
22
 
22
23
  // ─────────────────────────────────────────────────────────────────────────────
@@ -31,6 +32,8 @@ interface XerticaConfig {
31
32
  hasAssistant: boolean;
32
33
  disableDarkMode?: boolean;
33
34
  themeId?: string;
35
+ /** Missing on projects scaffolded before this field existed — treat as 'system'. */
36
+ projectType?: 'page' | 'system';
34
37
  }
35
38
 
36
39
  async function readXerticaConfig(targetDir: string): Promise<XerticaConfig | null> {
@@ -286,6 +289,165 @@ export function TemplatePage() {
286
289
  `;
287
290
  }
288
291
 
292
+ // ─────────────────────────────────────────────────────────────────────────────
293
+ // package.json copy helper — shared by the 'system' and 'page' init flows.
294
+ // ─────────────────────────────────────────────────────────────────────────────
295
+
296
+ async function copyPackageJson(templatesDir: string, targetDir: string): Promise<void> {
297
+ const pkgTemplatePath = path.join(templatesDir, 'package.json');
298
+ if (await fs.pathExists(pkgTemplatePath)) {
299
+ const pkgContent = await fs.readJson(pkgTemplatePath);
300
+ const projectName = path.basename(targetDir) || 'my-xertica-app';
301
+ pkgContent.name = projectName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
302
+ await fs.writeJson(path.join(targetDir, 'package.json'), pkgContent, { spaces: 2 });
303
+ }
304
+ }
305
+
306
+ // ─────────────────────────────────────────────────────────────────────────────
307
+ // Minimal "web page" scaffold — just the marketing LandingPage, no auth shell.
308
+ // ─────────────────────────────────────────────────────────────────────────────
309
+
310
+ async function initPageProject(targetDir: string, templatesDir: string): Promise<void> {
311
+ const response = await prompts([
312
+ {
313
+ type: 'multiselect',
314
+ name: 'languages',
315
+ message: 'Which languages should the page support?',
316
+ instructions: false,
317
+ hint: 'Select at least 1. Single-language apps auto-hide the LanguageSelector.',
318
+ min: 1,
319
+ choices: SUPPORTED_LANGUAGES.map(l => ({
320
+ title: l.label,
321
+ value: l.code,
322
+ selected: true,
323
+ })),
324
+ },
325
+ {
326
+ type: 'select',
327
+ name: 'theme',
328
+ message: 'Select the default color theme for your project:',
329
+ choices: colorThemes.map(t => ({
330
+ title: t.name,
331
+ description: t.description,
332
+ value: t.id,
333
+ })),
334
+ initial: 0,
335
+ },
336
+ {
337
+ type: 'confirm',
338
+ name: 'install',
339
+ message: 'Install dependencies automatically?',
340
+ initial: true,
341
+ },
342
+ ]);
343
+
344
+ if (!response.languages || !response.theme) return;
345
+
346
+ const spinner = ora('Initializing project...').start();
347
+
348
+ try {
349
+ await fs.ensureDir(targetDir);
350
+
351
+ const selectedLanguages: string[] =
352
+ Array.isArray(response.languages) && response.languages.length > 0
353
+ ? response.languages
354
+ : DEFAULT_SELECTION;
355
+
356
+ // 1. Copy root config files (no CLAUDE.md/guidelines — those document the
357
+ // FSD auth-app architecture, which this scaffold doesn't have; no
358
+ // .env.example — its keys are only used by the assistant/maps pages).
359
+ const rootFilesToCopy = [
360
+ 'index.html',
361
+ 'vite.config.ts',
362
+ 'tsconfig.json',
363
+ 'tsconfig.node.json',
364
+ 'postcss.config.js',
365
+ 'vite-env.d.ts',
366
+ 'eslint.config.js',
367
+ '.gitignore',
368
+ '.prettierrc',
369
+ ];
370
+
371
+ for (const file of rootFilesToCopy) {
372
+ const srcPath = path.join(templatesDir, file);
373
+ if (await fs.pathExists(srcPath)) {
374
+ await fs.copy(srcPath, path.join(targetDir, file));
375
+ }
376
+ }
377
+
378
+ // 2. Copy package.json
379
+ await copyPackageJson(templatesDir, targetDir);
380
+
381
+ // 3. Copy src/main.tsx (unchanged regardless of App.tsx variant)
382
+ await fs.copy(
383
+ path.join(templatesDir, 'src', 'main.tsx'),
384
+ path.join(targetDir, 'src', 'main.tsx')
385
+ );
386
+
387
+ // 4. Generate src/app/App.tsx rendering LandingPage directly
388
+ await fs.ensureDir(path.join(targetDir, 'src', 'app'));
389
+ await fs.writeFile(
390
+ path.join(targetDir, 'src', 'app', 'App.tsx'),
391
+ generateLandingAppTsx(selectedLanguages)
392
+ );
393
+
394
+ // 5. Generate i18n.ts + copy selected locales
395
+ await fs.writeFile(
396
+ path.join(targetDir, 'src', 'i18n.ts'),
397
+ generateI18nFile(selectedLanguages)
398
+ );
399
+ await syncLocaleFiles(templatesDir, targetDir, selectedLanguages, { pruneOthers: true });
400
+ await writeLanguagesConfig(targetDir, selectedLanguages);
401
+
402
+ // 6. Persist project config
403
+ await writeXerticaConfig(targetDir, {
404
+ hasAssistant: false,
405
+ disableDarkMode: false,
406
+ themeId: response.theme,
407
+ projectType: 'page',
408
+ });
409
+
410
+ // 7. Copy the LandingPage re-export shim
411
+ await fs.ensureDir(path.join(targetDir, 'src', 'pages'));
412
+ await fs.copy(
413
+ path.join(templatesDir, 'src', 'pages', 'LandingPage.tsx'),
414
+ path.join(targetDir, 'src', 'pages', 'LandingPage.tsx')
415
+ );
416
+
417
+ // 8. Generate theme tokens
418
+ const selectedTheme = colorThemes.find(t => t.id === response.theme) || colorThemes[0];
419
+ const tokensDir = path.join(targetDir, 'src', 'styles', 'xertica');
420
+ await fs.ensureDir(tokensDir);
421
+ await fs.copy(
422
+ path.join(templatesDir, 'src', 'styles', 'index.css'),
423
+ path.join(targetDir, 'src', 'styles', 'index.css')
424
+ );
425
+ await fs.writeFile(path.join(tokensDir, 'tokens.css'), generateTokensCss(selectedTheme));
426
+
427
+ spinner.succeed('Project initialized successfully!');
428
+
429
+ if (response.install) {
430
+ const installSpinner = ora('Installing dependencies...').start();
431
+ await execa('npm', ['install'], { cwd: targetDir });
432
+ installSpinner.succeed('Dependencies installed!');
433
+ }
434
+
435
+ console.log(chalk.green('\n✅ Done! Your Xertica UI landing page is ready.'));
436
+ console.log(chalk.cyan(`\n cd ${path.relative(process.cwd(), targetDir) || '.'}`));
437
+ if (!response.install) {
438
+ console.log(chalk.cyan(' npm install'));
439
+ }
440
+ console.log(chalk.cyan(' npm run dev'));
441
+ console.log();
442
+ console.log(chalk.gray(' The page is composed in xertica-ui/pages — edit src/app/App.tsx'));
443
+ console.log(chalk.gray(' Customize the theme in src/styles/xertica/tokens.css'));
444
+ console.log(chalk.gray(' To change the theme or languages later: npx xertica-ui update'));
445
+ } catch (error) {
446
+ spinner.fail('Failed to initialize project');
447
+ console.error(error);
448
+ }
449
+ }
450
+
289
451
  const program = new Command();
290
452
 
291
453
  program
@@ -303,6 +465,32 @@ program
303
465
 
304
466
  console.log(chalk.blue(`🚀 Welcome to Xertica UI CLI! ${chalk.dim(`v${pkgJson.version}`)}`));
305
467
 
468
+ const { projectType } = await prompts({
469
+ type: 'select',
470
+ name: 'projectType',
471
+ message: 'What do you want to create?',
472
+ choices: [
473
+ {
474
+ title: 'Full system',
475
+ description: 'Auth, sidebar, pages, i18n — the current full scaffold',
476
+ value: 'system',
477
+ },
478
+ {
479
+ title: 'Web page',
480
+ description: 'Just the marketing landing page — pick a theme and languages, done',
481
+ value: 'page',
482
+ },
483
+ ],
484
+ initial: 0,
485
+ });
486
+
487
+ if (!projectType) return;
488
+
489
+ if (projectType === 'page') {
490
+ await initPageProject(targetDir, templatesDir);
491
+ return;
492
+ }
493
+
306
494
  const response = await prompts([
307
495
  {
308
496
  type: 'multiselect',
@@ -408,13 +596,7 @@ program
408
596
  }
409
597
 
410
598
  // 2. Copy package.json
411
- const pkgTemplatePath = path.join(templatesDir, 'package.json');
412
- if (await fs.pathExists(pkgTemplatePath)) {
413
- const pkgContent = await fs.readJson(pkgTemplatePath);
414
- const projectName = path.basename(targetDir) || 'my-xertica-app';
415
- pkgContent.name = projectName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
416
- await fs.writeJson(path.join(targetDir, 'package.json'), pkgContent, { spaces: 2 });
417
- }
599
+ await copyPackageJson(templatesDir, targetDir);
418
600
 
419
601
  // 3. Copy src/main.tsx
420
602
  await fs.copy(
@@ -458,7 +640,12 @@ program
458
640
  await writeLanguagesConfig(targetDir, selectedLanguages);
459
641
 
460
642
  // 6.5 Persist project feature flags (.xertica.json)
461
- await writeXerticaConfig(targetDir, { hasAssistant, disableDarkMode, themeId: response.theme });
643
+ await writeXerticaConfig(targetDir, {
644
+ hasAssistant,
645
+ disableDarkMode,
646
+ themeId: response.theme,
647
+ projectType: 'system',
648
+ });
462
649
 
463
650
  // 6.4 Copy context
464
651
  await fs.ensureDir(path.join(targetDir, 'src', 'app', 'context'));
@@ -610,6 +797,8 @@ program
610
797
  console.log(chalk.blue(`🔧 Xertica UI CLI ${chalk.dim(`v${pkgJson.version}`)}`));
611
798
 
612
799
  const currentConfig = await readXerticaConfig(targetDir);
800
+ const projectType = currentConfig?.projectType ?? 'system';
801
+ const isPageProject = projectType === 'page';
613
802
 
614
803
  const { updateType } = await prompts({
615
804
  type: 'select',
@@ -626,13 +815,17 @@ program
626
815
  description: 'Add or remove supported languages (pt-BR, en, es, …)',
627
816
  value: 'languages',
628
817
  },
629
- {
630
- title: 'Assistant',
631
- description: currentConfig?.hasAssistant
632
- ? 'Remove the AI Assistant from your project'
633
- : 'Add the AI Assistant to your project',
634
- value: 'assistant',
635
- },
818
+ ...(isPageProject
819
+ ? []
820
+ : [
821
+ {
822
+ title: 'Assistant',
823
+ description: currentConfig?.hasAssistant
824
+ ? 'Remove the AI Assistant from your project'
825
+ : 'Add the AI Assistant to your project',
826
+ value: 'assistant',
827
+ },
828
+ ]),
636
829
  {
637
830
  title: 'Dark Mode',
638
831
  description: currentConfig?.disableDarkMode
@@ -642,7 +835,9 @@ program
642
835
  },
643
836
  {
644
837
  title: 'Project files',
645
- description: 'Update app shell, shared, features and pages to a specific version',
838
+ description: isPageProject
839
+ ? 'Update the app shell and landing page to a specific version'
840
+ : 'Update app shell, shared, features and pages to a specific version',
646
841
  value: 'project',
647
842
  },
648
843
  ],
@@ -798,7 +993,9 @@ program
798
993
  // 3) Regenerate App.tsx so the `availableLanguages` prop matches
799
994
  await fs.writeFile(
800
995
  path.join(targetDir, 'src', 'app', 'App.tsx'),
801
- generateAppTsx(newCodes, currentConfig?.disableDarkMode ?? false)
996
+ isPageProject
997
+ ? generateLandingAppTsx(newCodes, currentConfig?.disableDarkMode ?? false)
998
+ : generateAppTsx(newCodes, currentConfig?.disableDarkMode ?? false)
802
999
  );
803
1000
 
804
1001
  // 4) Persist the new selection
@@ -1014,7 +1211,9 @@ program
1014
1211
 
1015
1212
  await fs.writeFile(
1016
1213
  path.join(targetDir, 'src', 'app', 'App.tsx'),
1017
- generateAppTsx(selectedCodes, newDisableDarkMode)
1214
+ isPageProject
1215
+ ? generateLandingAppTsx(selectedCodes, newDisableDarkMode)
1216
+ : generateAppTsx(selectedCodes, newDisableDarkMode)
1018
1217
  );
1019
1218
 
1020
1219
  spinner.succeed(
@@ -1063,38 +1262,53 @@ program
1063
1262
  type: 'multiselect',
1064
1263
  name: 'filesToUpdate',
1065
1264
  message: 'Select which parts of the project to update:',
1066
- choices: [
1067
- {
1068
- title: 'App shell (src/app/)',
1069
- description: 'App.tsx, AppLayout.tsx',
1070
- value: 'app',
1071
- selected: true,
1072
- },
1073
- {
1074
- title: 'Shared utilities (src/shared/)',
1075
- description: 'auth.ts, navigation.ts, types',
1076
- value: 'shared',
1077
- selected: true,
1078
- },
1079
- {
1080
- title: 'Features (src/features/)',
1081
- description: 'auth, home, template UI components',
1082
- value: 'features',
1083
- selected: true,
1084
- },
1085
- {
1086
- title: 'Pages (src/pages/)',
1087
- description: 'Thin page wrapper components',
1088
- value: 'pages',
1089
- selected: true,
1090
- },
1091
- {
1092
- title: 'Root config files',
1093
- description: 'vite.config.ts, tsconfig.json, etc.',
1094
- value: 'config',
1095
- selected: false,
1096
- },
1097
- ],
1265
+ choices: isPageProject
1266
+ ? [
1267
+ {
1268
+ title: 'App shell + landing page',
1269
+ description: 'App.tsx and the LandingPage re-export',
1270
+ value: 'app',
1271
+ selected: true,
1272
+ },
1273
+ {
1274
+ title: 'Root config files',
1275
+ description: 'vite.config.ts, tsconfig.json, etc.',
1276
+ value: 'config',
1277
+ selected: false,
1278
+ },
1279
+ ]
1280
+ : [
1281
+ {
1282
+ title: 'App shell (src/app/)',
1283
+ description: 'App.tsx, AppLayout.tsx',
1284
+ value: 'app',
1285
+ selected: true,
1286
+ },
1287
+ {
1288
+ title: 'Shared utilities (src/shared/)',
1289
+ description: 'auth.ts, navigation.ts, types',
1290
+ value: 'shared',
1291
+ selected: true,
1292
+ },
1293
+ {
1294
+ title: 'Features (src/features/)',
1295
+ description: 'auth, home, template UI components',
1296
+ value: 'features',
1297
+ selected: true,
1298
+ },
1299
+ {
1300
+ title: 'Pages (src/pages/)',
1301
+ description: 'Thin page wrapper components',
1302
+ value: 'pages',
1303
+ selected: true,
1304
+ },
1305
+ {
1306
+ title: 'Root config files',
1307
+ description: 'vite.config.ts, tsconfig.json, etc.',
1308
+ value: 'config',
1309
+ selected: false,
1310
+ },
1311
+ ],
1098
1312
  });
1099
1313
 
1100
1314
  if (!filesToUpdate || filesToUpdate.length === 0) return;
@@ -1124,13 +1338,6 @@ program
1124
1338
  const updatedTemplatesDir = path.join(targetDir, 'node_modules', 'xertica-ui', 'templates');
1125
1339
 
1126
1340
  if (filesToUpdate.includes('app')) {
1127
- // AppLayout is always safe to overwrite (no per-project config baked in)
1128
- await fs.copy(
1129
- path.join(updatedTemplatesDir, 'src', 'app', 'components', 'AppLayout.tsx'),
1130
- path.join(targetDir, 'src', 'app', 'components', 'AppLayout.tsx'),
1131
- { overwrite: true }
1132
- );
1133
-
1134
1341
  // For App.tsx and i18n.ts we must preserve the user's language selection.
1135
1342
  // Read it from .languages.json (or fall back to inspecting locales/ for
1136
1343
  // projects scaffolded before the file existed).
@@ -1152,38 +1359,71 @@ program
1152
1359
 
1153
1360
  const projectConfig = await readXerticaConfig(targetDir);
1154
1361
 
1155
- // Regenerate App.tsx and i18n.ts honoring the persisted language set
1156
- await fs.writeFile(
1157
- path.join(targetDir, 'src', 'app', 'App.tsx'),
1158
- generateAppTsx(selectedCodes, projectConfig?.disableDarkMode ?? false)
1159
- );
1160
- await fs.writeFile(path.join(targetDir, 'src', 'i18n.ts'), generateI18nFile(selectedCodes));
1362
+ if (isPageProject) {
1363
+ // Regenerate App.tsx and i18n.ts, re-copy the LandingPage shim —
1364
+ // no AppLayout/AuthGuard exist in a page-only project.
1365
+ await fs.writeFile(
1366
+ path.join(targetDir, 'src', 'app', 'App.tsx'),
1367
+ generateLandingAppTsx(selectedCodes, projectConfig?.disableDarkMode ?? false)
1368
+ );
1369
+ await fs.writeFile(
1370
+ path.join(targetDir, 'src', 'i18n.ts'),
1371
+ generateI18nFile(selectedCodes)
1372
+ );
1373
+ await syncLocaleFiles(updatedTemplatesDir, targetDir, selectedCodes, {
1374
+ pruneOthers: true,
1375
+ });
1376
+ await fs.copy(
1377
+ path.join(updatedTemplatesDir, 'src', 'pages', 'LandingPage.tsx'),
1378
+ path.join(targetDir, 'src', 'pages', 'LandingPage.tsx'),
1379
+ { overwrite: true }
1380
+ );
1381
+ } else {
1382
+ // AppLayout is always safe to overwrite (no per-project config baked in)
1383
+ await fs.copy(
1384
+ path.join(updatedTemplatesDir, 'src', 'app', 'components', 'AppLayout.tsx'),
1385
+ path.join(targetDir, 'src', 'app', 'components', 'AppLayout.tsx'),
1386
+ { overwrite: true }
1387
+ );
1161
1388
 
1162
- // Refresh locale JSON files for the selected languages (keys grow over
1163
- // library updates) — but prune any orphans from prior selections.
1164
- await syncLocaleFiles(updatedTemplatesDir, targetDir, selectedCodes, {
1165
- pruneOthers: true,
1166
- });
1389
+ // Regenerate App.tsx and i18n.ts honoring the persisted language set
1390
+ await fs.writeFile(
1391
+ path.join(targetDir, 'src', 'app', 'App.tsx'),
1392
+ generateAppTsx(selectedCodes, projectConfig?.disableDarkMode ?? false)
1393
+ );
1394
+ await fs.writeFile(
1395
+ path.join(targetDir, 'src', 'i18n.ts'),
1396
+ generateI18nFile(selectedCodes)
1397
+ );
1167
1398
 
1168
- // Regenerate AuthGuard preserving the current page set and assistant flag
1169
- const pagesDir = path.join(targetDir, 'src', 'pages');
1170
- const existingPages = (await fs.pathExists(pagesDir)) ? await fs.readdir(pagesDir) : [];
1171
- const hasLoginP = existingPages.includes('LoginPage.tsx');
1172
- const hasHomeP = existingPages.includes('HomePage.tsx');
1173
- const hasTemplateP = existingPages.includes('TemplatePage.tsx');
1174
- const hasAssistantP =
1175
- projectConfig?.hasAssistant ?? existingPages.includes('AssistantPage.tsx');
1176
- const firstProtectedP = hasHomeP ? '/home' : hasTemplateP ? '/template' : '/login';
1177
- await fs.writeFile(
1178
- path.join(targetDir, 'src', 'app', 'components', 'AuthGuard.tsx'),
1179
- generateAuthGuard({
1180
- hasLogin: hasLoginP,
1181
- hasHome: hasHomeP,
1182
- hasTemplate: hasTemplateP,
1183
- hasAssistant: hasAssistantP,
1184
- firstProtectedPath: firstProtectedP,
1185
- })
1186
- );
1399
+ // Refresh locale JSON files for the selected languages (keys grow over
1400
+ // library updates) but prune any orphans from prior selections.
1401
+ await syncLocaleFiles(updatedTemplatesDir, targetDir, selectedCodes, {
1402
+ pruneOthers: true,
1403
+ });
1404
+
1405
+ // Regenerate AuthGuard preserving the current page set and assistant flag
1406
+ const pagesDir = path.join(targetDir, 'src', 'pages');
1407
+ const existingPages = (await fs.pathExists(pagesDir))
1408
+ ? await fs.readdir(pagesDir)
1409
+ : [];
1410
+ const hasLoginP = existingPages.includes('LoginPage.tsx');
1411
+ const hasHomeP = existingPages.includes('HomePage.tsx');
1412
+ const hasTemplateP = existingPages.includes('TemplatePage.tsx');
1413
+ const hasAssistantP =
1414
+ projectConfig?.hasAssistant ?? existingPages.includes('AssistantPage.tsx');
1415
+ const firstProtectedP = hasHomeP ? '/home' : hasTemplateP ? '/template' : '/login';
1416
+ await fs.writeFile(
1417
+ path.join(targetDir, 'src', 'app', 'components', 'AuthGuard.tsx'),
1418
+ generateAuthGuard({
1419
+ hasLogin: hasLoginP,
1420
+ hasHome: hasHomeP,
1421
+ hasTemplate: hasTemplateP,
1422
+ hasAssistant: hasAssistantP,
1423
+ firstProtectedPath: firstProtectedP,
1424
+ })
1425
+ );
1426
+ }
1187
1427
  }
1188
1428
 
1189
1429
  if (filesToUpdate.includes('shared')) {
@@ -42,13 +42,13 @@ export const generateTokensCss = (theme: ColorTheme): string => {
42
42
  --xertica-dark: ${rgba(colors.sidebarDark)};
43
43
 
44
44
  /* Semantic Colors */
45
- --background: rgba(255, 255, 255, 1);
45
+ --background: ${colors.backgroundLight ? rgba(colors.backgroundLight) : 'rgba(255, 255, 255, 1)'};
46
46
  --foreground: rgba(9, 9, 11, 1);
47
-
48
- --card: rgba(255, 255, 255, 1);
47
+
48
+ --card: ${colors.cardLight ? rgba(colors.cardLight) : 'rgba(255, 255, 255, 1)'};
49
49
  --card-foreground: rgba(9, 9, 11, 1);
50
-
51
- --popover: rgba(255, 255, 255, 1);
50
+
51
+ --popover: ${colors.cardLight ? rgba(colors.cardLight) : 'rgba(255, 255, 255, 1)'};
52
52
  --popover-foreground: rgba(9, 9, 11, 1);
53
53
 
54
54
  --primary: var(--xertica-primary);
@@ -59,7 +59,7 @@ export const generateTokensCss = (theme: ColorTheme): string => {
59
59
  --secondary: rgba(244, 244, 245, 1);
60
60
  --secondary-foreground: rgba(24, 24, 27, 1);
61
61
 
62
- --muted: rgba(244, 244, 245, 1);
62
+ --muted: ${colors.backgroundLight ? rgba(colors.backgroundLight) : 'rgba(244, 244, 245, 1)'};
63
63
  --muted-foreground: rgba(113, 113, 122, 1);
64
64
 
65
65
  --accent: rgba(244, 244, 245, 1);
@@ -77,6 +77,7 @@ export const generateTokensCss = (theme: ColorTheme): string => {
77
77
  --warning-foreground: rgba(28, 25, 23, 1);
78
78
 
79
79
  --border: rgba(228, 228, 231, 1);
80
+ --input-border: ${colors.inputBorderColor || 'var(--border)'};
80
81
  --input: rgba(244, 244, 245, 0.5);
81
82
  --input-background: rgba(244, 244, 245, 0.5);
82
83
  --ring: ${rgba(colors.primary, 0.5)};
@@ -106,9 +107,17 @@ export const generateTokensCss = (theme: ColorTheme): string => {
106
107
 
107
108
  /* Spacing & Radius */
108
109
  --radius: 6px;
109
- --radius-button: 12px;
110
+ --radius-button: ${colors.buttonRadius || '12px'};
110
111
  --radius-card: 12px;
111
-
112
+
113
+ /* Button stroke & secondary (theme-overridable; defaults preserve the flat look) */
114
+ --button-stroke-width: ${colors.buttonStrokeWidth || '0px'};
115
+ --button-stroke-color: ${colors.buttonStrokeColor || 'transparent'};
116
+ --button-secondary-bg: ${colors.buttonSecondaryBg || 'var(--secondary)'};
117
+ --button-secondary-foreground: ${colors.buttonSecondaryForeground || 'var(--secondary-foreground)'};
118
+ --button-primary-bg: ${colors.buttonPrimaryBg || 'var(--primary)'};
119
+ --button-primary-foreground: ${colors.buttonPrimaryForeground || 'var(--primary-foreground)'};
120
+
112
121
  --elevation-sm: 0px 0px 48px 0px rgba(0, 0, 0, 0.1);
113
122
 
114
123
  /* Typography */
@@ -209,7 +218,14 @@ export const generateTokensCss = (theme: ColorTheme): string => {
209
218
  --input: ${rgba(colors.darkMuted, 0.5)};
210
219
  --input-background: ${rgba(colors.darkMuted, 0.5)};
211
220
  --ring: ${rgba(colors.primaryDarkMode, 0.5)};
212
-
221
+
222
+ /* Button stroke & secondary (theme-overridable; defaults preserve the flat look) */
223
+ --button-stroke-color: ${colors.buttonStrokeColorDark || colors.buttonStrokeColor || 'transparent'};
224
+ --button-secondary-bg: ${colors.buttonSecondaryBgDark || colors.buttonSecondaryBg || 'var(--secondary)'};
225
+ --button-secondary-foreground: ${colors.buttonSecondaryForegroundDark || colors.buttonSecondaryForeground || 'var(--secondary-foreground)'};
226
+ --button-primary-bg: ${colors.buttonPrimaryBgDark || colors.buttonPrimaryBg || 'var(--primary)'};
227
+ --button-primary-foreground: ${colors.buttonPrimaryForegroundDark || colors.buttonPrimaryForeground || 'var(--primary-foreground)'};
228
+
213
229
  --elevation-sm: 0px 0px 48px 0px rgba(0, 0, 0, 0.3);
214
230
 
215
231
  /* Charts — dark mode: slightly lighter/more saturated for contrast on dark bg */
@@ -299,24 +299,7 @@ export function generateAppTsx(selectedCodes: string[], disableDarkMode: boolean
299
299
  const selectedLangs = SUPPORTED_LANGUAGES.filter(l => selectedCodes.includes(l.code));
300
300
  const isMonolingual = selectedLangs.length === 1;
301
301
  const disableDarkModeProp = disableDarkMode ? `\n disableDarkMode={true}` : '';
302
- const isAllDefaults =
303
- selectedLangs.length === SUPPORTED_LANGUAGES.length &&
304
- selectedLangs.every(l => DEFAULT_SELECTION.includes(l.code));
305
-
306
- // Decide whether and how to render the `availableLanguages` prop on
307
- // XerticaProvider. When the user selected all 3 defaults, we can omit the
308
- // prop (the library default matches). Otherwise we emit the explicit set.
309
- const languagesArrayLiteral = selectedLangs
310
- .map(
311
- l => ` { code: '${l.code}', label: '${l.label}', shortLabel: '${l.shortLabel}' },`
312
- )
313
- .join('\n');
314
-
315
- const availableLanguagesProp = isAllDefaults
316
- ? ''
317
- : `\n availableLanguages={[
318
- ${languagesArrayLiteral}
319
- ]}`;
302
+ const availableLanguagesProp = buildAvailableLanguagesProp(selectedCodes, ' ');
320
303
 
321
304
  const monolingualBanner = isMonolingual
322
305
  ? `\n// This project is configured for a single language — the LanguageSelector
@@ -376,8 +359,65 @@ export default function App() {
376
359
  `;
377
360
  }
378
361
 
362
+ /**
363
+ * Generate the App.tsx source for a minimal "web page" project — renders the
364
+ * marketing `LandingPage` directly under `XerticaProvider`, with none of the
365
+ * router/query-client/auth machinery the full system scaffold needs (the
366
+ * landing page itself has no dependency on any of it).
367
+ */
368
+ export function generateLandingAppTsx(
369
+ selectedCodes: string[],
370
+ disableDarkMode: boolean = false
371
+ ): string {
372
+ const disableDarkModeProp = disableDarkMode ? `\n disableDarkMode={true}` : '';
373
+ const availableLanguagesProp = buildAvailableLanguagesProp(selectedCodes, ' ');
374
+
375
+ return `import React from 'react';
376
+ import { XerticaProvider } from 'xertica-ui/brand';
377
+ import { LandingPage } from 'xertica-ui/pages';
378
+
379
+ export default function App() {
380
+ return (
381
+ <XerticaProvider
382
+ useCustomTokens={true}${availableLanguagesProp}${disableDarkModeProp}
383
+ >
384
+ <LandingPage />
385
+ </XerticaProvider>
386
+ );
387
+ }
388
+ `;
389
+ }
390
+
379
391
  // ── Internal ─────────────────────────────────────────────────────────────────
380
392
 
393
+ /**
394
+ * Build the `availableLanguages` prop source for `<XerticaProvider>`. When the
395
+ * selection matches the library's default 3 languages, the prop is omitted
396
+ * entirely (the library default already matches). `indent` is the whitespace
397
+ * prefix the prop line itself should have — array items are indented one
398
+ * level deeper.
399
+ */
400
+ function buildAvailableLanguagesProp(selectedCodes: string[], indent: string): string {
401
+ const selectedLangs = SUPPORTED_LANGUAGES.filter(l => selectedCodes.includes(l.code));
402
+ const isAllDefaults =
403
+ selectedLangs.length === SUPPORTED_LANGUAGES.length &&
404
+ selectedLangs.every(l => DEFAULT_SELECTION.includes(l.code));
405
+
406
+ if (isAllDefaults) return '';
407
+
408
+ const itemIndent = `${indent} `;
409
+ const languagesArrayLiteral = selectedLangs
410
+ .map(
411
+ l =>
412
+ `${itemIndent}{ code: '${l.code}', label: '${l.label}', shortLabel: '${l.shortLabel}' },`
413
+ )
414
+ .join('\n');
415
+
416
+ return `\n${indent}availableLanguages={[
417
+ ${languagesArrayLiteral}
418
+ ${indent}]}`;
419
+ }
420
+
381
421
  /** Convert a BCP-47 code to a safe JS identifier (e.g. 'pt-BR' → 'ptBR'). */
382
422
  function toJsIdent(code: string): string {
383
423
  return code.replace(/[^a-zA-Z0-9]/g, '');