xertica-ui 2.8.0 → 2.9.7
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.
- package/CHANGELOG.md +108 -0
- package/README.md +1 -1
- package/bin/cli.ts +327 -87
- package/bin/language-config.ts +58 -18
- package/components/blocks/auth/AuthPageShell.tsx +63 -18
- package/components/blocks/auth/SocialLoginButtons.tsx +3 -3
- package/components/blocks/index.ts +1 -0
- package/components/blocks/marketing/CTASection.tsx +73 -0
- package/components/blocks/marketing/ComplianceBadgeRow.tsx +49 -0
- package/components/blocks/marketing/EvidenceTimeline.tsx +91 -0
- package/components/blocks/marketing/FeatureRow.tsx +78 -0
- package/components/blocks/marketing/Hero.tsx +125 -0
- package/components/blocks/marketing/HowItWorksSteps.tsx +90 -0
- package/components/blocks/marketing/LogoCloud.tsx +47 -0
- package/components/blocks/marketing/MarketingFooter.tsx +109 -0
- package/components/blocks/marketing/MarketingNavbar.tsx +192 -0
- package/components/blocks/marketing/PillBadge.tsx +96 -0
- package/components/blocks/marketing/SectionHeading.tsx +82 -0
- package/components/blocks/marketing/ServiceCardGrid.tsx +238 -0
- package/components/blocks/marketing/StatBand.tsx +99 -0
- package/components/blocks/marketing/TopAccentCards.tsx +91 -0
- package/components/blocks/marketing/index.ts +41 -0
- package/components/brand/index.ts +1 -0
- package/components/brand/isotype/Isotype.tsx +64 -0
- package/components/brand/isotype/IsotypeDiagonal.tsx +51 -0
- package/components/brand/isotype/IsotypeFrames.tsx +82 -0
- package/components/brand/isotype/IsotypeMini.tsx +65 -0
- package/components/brand/isotype/IsotypeTwist.tsx +68 -0
- package/components/brand/isotype/frame-variants.ts +20 -0
- package/components/brand/isotype/index.ts +9 -0
- package/components/brand/isotype/isotype-diagonal.mdx +52 -0
- package/components/brand/isotype/isotype-diagonal.stories.tsx +44 -0
- package/components/brand/isotype/isotype-diagonal.test.tsx +180 -0
- package/components/brand/isotype/isotype-frames.mdx +50 -0
- package/components/brand/isotype/isotype-frames.stories.tsx +63 -0
- package/components/brand/isotype/isotype-frames.test.tsx +92 -0
- package/components/brand/isotype/isotype-mini.mdx +61 -0
- package/components/brand/isotype/isotype-mini.stories.tsx +75 -0
- package/components/brand/isotype/isotype-mini.test.tsx +45 -0
- package/components/brand/isotype/isotype-twist.test.tsx +71 -0
- package/components/brand/isotype/isotype.mdx +61 -0
- package/components/brand/isotype/isotype.stories.tsx +74 -0
- package/components/brand/isotype/isotype.test.tsx +41 -0
- package/components/brand/isotype/mini-patterns.ts +50 -0
- package/components/brand/isotype/patterns.ts +83 -0
- package/components/brand/isotype/twist-variants.ts +20 -0
- package/components/pages/forgot-password-page/ForgotPasswordPage.tsx +3 -6
- package/components/pages/index.ts +1 -0
- package/components/pages/landing-page/LandingPage.tsx +360 -0
- package/components/pages/landing-page/index.ts +1 -0
- package/components/pages/login-page/LoginPage.tsx +3 -6
- package/components/pages/reset-password-page/ResetPasswordPage.tsx +1 -4
- package/components/pages/verify-email-page/VerifyEmailPage.tsx +2 -5
- package/components/ui/button/button.test.tsx +1 -1
- package/components/ui/button/button.tsx +7 -6
- package/components/ui/card/card.test.tsx +12 -0
- package/components/ui/card/card.tsx +5 -3
- package/components/ui/input-otp/input-otp.test.tsx +14 -1
- package/contexts/BrandColorsContext.tsx +9 -5
- package/contexts/theme-data.ts +32 -5
- package/dist/AssistantChart-BU48lxL2.js +3383 -0
- package/dist/AssistantChart-CoN6ga6Z.js +3383 -0
- package/dist/AssistantChart-DIRYJ7WY.js +3383 -0
- package/dist/AssistantChart-DOnY1ZlD.cjs +3551 -0
- package/dist/AssistantChart-DjM3qnp5.cjs +3551 -0
- package/dist/AssistantChart-hxPyE1S9.cjs +3551 -0
- package/dist/AudioPlayer-CpihsbaD.js +1278 -0
- package/dist/AudioPlayer-CvGajzMC.cjs +1282 -0
- package/dist/AudioPlayer-CvHpFqDG.cjs +1282 -0
- package/dist/AudioPlayer-D4S7GQou.js +1278 -0
- package/dist/BrandColorsContext-BNKLUVcU.js +829 -0
- package/dist/BrandColorsContext-DNZGHItQ.cjs +836 -0
- package/dist/BrandColorsContext-Ug_TZ8yn.cjs +846 -0
- package/dist/BrandColorsContext-z0O2LlZz.js +839 -0
- package/dist/CodeBlock-BkaZf-R8.cjs +223 -0
- package/dist/CodeBlock-CKu8LgbP.cjs +223 -0
- package/dist/CodeBlock-DiLS5LLI.js +221 -0
- package/dist/CodeBlock-zdylBGdZ.js +221 -0
- package/dist/CustomTooltipContent-BAR5qCQg.js +33 -0
- package/dist/CustomTooltipContent-CBLHBxX8.cjs +54 -0
- package/dist/CustomTooltipContent-CjWm3jjV.js +33 -0
- package/dist/CustomTooltipContent-DTV9MN9E.cjs +54 -0
- package/dist/EvidenceTimeline-DrRk4yqb.cjs +560 -0
- package/dist/EvidenceTimeline-l4MaV4C7.js +546 -0
- package/dist/FeatureCard-CIbBHqeY.cjs +497 -0
- package/dist/FeatureCard-DtoKPSfW.cjs +497 -0
- package/dist/FeatureCard-P4iEpBmB.js +485 -0
- package/dist/FeatureCard-e3f8bnF0.js +485 -0
- package/dist/ImageWithFallback-C1ww9Hg3.cjs +122 -0
- package/dist/ImageWithFallback-CBrkAEo3.cjs +122 -0
- package/dist/ImageWithFallback-CGk5zPH-.js +98 -0
- package/dist/ImageWithFallback-CfnoFFSP.js +98 -0
- package/dist/Isotype--fRZWwS6.js +85 -0
- package/dist/Isotype-0dpLqetB.js +85 -0
- package/dist/Isotype-B8XLEXSB.cjs +92 -0
- package/dist/Isotype-ChKwN7e-.cjs +91 -0
- package/dist/IsotypeDiagonal-CuPYPP4f.js +84 -0
- package/dist/IsotypeDiagonal-eNcOXRAc.cjs +91 -0
- package/dist/IsotypeDiagonal-oiwpXZhE.js +104 -0
- package/dist/IsotypeDiagonal-xMFoFXkb.cjs +109 -0
- package/dist/IsotypeFrames-BcWtyAWp.cjs +83 -0
- package/dist/IsotypeFrames-BnvSJKiH.cjs +73 -0
- package/dist/IsotypeFrames-iDRTRuIu.js +79 -0
- package/dist/IsotypeFrames-qoXOvOJt.js +69 -0
- package/dist/IsotypeMini-CQtWVo3h.js +126 -0
- package/dist/IsotypeMini-Cu_sW5yN.cjs +134 -0
- package/dist/IsotypeTwist-BTdNL4iV.js +106 -0
- package/dist/IsotypeTwist-DvsUgZs_.cjs +115 -0
- package/dist/LanguageContext-B1aOXO-K.js +1987 -0
- package/dist/LanguageContext-BP0k7AzI.js +1993 -0
- package/dist/LanguageContext-CChcIHIG.cjs +1998 -0
- package/dist/LanguageContext-ubC7TSs_.cjs +1992 -0
- package/dist/LanguageSelector-BLFPXGo8.cjs +48 -0
- package/dist/LanguageSelector-CYRzWkRZ.cjs +48 -0
- package/dist/LanguageSelector-CyHjZgC4.cjs +48 -0
- package/dist/LanguageSelector-DE8lIySO.js +46 -0
- package/dist/LanguageSelector-DUr1hjBW.js +46 -0
- package/dist/LanguageSelector-DjbWIKWC.js +46 -0
- package/dist/LogoCloud-C_uMKVNg.cjs +513 -0
- package/dist/LogoCloud-DJsMPNPh.js +500 -0
- package/dist/MarketingFooter-B_ycEdTJ.cjs +727 -0
- package/dist/MarketingFooter-Bhx-2Vlr.cjs +727 -0
- package/dist/MarketingFooter-Br1MGK9e.js +699 -0
- package/dist/MarketingFooter-BwE1vmeX.cjs +700 -0
- package/dist/MarketingFooter-CsZ1_xL9.js +709 -0
- package/dist/MarketingFooter-DCwf78Q4.cjs +716 -0
- package/dist/MarketingFooter-KH2r-OOL.js +709 -0
- package/dist/MarketingFooter-nB7G7gQ5.js +682 -0
- package/dist/SectionHeading-DEeOKcAd.cjs +857 -0
- package/dist/SectionHeading-DMNObcwm.js +838 -0
- package/dist/ThemeToggle--CGJjQJv.cjs +219 -0
- package/dist/ThemeToggle-Bn_7Pmfe.js +215 -0
- package/dist/ThemeToggle-CoL8Ady7.js +215 -0
- package/dist/ThemeToggle-D2Wzm5bn.cjs +219 -0
- package/dist/VerifyEmailPage-90lK6pP4.js +3258 -0
- package/dist/VerifyEmailPage-BJX1Rter.cjs +3320 -0
- package/dist/VerifyEmailPage-BSWvOgry.js +3310 -0
- package/dist/VerifyEmailPage-CDqIkhx-.js +3224 -0
- package/dist/VerifyEmailPage-Crxje3ZB.js +3323 -0
- package/dist/VerifyEmailPage-D2ShbuEN.cjs +3333 -0
- package/dist/VerifyEmailPage-DEBZXQ7c.cjs +3310 -0
- package/dist/VerifyEmailPage-DGaX-jZv.cjs +3268 -0
- package/dist/VerifyEmailPage-ZtOPkgOA.cjs +3234 -0
- package/dist/VerifyEmailPage-s927GSiR.js +3300 -0
- package/dist/XerticaOrbe-BHex09xs.js +1925 -0
- package/dist/XerticaOrbe-BKW3LJEz.js +1925 -0
- package/dist/XerticaOrbe-Br2i99U_.cjs +1927 -0
- package/dist/XerticaOrbe-kjFmuyx-.cjs +1927 -0
- package/dist/XerticaProvider-Bi5lKC9N.js +44 -0
- package/dist/XerticaProvider-BrPMVhiv.js +44 -0
- package/dist/XerticaProvider-CnX5kt5W.cjs +46 -0
- package/dist/XerticaProvider-DEKNJTlN.js +44 -0
- package/dist/XerticaProvider-X_wavDYA.cjs +46 -0
- package/dist/XerticaProvider-b3n_oL8w.cjs +46 -0
- package/dist/alert-dialog--qdlmB5i.cjs +872 -0
- package/dist/alert-dialog-C48TOdYU.cjs +872 -0
- package/dist/alert-dialog-CEPpnpXt.js +819 -0
- package/dist/alert-dialog-NjflitDa.js +819 -0
- package/dist/assistant.cjs.js +2 -2
- package/dist/assistant.es.js +2 -2
- package/dist/avatar-CtEKgg7s.cjs +77 -0
- package/dist/avatar-D03MNQxs.js +54 -0
- package/dist/avatar-Df7KgSvs.js +54 -0
- package/dist/avatar-Gy0_Xu9i.cjs +77 -0
- package/dist/blocks.cjs.js +33 -18
- package/dist/blocks.es.js +2 -2
- package/dist/brand.cjs.js +110 -4
- package/dist/brand.es.js +98 -4
- package/dist/breadcrumb-BGO5PZPG.js +90 -0
- package/dist/breadcrumb-BvGAY4ne.cjs +98 -0
- package/dist/breadcrumb-CU-punra.js +90 -0
- package/dist/breadcrumb-DjV9wfX1.cjs +98 -0
- package/dist/button-B05czY_8.js +62 -0
- package/dist/button-B3SE1liJ.js +62 -0
- package/dist/button-BMDlWZR8.cjs +85 -0
- package/dist/button-DVhloDtr.cjs +85 -0
- package/dist/cli.js +280 -62
- package/dist/components/blocks/auth/AuthPageShell.d.ts +21 -5
- package/dist/components/blocks/index.d.ts +1 -0
- package/dist/components/blocks/marketing/CTASection.d.ts +28 -0
- package/dist/components/blocks/marketing/ComplianceBadgeRow.d.ts +23 -0
- package/dist/components/blocks/marketing/EvidenceTimeline.d.ts +26 -0
- package/dist/components/blocks/marketing/FeatureRow.d.ts +25 -0
- package/dist/components/blocks/marketing/Hero.d.ts +35 -0
- package/dist/components/blocks/marketing/HowItWorksSteps.d.ts +29 -0
- package/dist/components/blocks/marketing/LogoCloud.d.ts +22 -0
- package/dist/components/blocks/marketing/MarketingFooter.d.ts +42 -0
- package/dist/components/blocks/marketing/MarketingNavbar.d.ts +47 -0
- package/dist/components/blocks/marketing/PillBadge.d.ts +21 -0
- package/dist/components/blocks/marketing/SectionHeading.d.ts +23 -0
- package/dist/components/blocks/marketing/ServiceCardGrid.d.ts +65 -0
- package/dist/components/blocks/marketing/StatBand.d.ts +25 -0
- package/dist/components/blocks/marketing/TopAccentCards.d.ts +29 -0
- package/dist/components/blocks/marketing/index.d.ts +28 -0
- package/dist/components/brand/index.d.ts +1 -0
- package/dist/components/brand/isotype/Isotype.d.ts +27 -0
- package/dist/components/brand/isotype/IsotypeDiagonal.d.ts +19 -0
- package/dist/components/brand/isotype/IsotypeFrames.d.ts +21 -0
- package/dist/components/brand/isotype/IsotypeMini.d.ts +26 -0
- package/dist/components/brand/isotype/IsotypeTwist.d.ts +22 -0
- package/dist/components/brand/isotype/frame-variants.d.ts +11 -0
- package/dist/components/brand/isotype/index.d.ts +9 -0
- package/dist/components/brand/isotype/mini-patterns.d.ts +25 -0
- package/dist/components/brand/isotype/patterns.d.ts +42 -0
- package/dist/components/brand/isotype/twist-variants.d.ts +11 -0
- package/dist/components/pages/forgot-password-page/ForgotPasswordPage.d.ts +2 -2
- package/dist/components/pages/index.d.ts +1 -0
- package/dist/components/pages/landing-page/LandingPage.d.ts +18 -0
- package/dist/components/pages/landing-page/index.d.ts +1 -0
- package/dist/components/pages/login-page/LoginPage.d.ts +2 -2
- package/dist/components/pages/verify-email-page/VerifyEmailPage.d.ts +1 -1
- package/dist/components/ui/card/card.d.ts +3 -1
- package/dist/contexts/theme-data.d.ts +6 -0
- package/dist/dropdown-menu-ChQa9zW3.cjs +225 -0
- package/dist/dropdown-menu-DRvnsQAt.cjs +225 -0
- package/dist/dropdown-menu-DUk81i5Y.js +190 -0
- package/dist/dropdown-menu-NlUHhVmK.js +190 -0
- package/dist/hooks.cjs.js +2 -2
- package/dist/hooks.es.js +2 -2
- package/dist/index.cjs.js +57 -41
- package/dist/index.es.js +25 -25
- package/dist/input-Csp_Metb.cjs +91 -0
- package/dist/input-DVRwGVLx.js +65 -0
- package/dist/input-Dqyj7Hdw.cjs +91 -0
- package/dist/input-dOgrFQ-3.js +65 -0
- package/dist/layout.cjs.js +1 -1
- package/dist/layout.es.js +1 -1
- package/dist/media.cjs.js +1 -1
- package/dist/media.es.js +1 -1
- package/dist/pages.cjs.js +2 -1
- package/dist/pages.es.js +1 -1
- package/dist/rich-text-editor-7K7UjLJN.cjs +2968 -0
- package/dist/rich-text-editor-B3jLP2bm.cjs +2968 -0
- package/dist/rich-text-editor-BntMVQsB.js +2894 -0
- package/dist/rich-text-editor-Diz_onyB.js +2894 -0
- package/dist/rich-text-editor-RWvK4hd3.cjs +2968 -0
- package/dist/rich-text-editor-gauEkzPM.js +2894 -0
- package/dist/select-B6PygS38.cjs +161 -0
- package/dist/select-BD763J5Y.cjs +161 -0
- package/dist/select-QJDKZITN.js +130 -0
- package/dist/select-q7aDfuPn.js +130 -0
- package/dist/sidebar-Bkk1YAsD.cjs +1154 -0
- package/dist/sidebar-CuzYeOSz.cjs +1154 -0
- package/dist/sidebar-CwlW3LXE.js +1151 -0
- package/dist/sidebar-DNkf-Ug6.js +1151 -0
- package/dist/sidebar-DaS3fplw.cjs +1154 -0
- package/dist/sidebar-FDCY42oP.js +1151 -0
- package/dist/skeleton-BtBwJ39W.js +79 -0
- package/dist/skeleton-CJyg0eJ1.cjs +88 -0
- package/dist/skeleton-D8WaauK0.cjs +88 -0
- package/dist/skeleton-DBYtjaZW.cjs +88 -0
- package/dist/skeleton-DY_lSFWf.js +79 -0
- package/dist/skeleton-Df65Ox10.js +79 -0
- package/dist/slider-BKV_vvsh.cjs +78 -0
- package/dist/slider-B_lUjFNa.cjs +78 -0
- package/dist/slider-CtBpIaU4.js +56 -0
- package/dist/slider-KgWmSJbx.js +56 -0
- package/dist/tooltip-BPttuPxU.js +48 -0
- package/dist/tooltip-CIKRzQqE.cjs +72 -0
- package/dist/tooltip-CoDByjE_.cjs +72 -0
- package/dist/tooltip-_MAwsiOL.js +48 -0
- package/dist/ui.cjs.js +13 -13
- package/dist/ui.es.js +13 -13
- package/dist/xertica-assistant-B1xAl2Vn.js +2173 -0
- package/dist/xertica-assistant-BBUMaUXw.js +2173 -0
- package/dist/xertica-assistant-CWuBwfzt.cjs +2180 -0
- package/dist/xertica-assistant-D2hlwiEP.js +2173 -0
- package/dist/xertica-assistant-DN2J_sQQ.cjs +2180 -0
- package/dist/xertica-assistant-DdYS6WXT.cjs +2180 -0
- package/dist/xertica-ui.css +1 -1
- package/llms-compact.txt +1 -1
- package/llms.txt +1 -1
- package/package.json +4 -2
- package/styles/xertica/base.css +8 -0
- package/styles/xertica/tokens.css +1 -0
- package/templates/package.json +1 -1
- package/templates/src/app/components/AuthGuard.tsx +6 -0
- package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +1 -4
- package/templates/src/features/auth/ui/LoginContent.tsx +1 -4
- package/templates/src/features/auth/ui/ResetPasswordContent.tsx +1 -4
- package/templates/src/features/auth/ui/VerifyEmailContent.tsx +1 -4
- package/templates/src/locales/en/pages/landing.json +175 -0
- package/templates/src/locales/es/pages/landing.json +175 -0
- package/templates/src/locales/pt-BR/pages/landing.json +175 -0
- package/templates/src/pages/LandingPage.tsx +349 -0
- package/templates/src/styles/xertica/tokens.css +1 -0
package/dist/cli.js
CHANGED
|
@@ -69,12 +69,12 @@ var colorThemes = [
|
|
|
69
69
|
darkCard: "#1E1E1E",
|
|
70
70
|
darkMuted: "#26241f",
|
|
71
71
|
darkBorder: "#38352c",
|
|
72
|
-
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
gradientStartDark: "#
|
|
77
|
-
gradientEndDark: "#
|
|
72
|
+
// Flat fill, same value on every stop — this theme uses solid ink
|
|
73
|
+
// colors, never gradients (Negro Xertica, matching sidebar/secondary-button).
|
|
74
|
+
gradientStart: "#1E1E1E",
|
|
75
|
+
gradientEnd: "#1E1E1E",
|
|
76
|
+
gradientStartDark: "#1E1E1E",
|
|
77
|
+
gradientEndDark: "#1E1E1E",
|
|
78
78
|
chart1: "#3D63AC",
|
|
79
79
|
// Azul
|
|
80
80
|
chart2: "#1899AF",
|
|
@@ -91,11 +91,22 @@ var colorThemes = [
|
|
|
91
91
|
// Marfim — cards, header, assistant panel
|
|
92
92
|
inputBorderColor: "rgba(30, 30, 30, 0.4)",
|
|
93
93
|
// Negro Xertica stroke — form fields only
|
|
94
|
+
outlineBorderColor: "rgba(30, 30, 30, 0.4)",
|
|
95
|
+
// Negro Xertica stroke — Button `outline` variant only
|
|
96
|
+
successColor: "#2E8B5A",
|
|
97
|
+
// Verde
|
|
98
|
+
warningColor: "#E37744",
|
|
99
|
+
// Naranja
|
|
100
|
+
infoColor: "#3D63AC",
|
|
101
|
+
// Azul
|
|
102
|
+
destructiveColor: "#DE5B48",
|
|
103
|
+
// Rojo Coral
|
|
94
104
|
buttonRadius: "9999px",
|
|
95
|
-
buttonStrokeWidth: "
|
|
105
|
+
buttonStrokeWidth: "1px",
|
|
96
106
|
buttonStrokeColor: "#1E1E1E",
|
|
97
107
|
buttonStrokeColorDark: "#F2EDD8",
|
|
98
108
|
// Crema
|
|
109
|
+
buttonFontWeight: "400",
|
|
99
110
|
buttonSecondaryBg: "#1E1E1E",
|
|
100
111
|
buttonSecondaryBgDark: "#1E1E1E",
|
|
101
112
|
buttonSecondaryForeground: "#FFFEF8",
|
|
@@ -832,14 +843,7 @@ function generateAppTsx(selectedCodes, disableDarkMode = false) {
|
|
|
832
843
|
const isMonolingual = selectedLangs.length === 1;
|
|
833
844
|
const disableDarkModeProp = disableDarkMode ? `
|
|
834
845
|
disableDarkMode={true}` : "";
|
|
835
|
-
const
|
|
836
|
-
const languagesArrayLiteral = selectedLangs.map(
|
|
837
|
-
(l) => ` { code: '${l.code}', label: '${l.label}', shortLabel: '${l.shortLabel}' },`
|
|
838
|
-
).join("\n");
|
|
839
|
-
const availableLanguagesProp = isAllDefaults ? "" : `
|
|
840
|
-
availableLanguages={[
|
|
841
|
-
${languagesArrayLiteral}
|
|
842
|
-
]}`;
|
|
846
|
+
const availableLanguagesProp = buildAvailableLanguagesProp(selectedCodes, " ");
|
|
843
847
|
const monolingualBanner = isMonolingual ? `
|
|
844
848
|
// This project is configured for a single language \u2014 the LanguageSelector
|
|
845
849
|
// auto-hides because there is nothing to switch to.` : "";
|
|
@@ -895,6 +899,38 @@ export default function App() {
|
|
|
895
899
|
}
|
|
896
900
|
`;
|
|
897
901
|
}
|
|
902
|
+
function generateLandingAppTsx(selectedCodes, disableDarkMode = false) {
|
|
903
|
+
const disableDarkModeProp = disableDarkMode ? `
|
|
904
|
+
disableDarkMode={true}` : "";
|
|
905
|
+
const availableLanguagesProp = buildAvailableLanguagesProp(selectedCodes, " ");
|
|
906
|
+
return `import React from 'react';
|
|
907
|
+
import { XerticaProvider } from 'xertica-ui/brand';
|
|
908
|
+
import { LandingPage } from '../pages/LandingPage';
|
|
909
|
+
|
|
910
|
+
export default function App() {
|
|
911
|
+
return (
|
|
912
|
+
<XerticaProvider
|
|
913
|
+
useCustomTokens={true}${availableLanguagesProp}${disableDarkModeProp}
|
|
914
|
+
>
|
|
915
|
+
<LandingPage />
|
|
916
|
+
</XerticaProvider>
|
|
917
|
+
);
|
|
918
|
+
}
|
|
919
|
+
`;
|
|
920
|
+
}
|
|
921
|
+
function buildAvailableLanguagesProp(selectedCodes, indent) {
|
|
922
|
+
const selectedLangs = SUPPORTED_LANGUAGES.filter((l) => selectedCodes.includes(l.code));
|
|
923
|
+
const isAllDefaults = selectedLangs.length === SUPPORTED_LANGUAGES.length && selectedLangs.every((l) => DEFAULT_SELECTION.includes(l.code));
|
|
924
|
+
if (isAllDefaults) return "";
|
|
925
|
+
const itemIndent = `${indent} `;
|
|
926
|
+
const languagesArrayLiteral = selectedLangs.map(
|
|
927
|
+
(l) => `${itemIndent}{ code: '${l.code}', label: '${l.label}', shortLabel: '${l.shortLabel}' },`
|
|
928
|
+
).join("\n");
|
|
929
|
+
return `
|
|
930
|
+
${indent}availableLanguages={[
|
|
931
|
+
${languagesArrayLiteral}
|
|
932
|
+
${indent}]}`;
|
|
933
|
+
}
|
|
898
934
|
function toJsIdent(code) {
|
|
899
935
|
return code.replace(/[^a-zA-Z0-9]/g, "");
|
|
900
936
|
}
|
|
@@ -1112,12 +1148,156 @@ export function TemplatePage() {
|
|
|
1112
1148
|
}
|
|
1113
1149
|
`;
|
|
1114
1150
|
}
|
|
1151
|
+
async function copyPackageJson(templatesDir, targetDir) {
|
|
1152
|
+
const pkgTemplatePath = path2.join(templatesDir, "package.json");
|
|
1153
|
+
if (await fs2.pathExists(pkgTemplatePath)) {
|
|
1154
|
+
const pkgContent = await fs2.readJson(pkgTemplatePath);
|
|
1155
|
+
const projectName = path2.basename(targetDir) || "my-xertica-app";
|
|
1156
|
+
pkgContent.name = projectName.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
1157
|
+
await fs2.writeJson(path2.join(targetDir, "package.json"), pkgContent, { spaces: 2 });
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
async function initPageProject(targetDir, templatesDir) {
|
|
1161
|
+
const response = await prompts([
|
|
1162
|
+
{
|
|
1163
|
+
type: "multiselect",
|
|
1164
|
+
name: "languages",
|
|
1165
|
+
message: "Which languages should the page support?",
|
|
1166
|
+
instructions: false,
|
|
1167
|
+
hint: "Select at least 1. Single-language apps auto-hide the LanguageSelector.",
|
|
1168
|
+
min: 1,
|
|
1169
|
+
choices: SUPPORTED_LANGUAGES.map((l) => ({
|
|
1170
|
+
title: l.label,
|
|
1171
|
+
value: l.code,
|
|
1172
|
+
selected: true
|
|
1173
|
+
}))
|
|
1174
|
+
},
|
|
1175
|
+
{
|
|
1176
|
+
type: "select",
|
|
1177
|
+
name: "theme",
|
|
1178
|
+
message: "Select the default color theme for your project:",
|
|
1179
|
+
choices: colorThemes.map((t) => ({
|
|
1180
|
+
title: t.name,
|
|
1181
|
+
description: t.description,
|
|
1182
|
+
value: t.id
|
|
1183
|
+
})),
|
|
1184
|
+
initial: 0
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
type: "confirm",
|
|
1188
|
+
name: "install",
|
|
1189
|
+
message: "Install dependencies automatically?",
|
|
1190
|
+
initial: true
|
|
1191
|
+
}
|
|
1192
|
+
]);
|
|
1193
|
+
if (!response.languages || !response.theme) return;
|
|
1194
|
+
const spinner = ora("Initializing project...").start();
|
|
1195
|
+
try {
|
|
1196
|
+
await fs2.ensureDir(targetDir);
|
|
1197
|
+
const selectedLanguages = Array.isArray(response.languages) && response.languages.length > 0 ? response.languages : DEFAULT_SELECTION;
|
|
1198
|
+
const rootFilesToCopy = [
|
|
1199
|
+
"index.html",
|
|
1200
|
+
"vite.config.ts",
|
|
1201
|
+
"tsconfig.json",
|
|
1202
|
+
"tsconfig.node.json",
|
|
1203
|
+
"postcss.config.js",
|
|
1204
|
+
"vite-env.d.ts",
|
|
1205
|
+
"eslint.config.js",
|
|
1206
|
+
".gitignore",
|
|
1207
|
+
".prettierrc"
|
|
1208
|
+
];
|
|
1209
|
+
for (const file of rootFilesToCopy) {
|
|
1210
|
+
const srcPath = path2.join(templatesDir, file);
|
|
1211
|
+
if (await fs2.pathExists(srcPath)) {
|
|
1212
|
+
await fs2.copy(srcPath, path2.join(targetDir, file));
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
await copyPackageJson(templatesDir, targetDir);
|
|
1216
|
+
await fs2.copy(
|
|
1217
|
+
path2.join(templatesDir, "src", "main.tsx"),
|
|
1218
|
+
path2.join(targetDir, "src", "main.tsx")
|
|
1219
|
+
);
|
|
1220
|
+
await fs2.ensureDir(path2.join(targetDir, "src", "app"));
|
|
1221
|
+
await fs2.writeFile(
|
|
1222
|
+
path2.join(targetDir, "src", "app", "App.tsx"),
|
|
1223
|
+
generateLandingAppTsx(selectedLanguages)
|
|
1224
|
+
);
|
|
1225
|
+
await fs2.writeFile(
|
|
1226
|
+
path2.join(targetDir, "src", "i18n.ts"),
|
|
1227
|
+
generateI18nFile(selectedLanguages)
|
|
1228
|
+
);
|
|
1229
|
+
await syncLocaleFiles(templatesDir, targetDir, selectedLanguages, { pruneOthers: true });
|
|
1230
|
+
await writeLanguagesConfig(targetDir, selectedLanguages);
|
|
1231
|
+
await writeXerticaConfig(targetDir, {
|
|
1232
|
+
hasAssistant: false,
|
|
1233
|
+
disableDarkMode: false,
|
|
1234
|
+
themeId: response.theme,
|
|
1235
|
+
projectType: "page"
|
|
1236
|
+
});
|
|
1237
|
+
await fs2.ensureDir(path2.join(targetDir, "src", "pages"));
|
|
1238
|
+
await fs2.copy(
|
|
1239
|
+
path2.join(templatesDir, "src", "pages", "LandingPage.tsx"),
|
|
1240
|
+
path2.join(targetDir, "src", "pages", "LandingPage.tsx")
|
|
1241
|
+
);
|
|
1242
|
+
const selectedTheme = colorThemes.find((t) => t.id === response.theme) || colorThemes[0];
|
|
1243
|
+
const tokensDir = path2.join(targetDir, "src", "styles", "xertica");
|
|
1244
|
+
await fs2.ensureDir(tokensDir);
|
|
1245
|
+
await fs2.copy(
|
|
1246
|
+
path2.join(templatesDir, "src", "styles", "index.css"),
|
|
1247
|
+
path2.join(targetDir, "src", "styles", "index.css")
|
|
1248
|
+
);
|
|
1249
|
+
await fs2.writeFile(path2.join(tokensDir, "tokens.css"), generateTokensCss(selectedTheme));
|
|
1250
|
+
spinner.succeed("Project initialized successfully!");
|
|
1251
|
+
if (response.install) {
|
|
1252
|
+
const installSpinner = ora("Installing dependencies...").start();
|
|
1253
|
+
await execa("npm", ["install"], { cwd: targetDir });
|
|
1254
|
+
installSpinner.succeed("Dependencies installed!");
|
|
1255
|
+
}
|
|
1256
|
+
console.log(chalk.green("\n\u2705 Done! Your Xertica UI landing page is ready."));
|
|
1257
|
+
console.log(chalk.cyan(`
|
|
1258
|
+
cd ${path2.relative(process.cwd(), targetDir) || "."}`));
|
|
1259
|
+
if (!response.install) {
|
|
1260
|
+
console.log(chalk.cyan(" npm install"));
|
|
1261
|
+
}
|
|
1262
|
+
console.log(chalk.cyan(" npm run dev"));
|
|
1263
|
+
console.log();
|
|
1264
|
+
console.log(chalk.gray(" Edit the demo content in src/pages/LandingPage.tsx"));
|
|
1265
|
+
console.log(chalk.gray(" Customize the theme in src/styles/xertica/tokens.css"));
|
|
1266
|
+
console.log(chalk.gray(" To change the theme or languages later: npx xertica-ui update"));
|
|
1267
|
+
} catch (error) {
|
|
1268
|
+
spinner.fail("Failed to initialize project");
|
|
1269
|
+
console.error(error);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1115
1272
|
var program = new Command();
|
|
1116
1273
|
program.name("xertica-ui").description("CLI to initialize Xertica UI projects").version(pkgJson.version);
|
|
1117
1274
|
program.command("init").description("Initialize a new Xertica UI project").argument("[directory]", "Directory to initialize in", ".").action(async (directory) => {
|
|
1118
1275
|
const targetDir = path2.resolve(process.cwd(), directory);
|
|
1119
1276
|
const templatesDir = path2.resolve(__dirname, "../templates");
|
|
1120
1277
|
console.log(chalk.blue(`\u{1F680} Welcome to Xertica UI CLI! ${chalk.dim(`v${pkgJson.version}`)}`));
|
|
1278
|
+
const { projectType } = await prompts({
|
|
1279
|
+
type: "select",
|
|
1280
|
+
name: "projectType",
|
|
1281
|
+
message: "What do you want to create?",
|
|
1282
|
+
choices: [
|
|
1283
|
+
{
|
|
1284
|
+
title: "Full system",
|
|
1285
|
+
description: "Auth, sidebar, pages, i18n \u2014 the current full scaffold",
|
|
1286
|
+
value: "system"
|
|
1287
|
+
},
|
|
1288
|
+
{
|
|
1289
|
+
title: "Web page",
|
|
1290
|
+
description: "Just the marketing landing page \u2014 pick a theme and languages, done",
|
|
1291
|
+
value: "page"
|
|
1292
|
+
}
|
|
1293
|
+
],
|
|
1294
|
+
initial: 0
|
|
1295
|
+
});
|
|
1296
|
+
if (!projectType) return;
|
|
1297
|
+
if (projectType === "page") {
|
|
1298
|
+
await initPageProject(targetDir, templatesDir);
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1121
1301
|
const response = await prompts([
|
|
1122
1302
|
{
|
|
1123
1303
|
type: "multiselect",
|
|
@@ -1206,13 +1386,7 @@ program.command("init").description("Initialize a new Xertica UI project").argum
|
|
|
1206
1386
|
await fs2.copy(srcPath, path2.join(targetDir, file));
|
|
1207
1387
|
}
|
|
1208
1388
|
}
|
|
1209
|
-
|
|
1210
|
-
if (await fs2.pathExists(pkgTemplatePath)) {
|
|
1211
|
-
const pkgContent = await fs2.readJson(pkgTemplatePath);
|
|
1212
|
-
const projectName = path2.basename(targetDir) || "my-xertica-app";
|
|
1213
|
-
pkgContent.name = projectName.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
1214
|
-
await fs2.writeJson(path2.join(targetDir, "package.json"), pkgContent, { spaces: 2 });
|
|
1215
|
-
}
|
|
1389
|
+
await copyPackageJson(templatesDir, targetDir);
|
|
1216
1390
|
await fs2.copy(
|
|
1217
1391
|
path2.join(templatesDir, "src", "main.tsx"),
|
|
1218
1392
|
path2.join(targetDir, "src", "main.tsx")
|
|
@@ -1238,7 +1412,12 @@ program.command("init").description("Initialize a new Xertica UI project").argum
|
|
|
1238
1412
|
);
|
|
1239
1413
|
await syncLocaleFiles(templatesDir, targetDir, selectedLanguages, { pruneOthers: true });
|
|
1240
1414
|
await writeLanguagesConfig(targetDir, selectedLanguages);
|
|
1241
|
-
await writeXerticaConfig(targetDir, {
|
|
1415
|
+
await writeXerticaConfig(targetDir, {
|
|
1416
|
+
hasAssistant,
|
|
1417
|
+
disableDarkMode,
|
|
1418
|
+
themeId: response.theme,
|
|
1419
|
+
projectType: "system"
|
|
1420
|
+
});
|
|
1242
1421
|
await fs2.ensureDir(path2.join(targetDir, "src", "app", "context"));
|
|
1243
1422
|
await fs2.copy(
|
|
1244
1423
|
path2.join(templatesDir, "src", "app", "context", "AuthContext.tsx"),
|
|
@@ -1362,6 +1541,8 @@ program.command("update").alias("update-theme").description("Update theme or pro
|
|
|
1362
1541
|
const targetDir = process.cwd();
|
|
1363
1542
|
console.log(chalk.blue(`\u{1F527} Xertica UI CLI ${chalk.dim(`v${pkgJson.version}`)}`));
|
|
1364
1543
|
const currentConfig = await readXerticaConfig(targetDir);
|
|
1544
|
+
const projectType = currentConfig?.projectType ?? "system";
|
|
1545
|
+
const isPageProject = projectType === "page";
|
|
1365
1546
|
const { updateType } = await prompts({
|
|
1366
1547
|
type: "select",
|
|
1367
1548
|
name: "updateType",
|
|
@@ -1377,11 +1558,13 @@ program.command("update").alias("update-theme").description("Update theme or pro
|
|
|
1377
1558
|
description: "Add or remove supported languages (pt-BR, en, es, \u2026)",
|
|
1378
1559
|
value: "languages"
|
|
1379
1560
|
},
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1561
|
+
...isPageProject ? [] : [
|
|
1562
|
+
{
|
|
1563
|
+
title: "Assistant",
|
|
1564
|
+
description: currentConfig?.hasAssistant ? "Remove the AI Assistant from your project" : "Add the AI Assistant to your project",
|
|
1565
|
+
value: "assistant"
|
|
1566
|
+
}
|
|
1567
|
+
],
|
|
1385
1568
|
{
|
|
1386
1569
|
title: "Dark Mode",
|
|
1387
1570
|
description: currentConfig?.disableDarkMode ? "Enable dark mode support in your project" : "Disable dark mode support in your project",
|
|
@@ -1389,7 +1572,7 @@ program.command("update").alias("update-theme").description("Update theme or pro
|
|
|
1389
1572
|
},
|
|
1390
1573
|
{
|
|
1391
1574
|
title: "Project files",
|
|
1392
|
-
description: "Update app shell, shared, features and pages to a specific version",
|
|
1575
|
+
description: isPageProject ? "Update the app shell and landing page to a specific version" : "Update app shell, shared, features and pages to a specific version",
|
|
1393
1576
|
value: "project"
|
|
1394
1577
|
}
|
|
1395
1578
|
]
|
|
@@ -1510,7 +1693,7 @@ ${summary.join("\n")}
|
|
|
1510
1693
|
await fs2.writeFile(path2.join(targetDir, "src", "i18n.ts"), generateI18nFile(newCodes));
|
|
1511
1694
|
await fs2.writeFile(
|
|
1512
1695
|
path2.join(targetDir, "src", "app", "App.tsx"),
|
|
1513
|
-
generateAppTsx(newCodes, currentConfig?.disableDarkMode ?? false)
|
|
1696
|
+
isPageProject ? generateLandingAppTsx(newCodes, currentConfig?.disableDarkMode ?? false) : generateAppTsx(newCodes, currentConfig?.disableDarkMode ?? false)
|
|
1514
1697
|
);
|
|
1515
1698
|
await writeLanguagesConfig(targetDir, newCodes);
|
|
1516
1699
|
spinner2.succeed("Languages updated successfully!");
|
|
@@ -1672,7 +1855,7 @@ AI Assistant is currently: ${currentlyHas ? chalk.green("enabled") : chalk.red("
|
|
|
1672
1855
|
const selectedCodes = persistedCodes && persistedCodes.length > 0 ? persistedCodes : DEFAULT_SELECTION;
|
|
1673
1856
|
await fs2.writeFile(
|
|
1674
1857
|
path2.join(targetDir, "src", "app", "App.tsx"),
|
|
1675
|
-
generateAppTsx(selectedCodes, newDisableDarkMode)
|
|
1858
|
+
isPageProject ? generateLandingAppTsx(selectedCodes, newDisableDarkMode) : generateAppTsx(selectedCodes, newDisableDarkMode)
|
|
1676
1859
|
);
|
|
1677
1860
|
spinner2.succeed(
|
|
1678
1861
|
newDisableDarkMode ? "Dark mode disabled successfully! (Locked to Light Mode)" : "Dark mode enabled successfully!"
|
|
@@ -1712,7 +1895,20 @@ AI Assistant is currently: ${currentlyHas ? chalk.green("enabled") : chalk.red("
|
|
|
1712
1895
|
type: "multiselect",
|
|
1713
1896
|
name: "filesToUpdate",
|
|
1714
1897
|
message: "Select which parts of the project to update:",
|
|
1715
|
-
choices: [
|
|
1898
|
+
choices: isPageProject ? [
|
|
1899
|
+
{
|
|
1900
|
+
title: "App shell + landing page",
|
|
1901
|
+
description: "App.tsx and the LandingPage re-export",
|
|
1902
|
+
value: "app",
|
|
1903
|
+
selected: true
|
|
1904
|
+
},
|
|
1905
|
+
{
|
|
1906
|
+
title: "Root config files",
|
|
1907
|
+
description: "vite.config.ts, tsconfig.json, etc.",
|
|
1908
|
+
value: "config",
|
|
1909
|
+
selected: false
|
|
1910
|
+
}
|
|
1911
|
+
] : [
|
|
1716
1912
|
{
|
|
1717
1913
|
title: "App shell (src/app/)",
|
|
1718
1914
|
description: "App.tsx, AppLayout.tsx",
|
|
@@ -1764,11 +1960,6 @@ AI Assistant is currently: ${currentlyHas ? chalk.green("enabled") : chalk.red("
|
|
|
1764
1960
|
spinner.text = "Copying updated files...";
|
|
1765
1961
|
const updatedTemplatesDir = path2.join(targetDir, "node_modules", "xertica-ui", "templates");
|
|
1766
1962
|
if (filesToUpdate.includes("app")) {
|
|
1767
|
-
await fs2.copy(
|
|
1768
|
-
path2.join(updatedTemplatesDir, "src", "app", "components", "AppLayout.tsx"),
|
|
1769
|
-
path2.join(targetDir, "src", "app", "components", "AppLayout.tsx"),
|
|
1770
|
-
{ overwrite: true }
|
|
1771
|
-
);
|
|
1772
1963
|
const persistedCodes = await readLanguagesConfig(targetDir);
|
|
1773
1964
|
let selectedCodes = persistedCodes ?? [];
|
|
1774
1965
|
if (selectedCodes.length === 0) {
|
|
@@ -1783,31 +1974,58 @@ AI Assistant is currently: ${currentlyHas ? chalk.green("enabled") : chalk.red("
|
|
|
1783
1974
|
await writeLanguagesConfig(targetDir, selectedCodes);
|
|
1784
1975
|
}
|
|
1785
1976
|
const projectConfig = await readXerticaConfig(targetDir);
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1977
|
+
if (isPageProject) {
|
|
1978
|
+
await fs2.writeFile(
|
|
1979
|
+
path2.join(targetDir, "src", "app", "App.tsx"),
|
|
1980
|
+
generateLandingAppTsx(selectedCodes, projectConfig?.disableDarkMode ?? false)
|
|
1981
|
+
);
|
|
1982
|
+
await fs2.writeFile(
|
|
1983
|
+
path2.join(targetDir, "src", "i18n.ts"),
|
|
1984
|
+
generateI18nFile(selectedCodes)
|
|
1985
|
+
);
|
|
1986
|
+
await syncLocaleFiles(updatedTemplatesDir, targetDir, selectedCodes, {
|
|
1987
|
+
pruneOthers: true
|
|
1988
|
+
});
|
|
1989
|
+
await fs2.copy(
|
|
1990
|
+
path2.join(updatedTemplatesDir, "src", "pages", "LandingPage.tsx"),
|
|
1991
|
+
path2.join(targetDir, "src", "pages", "LandingPage.tsx"),
|
|
1992
|
+
{ overwrite: true }
|
|
1993
|
+
);
|
|
1994
|
+
} else {
|
|
1995
|
+
await fs2.copy(
|
|
1996
|
+
path2.join(updatedTemplatesDir, "src", "app", "components", "AppLayout.tsx"),
|
|
1997
|
+
path2.join(targetDir, "src", "app", "components", "AppLayout.tsx"),
|
|
1998
|
+
{ overwrite: true }
|
|
1999
|
+
);
|
|
2000
|
+
await fs2.writeFile(
|
|
2001
|
+
path2.join(targetDir, "src", "app", "App.tsx"),
|
|
2002
|
+
generateAppTsx(selectedCodes, projectConfig?.disableDarkMode ?? false)
|
|
2003
|
+
);
|
|
2004
|
+
await fs2.writeFile(
|
|
2005
|
+
path2.join(targetDir, "src", "i18n.ts"),
|
|
2006
|
+
generateI18nFile(selectedCodes)
|
|
2007
|
+
);
|
|
2008
|
+
await syncLocaleFiles(updatedTemplatesDir, targetDir, selectedCodes, {
|
|
2009
|
+
pruneOthers: true
|
|
2010
|
+
});
|
|
2011
|
+
const pagesDir = path2.join(targetDir, "src", "pages");
|
|
2012
|
+
const existingPages = await fs2.pathExists(pagesDir) ? await fs2.readdir(pagesDir) : [];
|
|
2013
|
+
const hasLoginP = existingPages.includes("LoginPage.tsx");
|
|
2014
|
+
const hasHomeP = existingPages.includes("HomePage.tsx");
|
|
2015
|
+
const hasTemplateP = existingPages.includes("TemplatePage.tsx");
|
|
2016
|
+
const hasAssistantP = projectConfig?.hasAssistant ?? existingPages.includes("AssistantPage.tsx");
|
|
2017
|
+
const firstProtectedP = hasHomeP ? "/home" : hasTemplateP ? "/template" : "/login";
|
|
2018
|
+
await fs2.writeFile(
|
|
2019
|
+
path2.join(targetDir, "src", "app", "components", "AuthGuard.tsx"),
|
|
2020
|
+
generateAuthGuard({
|
|
2021
|
+
hasLogin: hasLoginP,
|
|
2022
|
+
hasHome: hasHomeP,
|
|
2023
|
+
hasTemplate: hasTemplateP,
|
|
2024
|
+
hasAssistant: hasAssistantP,
|
|
2025
|
+
firstProtectedPath: firstProtectedP
|
|
2026
|
+
})
|
|
2027
|
+
);
|
|
2028
|
+
}
|
|
1811
2029
|
}
|
|
1812
2030
|
if (filesToUpdate.includes("shared")) {
|
|
1813
2031
|
await fs2.copy(
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export
|
|
2
|
+
export type AuthPageShellProps = {
|
|
3
|
+
/** Hero photo on the left (default). Requires `imageSrc`/`imageAlt`. */
|
|
4
|
+
leftPanel?: 'image';
|
|
3
5
|
imageSrc: string;
|
|
4
6
|
imageAlt: string;
|
|
7
|
+
/**
|
|
8
|
+
* Background classes for the hero image overlay gradient. Defaults to the
|
|
9
|
+
* shared `--gradient-diagonal` theme token; pass a Tailwind gradient to
|
|
10
|
+
* override it for a specific auth page without affecting the others.
|
|
11
|
+
*/
|
|
12
|
+
gradientClassName?: string;
|
|
5
13
|
children: React.ReactNode;
|
|
6
|
-
}
|
|
14
|
+
} | {
|
|
15
|
+
/**
|
|
16
|
+
* Brand isotype mark on a solid `bg-muted` panel — no photo, no
|
|
17
|
+
* gradient. Pairs with a lighter `bg-card` form panel on the right,
|
|
18
|
+
* the inverse of the `image` variant's `bg-muted` form panel.
|
|
19
|
+
*/
|
|
20
|
+
leftPanel: 'isotype';
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
};
|
|
7
23
|
/**
|
|
8
24
|
* Shared two-column shell used by every auth page (Login, ForgotPassword,
|
|
9
|
-
* ResetPassword, VerifyEmail): hero image
|
|
10
|
-
* with a language selector on the right.
|
|
25
|
+
* ResetPassword, VerifyEmail): a left panel (hero image or brand isotype) and
|
|
26
|
+
* a centered form panel with a language selector on the right.
|
|
11
27
|
*/
|
|
12
|
-
export declare function AuthPageShell(
|
|
28
|
+
export declare function AuthPageShell(props: AuthPageShellProps): React.JSX.Element;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface CTASectionAction {
|
|
3
|
+
label: string;
|
|
4
|
+
href?: string;
|
|
5
|
+
onClick?: () => void;
|
|
6
|
+
}
|
|
7
|
+
export interface CTASectionProps extends React.HTMLAttributes<HTMLElement> {
|
|
8
|
+
title: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
cta: CTASectionAction;
|
|
11
|
+
secondaryCta?: CTASectionAction;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Full-width dark band prompting a primary conversion action.
|
|
15
|
+
*
|
|
16
|
+
* @description
|
|
17
|
+
* A high-impact closing section for marketing pages: a bold left-aligned
|
|
18
|
+
* headline, optional supporting copy, and up to two CTA buttons on a flat
|
|
19
|
+
* `bg-sidebar` surface — the same token-driven dark surface used elsewhere
|
|
20
|
+
* on this page (e.g. the methodology section) — so it stays legible across
|
|
21
|
+
* all Xertica-ui themes without per-theme contrast tuning or a gradient.
|
|
22
|
+
*
|
|
23
|
+
* @ai-rules
|
|
24
|
+
* 1. The background is a flat `bg-sidebar` surface with a `border-sidebar-border` hairline — never reintroduce a gradient or hardcode colors here.
|
|
25
|
+
* 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.
|
|
26
|
+
* 3. Each `cta`/`secondaryCta` needs either `href` (renders an `<a>`) or `onClick`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function CTASection({ title, description, cta, secondaryCta, className, ...props }: CTASectionProps): React.JSX.Element;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface ComplianceBadge {
|
|
3
|
+
icon: React.ReactNode;
|
|
4
|
+
label: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ComplianceBadgeRowProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
8
|
+
badges: ComplianceBadge[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A row of certification/compliance badges (e.g. SOC 2, GDPR, WCAG 2.1 AA).
|
|
12
|
+
*
|
|
13
|
+
* @description
|
|
14
|
+
* Renders a left-aligned grid where each badge pairs a token-radius outlined
|
|
15
|
+
* icon chip with a label and an optional short description, built entirely
|
|
16
|
+
* from theme tokens so it reskins across all Xertica-ui themes and dark mode.
|
|
17
|
+
*
|
|
18
|
+
* @ai-rules
|
|
19
|
+
* 1. Provide `badges` as `{ icon, label, description? }` — `icon` should be a small lucide-react element.
|
|
20
|
+
* 2. Keep `label` and `description` short — badges sit in a `grid-cols-2 sm:grid-cols-4` layout, so each column has limited width.
|
|
21
|
+
* 3. Do not hand-roll badge styling elsewhere — this component owns the icon-chip/label/description layout.
|
|
22
|
+
*/
|
|
23
|
+
export declare function ComplianceBadgeRow({ badges, className, ...props }: ComplianceBadgeRowProps): React.JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export type BlockColor = 'primary' | 'chart-1' | 'chart-2' | 'chart-3' | 'chart-4' | 'chart-5' | 'success' | 'info' | 'warning' | 'destructive';
|
|
3
|
+
export interface EvidenceTimelineItem {
|
|
4
|
+
number?: string | number;
|
|
5
|
+
icon?: React.ReactNode;
|
|
6
|
+
title: string;
|
|
7
|
+
description: string;
|
|
8
|
+
color?: BlockColor;
|
|
9
|
+
}
|
|
10
|
+
export interface EvidenceTimelineProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
11
|
+
items: EvidenceTimelineItem[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Vertical numbered timeline with a connecting line and colored step dots.
|
|
15
|
+
*
|
|
16
|
+
* @description
|
|
17
|
+
* Renders a "how our methodology works" style list: each item gets a
|
|
18
|
+
* colored dot (icon or step number) on a shared vertical line, with a
|
|
19
|
+
* title and description to its right.
|
|
20
|
+
*
|
|
21
|
+
* @ai-rules
|
|
22
|
+
* 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.
|
|
23
|
+
* 2. Each item's `color` maps to `colorTokens` — never hardcode colors.
|
|
24
|
+
* 3. This block has no outer card chrome; wrap it in a `<Card>` or section if chrome is needed.
|
|
25
|
+
*/
|
|
26
|
+
export declare function EvidenceTimeline({ items, className, ...props }: EvidenceTimelineProps): React.JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface FeatureRowProps extends React.HTMLAttributes<HTMLElement> {
|
|
3
|
+
eyebrow?: string;
|
|
4
|
+
title: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
bullets?: string[];
|
|
7
|
+
visual: React.ReactNode;
|
|
8
|
+
reverse?: boolean;
|
|
9
|
+
tone?: 'default' | 'muted' | 'card';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Alternating text + visual marketing section.
|
|
13
|
+
*
|
|
14
|
+
* @description
|
|
15
|
+
* A two-column "how it works" / definition row: a text block (eyebrow,
|
|
16
|
+
* title, description, optional checklist) paired with a consumer-supplied
|
|
17
|
+
* visual (image, illustration, or custom node). Stacks on mobile and
|
|
18
|
+
* alternates sides on desktop via `reverse`.
|
|
19
|
+
*
|
|
20
|
+
* @ai-rules
|
|
21
|
+
* 1. Chain multiple `FeatureRow`s and alternate `reverse` to build a "how it works" narrative.
|
|
22
|
+
* 2. Pass the visual as `<ImageWithFallback />` or any custom `ReactNode`; this component never renders an image itself.
|
|
23
|
+
* 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`).
|
|
24
|
+
*/
|
|
25
|
+
export declare function FeatureRow({ eyebrow, title, description, bullets, visual, reverse, tone, className, ...props }: FeatureRowProps): React.JSX.Element;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface HeroCta {
|
|
3
|
+
label: string;
|
|
4
|
+
href?: string;
|
|
5
|
+
onClick?: () => void;
|
|
6
|
+
}
|
|
7
|
+
export interface HeroProps extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {
|
|
8
|
+
eyebrow?: {
|
|
9
|
+
label: string;
|
|
10
|
+
icon?: React.ReactNode;
|
|
11
|
+
};
|
|
12
|
+
title: React.ReactNode;
|
|
13
|
+
description?: React.ReactNode;
|
|
14
|
+
primaryCta?: HeroCta;
|
|
15
|
+
secondaryCta?: HeroCta;
|
|
16
|
+
visual?: React.ReactNode;
|
|
17
|
+
align?: 'left' | 'center';
|
|
18
|
+
decorative?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Full-width, above-the-fold marketing hero section.
|
|
22
|
+
*
|
|
23
|
+
* @description
|
|
24
|
+
* The lead block for landing and marketing pages: an optional `PillBadge`
|
|
25
|
+
* eyebrow, a very large headline, supporting copy, and up to two `<Button>`
|
|
26
|
+
* CTAs. Automatically switches from a single column to a two-column layout
|
|
27
|
+
* once a `visual` (screenshot, illustration, collage) is supplied.
|
|
28
|
+
*
|
|
29
|
+
* @ai-rules
|
|
30
|
+
* 1. Pass `visual` for the two-column desktop layout; omit it for a single-column hero.
|
|
31
|
+
* 2. `primaryCta` renders as `default` (primary/brand) and `secondaryCta` as `secondary`, both via `<Button>` (`size="lg"`) — never hand-roll buttons.
|
|
32
|
+
* 3. Set `decorative` to add a token-based gradient blob backdrop; it is purely visual and never shifts layout.
|
|
33
|
+
* 4. `align="center"` centers the eyebrow/heading/copy/CTAs — pair it with omitting `visual` for a classic centered hero.
|
|
34
|
+
*/
|
|
35
|
+
export declare function Hero({ eyebrow, title, description, primaryCta, secondaryCta, visual, align, decorative, className, ...props }: HeroProps): React.JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export type BlockColor = 'primary' | 'chart-1' | 'chart-2' | 'chart-3' | 'chart-4' | 'chart-5' | 'success' | 'info' | 'warning' | 'destructive';
|
|
3
|
+
export interface HowItWorksStepItem {
|
|
4
|
+
number?: string | number;
|
|
5
|
+
icon?: React.ReactNode;
|
|
6
|
+
title: string;
|
|
7
|
+
description: string;
|
|
8
|
+
color?: BlockColor;
|
|
9
|
+
}
|
|
10
|
+
export interface HowItWorksStepsProps {
|
|
11
|
+
items: HowItWorksStepItem[];
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Horizontal numbered process row — the horizontal counterpart to `EvidenceTimeline`.
|
|
16
|
+
*
|
|
17
|
+
* @description
|
|
18
|
+
* Renders a "how it works" style row of steps: each item gets a colored
|
|
19
|
+
* badge (icon or step number) above a title and description, laid out
|
|
20
|
+
* side by side in a responsive grid instead of `EvidenceTimeline`'s
|
|
21
|
+
* vertical connecting line.
|
|
22
|
+
*
|
|
23
|
+
* @ai-rules
|
|
24
|
+
* 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.
|
|
25
|
+
* 2. Each item's `color` maps to `colorTokens` — never hardcode colors.
|
|
26
|
+
* 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.
|
|
27
|
+
* 4. This block has no outer card chrome; wrap it in a `<Card>` or section if chrome is needed.
|
|
28
|
+
*/
|
|
29
|
+
export declare function HowItWorksSteps({ items, className }: HowItWorksStepsProps): React.JSX.Element;
|