xertica-ui 2.5.1 → 2.5.2
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 +13 -0
- package/README.md +14 -16
- package/assets/xertica-logo.svg +37 -37
- package/assets/xertica-x-logo.svg +20 -20
- package/bin/generate-tokens.ts +262 -262
- package/bin/language-config.ts +359 -358
- package/components/assistant/code-block/CodeBlock.tsx +268 -268
- package/components/assistant/formatted-document/FormattedDocument.tsx +147 -147
- package/components/assistant/modern-chat-input/ModernChatInput.tsx +564 -564
- package/components/assistant/xertica-assistant/parts/AssistantCollapsedView.tsx +99 -99
- package/components/assistant/xertica-assistant/parts/AssistantConversationList.tsx +104 -104
- package/components/assistant/xertica-assistant/parts/AssistantDocumentEditor.tsx +81 -81
- package/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.tsx +88 -88
- package/components/assistant/xertica-assistant/parts/AssistantHeader.tsx +75 -75
- package/components/assistant/xertica-assistant/parts/AssistantMessageBubble.tsx +564 -564
- package/components/assistant/xertica-assistant/parts/AssistantTabBar.tsx +67 -67
- package/components/assistant/xertica-assistant/parts/AssistantWelcomeScreen.tsx +103 -103
- package/components/assistant/xertica-assistant/use-assistant.ts +615 -615
- package/components/assistant/xertica-assistant/xertica-assistant.tsx +611 -611
- package/components/blocks/card-patterns/ActivityCard.tsx +100 -100
- package/components/blocks/card-patterns/ActivityCardSkeleton.tsx +56 -56
- package/components/blocks/card-patterns/FeatureCardSkeleton.tsx +58 -58
- package/components/blocks/card-patterns/NotificationCard.tsx +140 -140
- package/components/blocks/card-patterns/NotificationCardSkeleton.tsx +81 -81
- package/components/blocks/card-patterns/ProfileCard.tsx +112 -112
- package/components/blocks/card-patterns/ProfileCardSkeleton.tsx +69 -69
- package/components/blocks/card-patterns/ProjectCard.tsx +123 -123
- package/components/blocks/card-patterns/ProjectCardSkeleton.tsx +67 -67
- package/components/blocks/card-patterns/QuickActionCardSkeleton.tsx +44 -44
- package/components/blocks/card-patterns/card-patterns.stories.tsx +594 -594
- package/components/blocks/card-patterns/index.ts +29 -29
- package/components/brand/language-selector/LanguageSelector.tsx +102 -102
- package/components/brand/language-selector/language-selector.stories.tsx +111 -111
- package/components/brand/language-selector/language-selector.test.tsx +101 -101
- package/components/brand/theme-toggle/ThemeToggle.tsx +74 -74
- package/components/brand/xertica-provider/xertica-provider.mdx +61 -61
- package/components/index.ts +86 -86
- package/components/layout/sidebar/sidebar.mdx +1 -1
- package/components/layout/sidebar/sidebar.stories.tsx +1033 -787
- package/components/layout/sidebar/sidebar.tsx +338 -1
- package/components/media/FloatingMediaWrapper.tsx +371 -371
- package/components/media/audio-player/AudioPlayer.tsx +768 -768
- package/components/media/video-player/VideoPlayer.tsx +310 -310
- package/components/pages/home-content/HomeContent.tsx +120 -120
- package/components/pages/home-content/home-content.mdx +62 -62
- package/components/pages/home-page/HomePage.tsx +78 -78
- package/components/pages/home-page/home-page.mdx +53 -53
- package/components/pages/template-content/TemplateContent.tsx +1354 -1354
- package/components/pages/template-content/template-content.mdx +61 -61
- package/components/pages/template-page/TemplatePage.stories.tsx +32 -32
- package/components/pages/template-page/template-page.mdx +53 -53
- package/components/shared/error-boundary.stories.tsx +114 -114
- package/components/shared/error-boundary.tsx +150 -150
- package/components/shared/error-fallbacks.tsx +222 -222
- package/components/ui/accordion/accordion.mdx +8 -8
- package/components/ui/alert/alert.mdx +8 -8
- package/components/ui/alert-dialog/alert-dialog.mdx +8 -8
- package/components/ui/aspect-ratio/aspect-ratio.mdx +8 -8
- package/components/ui/assistant-chart/assistant-chart.mdx +8 -8
- package/components/ui/avatar/avatar.mdx +8 -8
- package/components/ui/badge/badge.mdx +8 -8
- package/components/ui/breadcrumb/breadcrumb.mdx +8 -8
- package/components/ui/button/button.mdx +8 -8
- package/components/ui/calendar/calendar.mdx +8 -8
- package/components/ui/card/card.mdx +8 -8
- package/components/ui/carousel/carousel.mdx +8 -8
- package/components/ui/chart/chart.mdx +8 -8
- package/components/ui/chart/chart.test.tsx +178 -178
- package/components/ui/chart/chart.tsx +2245 -2239
- package/components/ui/checkbox/checkbox.mdx +8 -8
- package/components/ui/collapsible/collapsible.mdx +8 -8
- package/components/ui/command/command.mdx +8 -8
- package/components/ui/context-menu/context-menu.mdx +8 -8
- package/components/ui/dialog/dialog.mdx +8 -8
- package/components/ui/drawer/drawer.mdx +8 -8
- package/components/ui/dropdown-menu/dropdown-menu.mdx +8 -8
- package/components/ui/empty/empty.mdx +8 -8
- package/components/ui/file-upload/file-upload.mdx +8 -8
- package/components/ui/hover-card/hover-card.mdx +8 -8
- package/components/ui/input/input.mdx +8 -8
- package/components/ui/input-otp/input-otp.mdx +8 -8
- package/components/ui/label/label.mdx +8 -8
- package/components/ui/map/map.mdx +8 -8
- package/components/ui/menubar/menubar.mdx +8 -8
- package/components/ui/navigation-menu/navigation-menu.mdx +8 -8
- package/components/ui/notification-badge/notification-badge.mdx +8 -8
- package/components/ui/pagination/pagination.mdx +8 -8
- package/components/ui/popover/popover.mdx +8 -8
- package/components/ui/progress/progress.mdx +8 -8
- package/components/ui/radio-group/radio-group.mdx +8 -8
- package/components/ui/rating/rating.mdx +8 -8
- package/components/ui/resizable/resizable.mdx +8 -8
- package/components/ui/route-map/route-map.mdx +8 -8
- package/components/ui/scroll-area/scroll-area.mdx +8 -8
- package/components/ui/search/search.mdx +8 -8
- package/components/ui/select/select.mdx +8 -8
- package/components/ui/separator/separator.mdx +8 -8
- package/components/ui/sheet/sheet.mdx +8 -8
- package/components/ui/simple-map/simple-map.mdx +8 -8
- package/components/ui/skeleton/skeleton.mdx +8 -8
- package/components/ui/slider/slider.mdx +8 -8
- package/components/ui/sonner/sonner.mdx +8 -8
- package/components/ui/stats-card/index.ts +2 -2
- package/components/ui/stats-card/stats-card-skeleton.tsx +60 -60
- package/components/ui/stats-card/stats-card.mdx +8 -8
- package/components/ui/stats-card/stats-card.tsx +109 -109
- package/components/ui/stepper/stepper.mdx +8 -8
- package/components/ui/switch/switch.mdx +8 -8
- package/components/ui/table/table.mdx +8 -8
- package/components/ui/tabs/tabs.mdx +8 -8
- package/components/ui/textarea/textarea.mdx +8 -8
- package/components/ui/timeline/timeline.mdx +8 -8
- package/components/ui/toggle/toggle.mdx +8 -8
- package/components/ui/toggle-group/toggle-group.mdx +8 -8
- package/components/ui/tooltip/tooltip.mdx +8 -8
- package/components/ui/tree-view/tree-view.mdx +8 -8
- package/components.json +511 -511
- package/contexts/AuthContext.tsx +121 -121
- package/contexts/BrandColorsContext.tsx +282 -282
- package/contexts/LanguageContext.test.tsx +121 -121
- package/contexts/LanguageContext.tsx +250 -250
- package/contexts/theme-data.ts +391 -391
- package/dist/{AssistantChart-DoZCyS5r.cjs → AssistantChart-9w31gdAb.cjs} +4 -4
- package/dist/{AssistantChart-CldVCVDe.cjs → AssistantChart-BAudAfne.cjs} +5 -5
- package/dist/{AssistantChart-Bdd44uBn.cjs → AssistantChart-BAx9VQvb.cjs} +127 -388
- package/dist/{AssistantChart-Cu3m7RBo.js → AssistantChart-BP8upjMk.js} +5 -5
- package/dist/{AssistantChart-CFhDdGyU.js → AssistantChart-CVko2A1W.js} +130 -391
- package/dist/{AssistantChart-C_hwFRRr.js → AssistantChart-CVzmmhx4.js} +4 -4
- package/dist/{AudioPlayer-IAU5q5T1.cjs → AudioPlayer-1ypwE2Wh.cjs} +1 -1
- package/dist/{AudioPlayer-CGRUtUdN.js → AudioPlayer-DuKXrCfy.js} +1 -1
- package/dist/{LanguageContext-CS14yCpi.js → LanguageContext-BwhwC3G2.js} +2 -2
- package/dist/{LanguageContext-B_KFTCzT.cjs → LanguageContext-DvUt5jBg.cjs} +2 -2
- package/dist/{ThemeContext-C2EwAPDt.js → ThemeContext-BbBNoFTG.js} +2 -2
- package/dist/{ThemeContext-Bmod0Cg2.cjs → ThemeContext-BblcjQup.cjs} +13 -8
- package/dist/{ThemeContext-BWq9ACPo.js → ThemeContext-Bo-W2WZH.js} +13 -8
- package/dist/{ThemeContext-j5aGtPky.cjs → ThemeContext-CP3a0jxy.cjs} +193 -262
- package/dist/{ThemeContext-vTjumZeM.cjs → ThemeContext-Cmr8Ex8H.cjs} +2 -2
- package/dist/ThemeContext-CpqYShLq.cjs +324 -0
- package/dist/{ThemeContext-CQSo4Iwc.js → ThemeContext-D3LzacmG.js} +8 -1
- package/dist/ThemeContext-Du2nE1PL.js +325 -0
- package/dist/ThemeContext-GeEBTJ3q.cjs +1621 -0
- package/dist/ThemeContext-JyLK9B1o.js +1622 -0
- package/dist/{ThemeContext-CGk3KK0k.cjs → ThemeContext-U4dEYc6C.cjs} +8 -1
- package/dist/{ThemeContext-BXjrgUjW.js → ThemeContext-ept8jhXI.js} +200 -261
- package/dist/{VerifyEmailPage-CGIwmWrm.js → VerifyEmailPage-B31mCrMc.js} +1 -1
- package/dist/{VerifyEmailPage-C0c2e5n0.js → VerifyEmailPage-BE-L9mB7.js} +7 -7
- package/dist/{VerifyEmailPage-DSBMRHtl.js → VerifyEmailPage-BIBOKV7Z.js} +41 -36
- package/dist/{VerifyEmailPage-DgIid028.js → VerifyEmailPage-BJjAMUTW.js} +4 -4
- package/dist/{VerifyEmailPage--1Vurewl.cjs → VerifyEmailPage-BRSP-Pwt.cjs} +3 -3
- package/dist/{VerifyEmailPage-Cwi3kbol.cjs → VerifyEmailPage-Bae2cBXT.cjs} +7 -7
- package/dist/{VerifyEmailPage-De6bQjrz.cjs → VerifyEmailPage-BiRm7Nh4.cjs} +41 -36
- package/dist/{VerifyEmailPage-ByerOcm4.cjs → VerifyEmailPage-Bv8Ah_TK.cjs} +23 -20
- package/dist/VerifyEmailPage-Bvfv8HVQ.js +3214 -0
- package/dist/{VerifyEmailPage-BComraR7.cjs → VerifyEmailPage-CR7kb5df.cjs} +22 -12
- package/dist/{VerifyEmailPage-CpqqpLpo.cjs → VerifyEmailPage-C_Zk6Gen.cjs} +1 -1
- package/dist/{VerifyEmailPage-MTD7AG1Z.js → VerifyEmailPage-C_ihbcth.js} +4 -4
- package/dist/{VerifyEmailPage-1WwWczAn.js → VerifyEmailPage-CbgjOF0v.js} +22 -12
- package/dist/{VerifyEmailPage-DvMLZgFt.js → VerifyEmailPage-CdYPSJoO.js} +1 -1
- package/dist/{VerifyEmailPage-By3Jf__L.cjs → VerifyEmailPage-CkBYfsNy.cjs} +4 -4
- package/dist/{VerifyEmailPage-CJLz3jrn.js → VerifyEmailPage-Cyl55sJb.js} +23 -20
- package/dist/VerifyEmailPage-D-FRj5TU.cjs +3213 -0
- package/dist/{VerifyEmailPage-B4peJjAT.cjs → VerifyEmailPage-DF2ilhum.cjs} +334 -356
- package/dist/{VerifyEmailPage-CYXtbKi3.cjs → VerifyEmailPage-DMBh4NM9.cjs} +1 -1
- package/dist/{VerifyEmailPage-CgMxRb4z.js → VerifyEmailPage-DTtFfC-J.js} +3 -3
- package/dist/{VerifyEmailPage-CFLMls1p.cjs → VerifyEmailPage-Dt7zgA4w.cjs} +4 -4
- package/dist/{VerifyEmailPage-C5TNQTBa.js → VerifyEmailPage-EhudUdqF.js} +343 -355
- package/dist/{VerifyEmailPage-DGhuIqkb.js → VerifyEmailPage-X14vhdyl.js} +4 -4
- package/dist/VerifyEmailPage-hdB8JQGv.cjs +3213 -0
- package/dist/{VerifyEmailPage-Bp1XXl3H.cjs → VerifyEmailPage-u_Dn7t1U.cjs} +4 -4
- package/dist/VerifyEmailPage-vYHbYK3q.js +3214 -0
- package/dist/{XerticaProvider-CBGc4EMA.cjs → XerticaProvider-AChwphCO.cjs} +4 -4
- package/dist/{XerticaProvider-BIrqfZ-i.cjs → XerticaProvider-AbWlr7Af.cjs} +8 -11
- package/dist/{XerticaProvider-D-yNhF94.cjs → XerticaProvider-B8CaV7xu.cjs} +1 -1
- package/dist/{XerticaProvider-CEoWMTxu.js → XerticaProvider-BITjgC5p.js} +2 -2
- package/dist/{XerticaProvider-CllrbMEJ.cjs → XerticaProvider-By8q3Roe.cjs} +2 -2
- package/dist/{XerticaProvider-C1DKnvLh.js → XerticaProvider-CUYJZc32.js} +4 -4
- package/dist/{XerticaProvider-ET0ihewn.cjs → XerticaProvider-CW9hpCdF.cjs} +2 -2
- package/dist/{XerticaProvider-Dt5HEzbQ.js → XerticaProvider-CWgby5mY.js} +10 -10
- package/dist/XerticaProvider-CWs6EwNa.js +49 -0
- package/dist/XerticaProvider-CjQAQPcn.cjs +48 -0
- package/dist/XerticaProvider-D5lLumH-.js +49 -0
- package/dist/{XerticaProvider-DYq4JWtg.js → XerticaProvider-DQtvJU7m.js} +1 -1
- package/dist/XerticaProvider-qQUDop71.cjs +48 -0
- package/dist/{XerticaProvider-B7EVH-NF.js → XerticaProvider-siSt9uG2.js} +2 -2
- package/dist/{XerticaXLogo-Zw2B276b.cjs → XerticaXLogo-8TTzBjHw.cjs} +1 -1
- package/dist/{XerticaXLogo-B7xQ5dhi.js → XerticaXLogo-BWaag64t.js} +1 -1
- package/dist/{XerticaXLogo-DZbo4vOE.js → XerticaXLogo-CFuIlYFH.js} +12 -12
- package/dist/{XerticaXLogo-bvZSgwGF.cjs → XerticaXLogo-CU-U-GP4.cjs} +7 -13
- package/dist/XerticaXLogo-ChryA6xj.js +252 -0
- package/dist/{XerticaXLogo-CQUUjXoH.cjs → XerticaXLogo-CziKMQil.cjs} +8 -8
- package/dist/XerticaXLogo-DHz5SugF.js +252 -0
- package/dist/XerticaXLogo-DTee_y8X.cjs +251 -0
- package/dist/{XerticaXLogo-Cmsp-Eey.js → XerticaXLogo-DfUvz-lD.js} +9 -9
- package/dist/XerticaXLogo-kslQ8Tk_.cjs +251 -0
- package/dist/{alert-dialog-s-vmNkJ_.js → alert-dialog-iDe5VE5o.js} +3 -3
- package/dist/{alert-dialog-DSKByiKZ.cjs → alert-dialog-yckpaOpy.cjs} +3 -3
- package/dist/cli.js +2 -1
- package/dist/components/ui/chart/chart.d.ts +7 -5
- package/dist/{google-maps-loader-Y-QkD-Li.cjs → google-maps-loader-BqsYL48U.cjs} +0 -5
- package/dist/{google-maps-loader-CTYySAun.js → google-maps-loader-t2IlYBzw.js} +0 -4
- package/dist/index-CkTUgOwX.js +8 -0
- package/dist/{index-COtD8bRW.cjs → index-D3RLKRAs.cjs} +1 -1
- package/dist/index.cjs.js +2 -2
- package/dist/index.es.js +2 -2
- package/dist/index.umd.js +454 -1027
- package/dist/layout.cjs.js +1 -1
- package/dist/layout.es.js +1 -1
- package/dist/pages.cjs.js +1 -1
- package/dist/pages.es.js +1 -1
- package/dist/{sidebar-DAaY8bRU.cjs → sidebar-B3EYhli0.cjs} +33 -24
- package/dist/{sidebar-nzPoVHBQ.cjs → sidebar-B9NR0lCe.cjs} +46 -41
- package/dist/{sidebar-CeTMuzOx.cjs → sidebar-BvF5I2Ue.cjs} +47 -128
- package/dist/{sidebar-q7P2Godd.cjs → sidebar-C5B_LHek.cjs} +1 -1
- package/dist/{sidebar-CrQDDdcz.js → sidebar-CA6_ek3f.js} +33 -24
- package/dist/sidebar-CLmIjgNd.cjs +1136 -0
- package/dist/{sidebar-BxGXsDAd.cjs → sidebar-CVUGHOS_.cjs} +8 -16
- package/dist/{sidebar-BViy8Eeu.js → sidebar-CmvwjnVb.js} +9 -17
- package/dist/{sidebar-B6SlKZYN.js → sidebar-CplprZpM.js} +49 -40
- package/dist/sidebar-Duermn32.js +1133 -0
- package/dist/{sidebar-BbVIQvlP.js → sidebar-Dz7bd3zP.js} +1 -1
- package/dist/{sidebar-0ocFLSks.js → sidebar-KIS0C2JH.js} +50 -127
- package/dist/sidebar-OTO_up7Z.js +801 -0
- package/dist/sidebar-zowjejT2.cjs +800 -0
- package/dist/{use-audio-player-nv8ZSGa1.js → use-audio-player-Bkh23vQ3.js} +3 -7
- package/dist/{use-audio-player-NKsWyjWu.cjs → use-audio-player-Dn1NR9xN.cjs} +3 -7
- package/dist/{xertica-assistant-dyP7KHM5.cjs → xertica-assistant-B1IaHXnB.cjs} +388 -529
- package/dist/{xertica-assistant-ciJaWqm1.js → xertica-assistant-BMqdyRVi.js} +10 -28
- package/dist/{xertica-assistant-V_IdW4WF.cjs → xertica-assistant-Bj3vBCq_.cjs} +9 -27
- package/dist/{xertica-assistant-yX1CFBBo.js → xertica-assistant-DPsESB6t.js} +390 -531
- package/dist/{CodeBlock-7TTgmdGG.cjs → xertica-assistant-Qp3ydksa.cjs} +51 -263
- package/dist/{CodeBlock-BeSt1h5P.js → xertica-assistant-gnCJdcZY.js} +7 -219
- package/dist/xertica-ui.css +2 -2
- package/docs/architecture-improvements.md +456 -456
- package/docs/architecture.md +312 -312
- package/docs/components/assistant.md +428 -428
- package/docs/components/branding.md +252 -252
- package/docs/components/card-patterns.md +447 -447
- package/docs/components/error-boundary.md +201 -201
- package/docs/components/hooks.md +432 -432
- package/docs/components/language-selector.md +176 -176
- package/docs/components/pages.md +323 -323
- package/docs/components/sidebar.md +331 -331
- package/docs/components/stats-card.md +138 -138
- package/docs/doc-audit.md +244 -244
- package/docs/getting-started.md +616 -616
- package/docs/guidelines.md +330 -330
- package/docs/i18n.md +480 -480
- package/docs/installation.md +268 -268
- package/docs/llms.md +295 -295
- package/docs/state-management.md +289 -289
- package/guidelines/Guidelines.md +409 -409
- package/llms-compact.txt +1 -1
- package/llms-full.txt +10688 -10688
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/styles/xertica/base.css +90 -90
- package/styles/xertica/tokens.css +240 -240
- package/templates/.prettierignore +4 -4
- package/templates/.prettierrc +10 -10
- package/templates/CLAUDE.md +180 -180
- package/templates/package.json +2 -2
- package/templates/src/app/App.tsx +46 -46
- package/templates/src/app/components/AuthGuard.tsx +131 -131
- package/templates/src/features/assistant/data/mock.ts +75 -75
- package/templates/src/features/assistant/hooks/useAssistantConfig.ts +20 -20
- package/templates/src/features/assistant/index.ts +5 -5
- package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +70 -70
- package/templates/src/features/auth/ui/LoginContent.tsx +92 -92
- package/templates/src/features/auth/ui/ResetPasswordContent.tsx +183 -183
- package/templates/src/features/auth/ui/SocialLoginButtons.tsx +78 -78
- package/templates/src/features/auth/ui/VerifyEmailContent.tsx +80 -80
- package/templates/src/features/home/data/mock.ts +41 -41
- package/templates/src/features/home/hooks/useFeatureCards.ts +20 -20
- package/templates/src/features/home/index.ts +11 -11
- package/templates/src/features/home/ui/HomeContent.tsx +117 -117
- package/templates/src/features/template/ui/CrudTemplate.tsx +112 -112
- package/templates/src/features/template/ui/DashboardTemplate.tsx +110 -110
- package/templates/src/features/template/ui/FormTemplate.tsx +117 -117
- package/templates/src/features/template/ui/LoginTemplate.tsx +59 -59
- package/templates/src/features/template/ui/TemplateContent.tsx +1322 -1322
- package/templates/src/i18n.ts +124 -124
- package/templates/src/locales/en/common.json +21 -21
- package/templates/src/locales/en/components/activityCard.json +10 -10
- package/templates/src/locales/en/components/assistant.json +119 -119
- package/templates/src/locales/en/components/media.json +29 -29
- package/templates/src/locales/en/components/notificationCard.json +5 -5
- package/templates/src/locales/en/components/profileCard.json +8 -8
- package/templates/src/locales/en/components/projectCard.json +10 -10
- package/templates/src/locales/en/components/sidebar.json +14 -14
- package/templates/src/locales/en/components/stats.json +8 -8
- package/templates/src/locales/en/components/team.json +14 -14
- package/templates/src/locales/en/errors.json +9 -9
- package/templates/src/locales/en/languageSelector.json +7 -7
- package/templates/src/locales/en/nav.json +6 -6
- package/templates/src/locales/en/pages/crudTemplate.json +25 -25
- package/templates/src/locales/en/pages/dashboardTemplate.json +20 -20
- package/templates/src/locales/en/pages/forgotPassword.json +10 -10
- package/templates/src/locales/en/pages/formTemplate.json +16 -16
- package/templates/src/locales/en/pages/home.json +7 -7
- package/templates/src/locales/en/pages/login.json +15 -15
- package/templates/src/locales/en/pages/loginTemplate.json +9 -9
- package/templates/src/locales/en/pages/resetPassword.json +18 -18
- package/templates/src/locales/en/pages/templates.json +317 -317
- package/templates/src/locales/en/pages/verifyEmail.json +12 -12
- package/templates/src/locales/en/themeToggle.json +6 -6
- package/templates/src/locales/es/common.json +21 -21
- package/templates/src/locales/es/components/activityCard.json +10 -10
- package/templates/src/locales/es/components/assistant.json +119 -119
- package/templates/src/locales/es/components/media.json +29 -29
- package/templates/src/locales/es/components/notificationCard.json +5 -5
- package/templates/src/locales/es/components/profileCard.json +8 -8
- package/templates/src/locales/es/components/projectCard.json +10 -10
- package/templates/src/locales/es/components/sidebar.json +14 -14
- package/templates/src/locales/es/components/stats.json +8 -8
- package/templates/src/locales/es/components/team.json +14 -14
- package/templates/src/locales/es/errors.json +9 -9
- package/templates/src/locales/es/languageSelector.json +7 -7
- package/templates/src/locales/es/nav.json +6 -6
- package/templates/src/locales/es/pages/crudTemplate.json +25 -25
- package/templates/src/locales/es/pages/dashboardTemplate.json +20 -20
- package/templates/src/locales/es/pages/forgotPassword.json +10 -10
- package/templates/src/locales/es/pages/formTemplate.json +16 -16
- package/templates/src/locales/es/pages/home.json +7 -7
- package/templates/src/locales/es/pages/login.json +15 -15
- package/templates/src/locales/es/pages/loginTemplate.json +9 -9
- package/templates/src/locales/es/pages/resetPassword.json +18 -18
- package/templates/src/locales/es/pages/templates.json +317 -317
- package/templates/src/locales/es/pages/verifyEmail.json +12 -12
- package/templates/src/locales/es/themeToggle.json +6 -6
- package/templates/src/locales/pt-BR/common.json +21 -21
- package/templates/src/locales/pt-BR/components/activityCard.json +10 -10
- package/templates/src/locales/pt-BR/components/assistant.json +119 -119
- package/templates/src/locales/pt-BR/components/media.json +29 -29
- package/templates/src/locales/pt-BR/components/notificationCard.json +5 -5
- package/templates/src/locales/pt-BR/components/profileCard.json +8 -8
- package/templates/src/locales/pt-BR/components/projectCard.json +10 -10
- package/templates/src/locales/pt-BR/components/sidebar.json +14 -14
- package/templates/src/locales/pt-BR/components/stats.json +8 -8
- package/templates/src/locales/pt-BR/components/team.json +14 -14
- package/templates/src/locales/pt-BR/errors.json +9 -9
- package/templates/src/locales/pt-BR/languageSelector.json +7 -7
- package/templates/src/locales/pt-BR/nav.json +6 -6
- package/templates/src/locales/pt-BR/pages/crudTemplate.json +25 -25
- package/templates/src/locales/pt-BR/pages/dashboardTemplate.json +20 -20
- package/templates/src/locales/pt-BR/pages/forgotPassword.json +10 -10
- package/templates/src/locales/pt-BR/pages/formTemplate.json +16 -16
- package/templates/src/locales/pt-BR/pages/home.json +7 -7
- package/templates/src/locales/pt-BR/pages/login.json +15 -15
- package/templates/src/locales/pt-BR/pages/loginTemplate.json +9 -9
- package/templates/src/locales/pt-BR/pages/resetPassword.json +18 -18
- package/templates/src/locales/pt-BR/pages/templates.json +317 -317
- package/templates/src/locales/pt-BR/pages/verifyEmail.json +12 -12
- package/templates/src/locales/pt-BR/themeToggle.json +6 -6
- package/templates/src/pages/AssistantPage.tsx +470 -470
- package/templates/src/pages/HomePage.tsx +53 -53
- package/templates/src/shared/error-boundary.tsx +150 -150
- package/templates/src/shared/error-fallbacks.tsx +222 -222
- package/templates/src/styles/xertica/tokens.css +240 -240
- package/templates/vite.config.js +20 -20
- package/templates/vite.config.ts +55 -55
- package/dist/AssistantChart-BKVtGUKF.js +0 -3383
- package/dist/AssistantChart-CxGjH7Qk.js +0 -3477
- package/dist/AssistantChart-DIpshm3i.js +0 -4784
- package/dist/AssistantChart-D_PTeu8P.cjs +0 -3503
- package/dist/AssistantChart-WeycT5Pd.cjs +0 -3551
- package/dist/AssistantChart-zjsy2GaZ.cjs +0 -4810
- package/dist/AudioPlayer-B1lt5cPl.cjs +0 -989
- package/dist/AudioPlayer-BZ7bibzU.cjs +0 -982
- package/dist/AudioPlayer-BpRPS4-1.cjs +0 -1277
- package/dist/AudioPlayer-C12BjQBV.cjs +0 -997
- package/dist/AudioPlayer-CFeV8t-5.cjs +0 -936
- package/dist/AudioPlayer-Coly3q5R.js +0 -1278
- package/dist/AudioPlayer-CySJIyvL.js +0 -937
- package/dist/AudioPlayer-DMcG_c7L.js +0 -990
- package/dist/AudioPlayer-DcFKRJE_.js +0 -998
- package/dist/AudioPlayer-e8LfNoqO.js +0 -983
- package/dist/BrandColorsContext-565dDHd5.js +0 -660
- package/dist/BrandColorsContext-BcJbtkqn.cjs +0 -659
- package/dist/CodeBlock-BgfYL_rD.cjs +0 -2094
- package/dist/CodeBlock-BlcqlA9M.cjs +0 -2094
- package/dist/CodeBlock-Bnmeu5ez.cjs +0 -2094
- package/dist/CodeBlock-BtfPlbAI.js +0 -2078
- package/dist/CodeBlock-CIySIuYr.js +0 -2078
- package/dist/CodeBlock-CuPtUM-7.cjs +0 -2094
- package/dist/CodeBlock-D6ffWXgc.js +0 -2078
- package/dist/CodeBlock-D8dcwbit.cjs +0 -2094
- package/dist/CodeBlock-DMZrFnlw.cjs +0 -2094
- package/dist/CodeBlock-DlBehYN8.js +0 -2078
- package/dist/CodeBlock-DnYNI8rQ.js +0 -2078
- package/dist/CodeBlock-DvKWbSnE.cjs +0 -2094
- package/dist/CodeBlock-DwMCfkFY.js +0 -2078
- package/dist/CodeBlock-Dy6CNYyj.js +0 -2078
- package/dist/CodeBlock-U1pPOQI7.cjs +0 -2094
- package/dist/CodeBlock-f_GpNhEB.js +0 -2078
- package/dist/CodeBlock-oB6u8nI1.js +0 -2078
- package/dist/CodeBlock-tZC31B73.cjs +0 -2094
- package/dist/FeatureCard-CxC-7C-C.cjs +0 -300
- package/dist/FeatureCard-DbHWCb4E.js +0 -301
- package/dist/ImageWithFallback-CGtidP6B.cjs +0 -4542
- package/dist/ImageWithFallback-lsg3pdFg.js +0 -4508
- package/dist/LanguageSelector-B5YfbHra.js +0 -231
- package/dist/LanguageSelector-D6uacAIM.cjs +0 -230
- package/dist/LayoutContext-B45-e9DI.cjs +0 -93
- package/dist/LayoutContext-BAql6ZRY.js +0 -97
- package/dist/LayoutContext-Bav3UMEA.js +0 -94
- package/dist/LayoutContext-BvK-ggDa.cjs +0 -96
- package/dist/ThemeContext-BoH4NLfN.js +0 -734
- package/dist/ThemeContext-r69W20Xg.cjs +0 -733
- package/dist/VerifyEmailPage-COiyNl1y.js +0 -2825
- package/dist/VerifyEmailPage-CqKsR2v8.js +0 -2827
- package/dist/VerifyEmailPage-DjQKRlUS.cjs +0 -2824
- package/dist/VerifyEmailPage-s-1X3LDJ.cjs +0 -2826
- package/dist/XerticaOrbe-KL1RBHzw.cjs +0 -1354
- package/dist/XerticaOrbe-zwS1p2a8.js +0 -1355
- package/dist/XerticaProvider-6btlAlzc.js +0 -17
- package/dist/XerticaProvider-BNoNOxQ5.cjs +0 -16
- package/dist/XerticaProvider-BlY2limY.cjs +0 -38
- package/dist/XerticaProvider-DDuiIcKo.js +0 -39
- package/dist/XerticaProvider-cI9hSs27.cjs +0 -38
- package/dist/XerticaProvider-hSwhNQex.js +0 -39
- package/dist/alert-dialog-BOje--vD.js +0 -847
- package/dist/alert-dialog-BtEuQqrg.cjs +0 -870
- package/dist/breadcrumb-CqJ7bHY5.js +0 -161
- package/dist/breadcrumb-m9Hb2_XN.cjs +0 -177
- package/dist/components/assistant/xertica-assistant/hooks/index.d.ts +0 -6
- package/dist/components/assistant/xertica-assistant/hooks/use-assistant-conversations.d.ts +0 -21
- package/dist/components/assistant/xertica-assistant/hooks/use-assistant-messages.d.ts +0 -49
- package/dist/components/assistant/xertica-assistant/hooks/use-assistant-suggestions.d.ts +0 -16
- package/dist/components/blocks/audio-player/AudioPlayer.d.ts +0 -35
- package/dist/components/blocks/audio-player/index.d.ts +0 -1
- package/dist/components/blocks/document-editor/DocumentEditor.d.ts +0 -26
- package/dist/components/blocks/document-editor/index.d.ts +0 -1
- package/dist/components/blocks/podcast-player/PodcastPlayer.d.ts +0 -41
- package/dist/components/blocks/podcast-player/index.d.ts +0 -1
- package/dist/components/ui/chart/parts/chart-dashboard.d.ts +0 -113
- package/dist/components/ui/chart/parts/chart-metric.d.ts +0 -118
- package/dist/components/ui/chart/parts/chart-primitives.d.ts +0 -101
- package/dist/components/ui/chart/parts/chart-shared.d.ts +0 -20
- package/dist/components/ui/chart/parts/chart-utils.d.ts +0 -12
- package/dist/components/ui/chart/parts/index.d.ts +0 -5
- package/dist/dropdown-menu-BDB5CmQs.cjs +0 -247
- package/dist/dropdown-menu-DQidbKBD.js +0 -231
- package/dist/google-maps-loader-BFWp6VPd.js +0 -287
- package/dist/google-maps-loader-BKcdgFbu.cjs +0 -312
- package/dist/google-maps-loader-CumCNXeG.js +0 -312
- package/dist/google-maps-loader-eS3uQ5TA.cjs +0 -287
- package/dist/header-Cgy6vYPk.cjs +0 -731
- package/dist/header-DRlT4jgI.js +0 -715
- package/dist/header-Dux00SI4.cjs +0 -731
- package/dist/header-EkGKXPsD.js +0 -715
- package/dist/header-WfEywpyc.cjs +0 -731
- package/dist/header-tifNQn2U.js +0 -715
- package/dist/index-BhapVLVj.js +0 -8
- package/dist/index-D6fxYEY8.cjs +0 -7
- package/dist/index-DAIp0_HK.js +0 -8
- package/dist/index-DW5tYe26.js +0 -8
- package/dist/index-GA__GvnG.cjs +0 -7
- package/dist/input-2R4loU86.js +0 -127
- package/dist/input-DWANSKGb.cjs +0 -145
- package/dist/progress-DPtzoVV8.js +0 -175
- package/dist/progress-EeaoqqUs.cjs +0 -191
- package/dist/rich-text-editor-0mraWT5y.cjs +0 -2376
- package/dist/rich-text-editor-B-IkcPD0.js +0 -2874
- package/dist/rich-text-editor-B6jMRLzk.cjs +0 -1939
- package/dist/rich-text-editor-B8_oYcIR.js +0 -1730
- package/dist/rich-text-editor-B9UbSXNb.js +0 -1203
- package/dist/rich-text-editor-BYuRBNBU.js +0 -2373
- package/dist/rich-text-editor-Bb9pySTs.cjs +0 -2374
- package/dist/rich-text-editor-BcL6L3cm.cjs +0 -2374
- package/dist/rich-text-editor-BoVZYtTs.cjs +0 -2391
- package/dist/rich-text-editor-Bp3zQqMC.js +0 -2954
- package/dist/rich-text-editor-CMgSN_w2.js +0 -1189
- package/dist/rich-text-editor-CPV1lEPH.cjs +0 -1748
- package/dist/rich-text-editor-CeucBdIv.cjs +0 -2971
- package/dist/rich-text-editor-CoKqbCtu.cjs +0 -1799
- package/dist/rich-text-editor-Cw56T_mB.js +0 -2356
- package/dist/rich-text-editor-Cyt8qs2b.js +0 -1921
- package/dist/rich-text-editor-D6H84OcX.cjs +0 -1220
- package/dist/rich-text-editor-D76gD-QI.js +0 -2328
- package/dist/rich-text-editor-DKkokOnA.js +0 -1781
- package/dist/rich-text-editor-DNsdpN64.cjs +0 -2359
- package/dist/rich-text-editor-DfG8bCyY.js +0 -2358
- package/dist/rich-text-editor-Dxjw31Z4.js +0 -2341
- package/dist/rich-text-editor-DzP0Epmb.js +0 -2356
- package/dist/rich-text-editor-bRkNoeZY.cjs +0 -2891
- package/dist/rich-text-editor-lyYE2ZG5.cjs +0 -1207
- package/dist/rich-text-editor-skplNlBM.cjs +0 -2345
- package/dist/select-Bkbr0f-Z.cjs +0 -162
- package/dist/select-CvIVdX2n.js +0 -145
- package/dist/sidebar-CK_0ZQHj.cjs +0 -803
- package/dist/sidebar-CUuOvYhK.js +0 -787
- package/dist/sidebar-DQj1z3jG.cjs +0 -758
- package/dist/sidebar-Djn5syhi.cjs +0 -786
- package/dist/sidebar-LluMXfam.js +0 -759
- package/dist/sidebar-_rT7rBMk.js +0 -787
- package/dist/slider-Bc5Hd0y1.js +0 -56
- package/dist/slider-N7hFFj6X.cjs +0 -73
- package/dist/tooltip-Ded96neP.cjs +0 -137
- package/dist/tooltip-HDOoD2-0.js +0 -120
- package/dist/use-audio-player-B31J-aqh.cjs +0 -187
- package/dist/use-audio-player-BkmEmj8Q.js +0 -185
- package/dist/use-audio-player-CLFTWFW1.cjs +0 -184
- package/dist/use-audio-player-CLLn00I6.js +0 -188
- package/dist/use-file-upload-BcjEo2S5.js +0 -404
- package/dist/use-file-upload-CRJR68Tj.cjs +0 -403
- package/dist/use-mobile-B0hNy_Y6.cjs +0 -4303
- package/dist/use-mobile-BXuYROXM.js +0 -4202
- package/dist/use-mobile-Bbd51ASU.cjs +0 -4392
- package/dist/use-mobile-Bk6CX-TC.js +0 -4359
- package/dist/use-mobile-BvYdisLP.js +0 -4202
- package/dist/use-mobile-BzuxjzNX.cjs +0 -4392
- package/dist/use-mobile-CG2-SdXV.cjs +0 -4235
- package/dist/use-mobile-CKb5pqTs.js +0 -4269
- package/dist/use-mobile-CYuAuGDl.js +0 -4202
- package/dist/use-mobile-CaENcqm-.js +0 -4508
- package/dist/use-mobile-CbrYgJGJ.js +0 -4203
- package/dist/use-mobile-Cd4xPrKq.cjs +0 -46
- package/dist/use-mobile-DMOvImGQ.cjs +0 -4542
- package/dist/use-mobile-DRB3BQgD.cjs +0 -4235
- package/dist/use-mobile-DZvv7QMR.js +0 -4359
- package/dist/use-mobile-DdI_TXam.cjs +0 -4235
- package/dist/use-mobile-DlceKf8a.js +0 -4359
- package/dist/use-mobile-DsOnow1o.cjs +0 -4236
- package/dist/use-mobile-Kcj6jSnK.cjs +0 -4392
- package/dist/use-mobile-bnKcua_i.js +0 -4202
- package/dist/use-mobile-j4w2Jrf1.js +0 -30
- package/dist/use-mobile-ncXBeE2z.cjs +0 -4235
- package/dist/use-rich-text-editor-DjiddBGv.js +0 -282
- package/dist/use-rich-text-editor-lpeswbCs.cjs +0 -281
- package/dist/xertica-assistant-BdiZag0h.js +0 -2187
- package/dist/xertica-assistant-CrgTb6Hs.cjs +0 -2155
- package/dist/xertica-assistant-DCsnQyi5.js +0 -2156
- package/dist/xertica-assistant-DUBpmEgo.cjs +0 -2186
- package/dist/{rich-text-editor-DgF8s7xW.js → rich-text-editor-BmsjY03B.js} +26 -26
- package/dist/{rich-text-editor-mWoaSCE4.cjs → rich-text-editor-GS2kpTAK.cjs} +26 -26
package/docs/architecture.md
CHANGED
|
@@ -1,312 +1,312 @@
|
|
|
1
|
-
# Xertica UI — Architecture
|
|
2
|
-
|
|
3
|
-
## Audit Date
|
|
4
|
-
|
|
5
|
-
2026-05-20 (Post-Modularization + State Layer)
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Summary of Changes
|
|
10
|
-
|
|
11
|
-
The library underwent a **complete architectural modularization**. The flat `components/` directory was reorganized into a domain-driven structure, and a dedicated **state layer** was introduced via `features/`, `AuthContext`, TanStack React Query, and Zustand.
|
|
12
|
-
|
|
13
|
-
### Component Domains
|
|
14
|
-
|
|
15
|
-
| Domain | Path | Contains |
|
|
16
|
-
| ----------- | ----------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
17
|
-
| `ui` | `components/ui/[name]/` | Design system primitives (Button, Card, Calendar, Chart, etc.) |
|
|
18
|
-
| `layout` | `components/layout/` | Sidebar, Header, SidebarPrimitive |
|
|
19
|
-
| `blocks` | `components/blocks/` | High-level composed components built from `ui/` primitives |
|
|
20
|
-
| `assistant` | `components/assistant/` | XerticaAssistant, MarkdownMessage, CodeBlock, etc. |
|
|
21
|
-
| `brand` | `components/brand/` | XerticaLogo, ThemeToggle, LanguageSelector, XerticaProvider |
|
|
22
|
-
| `pages` | `components/pages/` | LoginPage, HomePage, TemplatePage, etc. |
|
|
23
|
-
| `shared` | `components/shared/` | utils.ts, use-mobile.ts, layout-constants.ts, navigation.ts, **error-boundary.tsx**, **error-fallbacks.tsx** |
|
|
24
|
-
|
|
25
|
-
### State Layer — `features/`
|
|
26
|
-
|
|
27
|
-
Feature slices separate server state, client UI state, and mock data from the component tree.
|
|
28
|
-
|
|
29
|
-
**Library source** (in this repo, used by Storybook and the showcase pages):
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
features/
|
|
33
|
-
├── home/
|
|
34
|
-
│ ├── data/mock.ts ← typed mock data + async fetch functions (swap point for real API)
|
|
35
|
-
│ ├── hooks/
|
|
36
|
-
│ │ ├── useDashboardStats.ts ← React Query (staleTime 5 min) — library-only
|
|
37
|
-
│ │ ├── useTeamMembers.ts ← React Query (staleTime 2 min) — library-only
|
|
38
|
-
│ │ └── useFeatureCards.ts ← React Query (staleTime 10 min)
|
|
39
|
-
│ ├── store/dashboardStore.ts ← Zustand (progress, slider, activeTab — UI-only)
|
|
40
|
-
│ └── index.ts ← barrel
|
|
41
|
-
└── assistant/
|
|
42
|
-
├── data/mock.ts ← AssistantConfig + fetchAssistantConfig (swap point)
|
|
43
|
-
├── hooks/useAssistantConfig.ts ← React Query (staleTime 30 min)
|
|
44
|
-
└── index.ts ← barrel
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
**Scaffold template** (what `npx xertica-ui init` generates in a consumer project):
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
src/features/
|
|
51
|
-
├── home/
|
|
52
|
-
│ ├── data/mock.ts
|
|
53
|
-
│ ├── hooks/useFeatureCards.ts ← only useFeatureCards is scaffolded
|
|
54
|
-
│ ├── store/dashboardStore.ts
|
|
55
|
-
│ ├── ui/HomeContent.tsx
|
|
56
|
-
│ └── index.ts
|
|
57
|
-
└── assistant/
|
|
58
|
-
├── data/mock.ts ← exports getMockRichSuggestions() / getMockFeedbackOptions() factories
|
|
59
|
-
├── hooks/useAssistantConfig.ts
|
|
60
|
-
└── index.ts
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
> `useDashboardStats` and `useTeamMembers` exist only in the library source where they power `TemplateContent.tsx`'s design-system showcase. They are NOT generated in the scaffold template. Consumer projects that need them must scaffold their own following the same pattern.
|
|
64
|
-
|
|
65
|
-
All four hooks include the active **language** in their `queryKey` (`['home', 'feature-cards', language]`) so switching language triggers an automatic refetch in the new locale — see [`docs/i18n.md`](./i18n.md#language-aware-react-query-keys).
|
|
66
|
-
|
|
67
|
-
**Swap pattern**: to connect a feature to a real API, replace only the `async function fetch*()` in `data/mock.ts`. The hook, the component, and the type contract remain unchanged.
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
// data/mock.ts — before (mock)
|
|
71
|
-
export async function fetchTeamMembers(): Promise<TeamMember[]> {
|
|
72
|
-
await new Promise(resolve => setTimeout(resolve, 250));
|
|
73
|
-
return MOCK_TEAM_MEMBERS;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// data/mock.ts — after (real API)
|
|
77
|
-
export async function fetchTeamMembers(): Promise<TeamMember[]> {
|
|
78
|
-
return fetch('/api/team/members').then(r => r.json());
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### i18n Layer
|
|
83
|
-
|
|
84
|
-
Internationalization uses `i18next` + `react-i18next`. The setup is bootstrapped in `i18n.ts` (imported in `main.tsx`) and wired to `LanguageContext`:
|
|
85
|
-
|
|
86
|
-
```
|
|
87
|
-
i18n.ts ← configures i18next via import.meta.glob (auto-discovers new JSON files)
|
|
88
|
-
locales/
|
|
89
|
-
├── pt-BR/
|
|
90
|
-
│ ├── common.json ← shared action labels
|
|
91
|
-
│ ├── nav.json ← navigation labels
|
|
92
|
-
│ ├── errors.json ← error boundary UI
|
|
93
|
-
│ ├── languageSelector.json ← language picker UI
|
|
94
|
-
│ ├── themeToggle.json ← theme toggle UI
|
|
95
|
-
│ ├── pages/
|
|
96
|
-
│ │ └── home.json, templates.json, login.json, resetPassword.json, verifyEmail.json,
|
|
97
|
-
│ │ loginTemplate.json, formTemplate.json, dashboardTemplate.json, crudTemplate.json
|
|
98
|
-
│ └── components/
|
|
99
|
-
│ └── assistant.json, sidebar.json, media.json, projectCard.json, profileCard.json,
|
|
100
|
-
│ notificationCard.json, activityCard.json, stats.json, team.json
|
|
101
|
-
├── en/ ← same structure
|
|
102
|
-
└── es/ ← same structure
|
|
103
|
-
contexts/LanguageContext.tsx ← setLanguage() calls i18n.changeLanguage() + persists to localStorage
|
|
104
|
-
components/brand/language-selector/LanguageSelector.tsx ← uses useLanguage() + useTranslation()
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
All page components use `useTranslation()` for UI strings. Mock data functions use `i18n.t()` (the instance) at query time so they respond to the active language.
|
|
108
|
-
|
|
109
|
-
### ErrorBoundary Layer
|
|
110
|
-
|
|
111
|
-
Three pre-configured wrappers for granular error isolation:
|
|
112
|
-
|
|
113
|
-
```
|
|
114
|
-
components/shared/
|
|
115
|
-
├── error-boundary.tsx ← ErrorBoundary class + AppErrorBoundary, PageErrorBoundary, SectionErrorBoundary
|
|
116
|
-
└── error-fallbacks.tsx ← AppErrorFallback, PageErrorFallback, SectionErrorFallback
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Placement in `App.tsx`:
|
|
120
|
-
|
|
121
|
-
```
|
|
122
|
-
AppErrorBoundary (outermost — before QueryClientProvider)
|
|
123
|
-
└─ QueryClientProvider
|
|
124
|
-
└─ ...providers...
|
|
125
|
-
└─ Router
|
|
126
|
-
└─ AuthProvider
|
|
127
|
-
└─ PageErrorBoundary (wraps Routes/AuthGuard)
|
|
128
|
-
└─ Suspense + Routes
|
|
129
|
-
└─ Pages
|
|
130
|
-
└─ SectionErrorBoundary (wraps data sections)
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### AuthContext
|
|
134
|
-
|
|
135
|
-
Authentication state lives in `contexts/AuthContext.tsx` and is consumed via `useAuth()`:
|
|
136
|
-
|
|
137
|
-
```
|
|
138
|
-
contexts/
|
|
139
|
-
└── AuthContext.tsx ← AuthProvider + useAuth() hook
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
`AuthProvider` must be rendered **inside** `<BrowserRouter>` (it uses `useNavigate`). It:
|
|
143
|
-
|
|
144
|
-
- Hydrates session from `localStorage` on mount (`isLoading` flag prevents flash redirects)
|
|
145
|
-
- Exposes `user`, `login(email, password) → boolean`, `logout()`
|
|
146
|
-
- Redirects authenticated users away from auth-only pages automatically
|
|
147
|
-
|
|
148
|
-
Page components (`HomePage`, `TemplatePage`) consume `useAuth()` directly — no `user`/`onLogout` prop drilling.
|
|
149
|
-
|
|
150
|
-
### Lazy Loading
|
|
151
|
-
|
|
152
|
-
All routes in `App.tsx` use `React.lazy()` + `<Suspense>`. Each page is a separate chunk loaded only when the route is first visited:
|
|
153
|
-
|
|
154
|
-
```tsx
|
|
155
|
-
const HomePage = React.lazy(() =>
|
|
156
|
-
import('./components/pages/home-page').then(m => ({ default: m.HomePage }))
|
|
157
|
-
);
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Provider Stack
|
|
161
|
-
|
|
162
|
-
```tsx
|
|
163
|
-
<QueryClientProvider client={queryClient}>
|
|
164
|
-
{' '}
|
|
165
|
-
// ← TanStack React Query
|
|
166
|
-
<ApiKeyProvider>
|
|
167
|
-
<GoogleMapsLoaderProvider>
|
|
168
|
-
<LanguageProvider>
|
|
169
|
-
<BrandColorsProvider>
|
|
170
|
-
<ThemeProvider>
|
|
171
|
-
<AssistenteProvider>
|
|
172
|
-
<LayoutProvider>
|
|
173
|
-
<Router>
|
|
174
|
-
<AuthProvider>
|
|
175
|
-
{' '}
|
|
176
|
-
// ← must be inside Router
|
|
177
|
-
<Suspense fallback={null}>
|
|
178
|
-
<AppRoutes />
|
|
179
|
-
</Suspense>
|
|
180
|
-
</AuthProvider>
|
|
181
|
-
</Router>
|
|
182
|
-
</LayoutProvider>
|
|
183
|
-
</AssistenteProvider>
|
|
184
|
-
</ThemeProvider>
|
|
185
|
-
</BrandColorsProvider>
|
|
186
|
-
</LanguageProvider>
|
|
187
|
-
</GoogleMapsLoaderProvider>
|
|
188
|
-
</ApiKeyProvider>
|
|
189
|
-
</QueryClientProvider>
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### blocks/ domain
|
|
193
|
-
|
|
194
|
-
The `blocks/` domain contains **pre-composed patterns** built exclusively from `ui/` primitives. Unlike primitives, blocks encapsulate specific use-case logic and are ready to drop into dashboards and feature pages without additional composition.
|
|
195
|
-
|
|
196
|
-
```
|
|
197
|
-
components/blocks/
|
|
198
|
-
└── card-patterns/
|
|
199
|
-
├── ActivityCard.tsx — activity feed with avatars and type badges
|
|
200
|
-
├── ProfileCard.tsx — user/member card with stats and actions
|
|
201
|
-
├── ProjectCard.tsx — project status with progress bar and member avatars
|
|
202
|
-
├── QuickActionCard.tsx — icon + title + description + action button
|
|
203
|
-
├── NotificationCard.tsx — notification list with unread indicators
|
|
204
|
-
├── FeatureCard.tsx — colored icon + title + badge + description + CTA
|
|
205
|
-
└── index.ts
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
All block components are exported from both `components/blocks/index.ts` and the root `components/index.ts` barrel.
|
|
209
|
-
|
|
210
|
-
**Consumers can import from the root `xertica-ui` entrypoint (all components) or from granular subpath entries (v2, recommended for FSD/FDA projects).**
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## Subpath Exports (v2)
|
|
215
|
-
|
|
216
|
-
The build system produces 7 distinct entry bundles from a multi-entry Vite `lib.entry` configuration. Each bundle maps to a `package.json` `exports` subpath:
|
|
217
|
-
|
|
218
|
-
| Subpath | Source entry | Contents |
|
|
219
|
-
| ---------------------- | ------------------------------- | -------------------------------------------------------------------------- |
|
|
220
|
-
| `xertica-ui` | `components/index.ts` | Full barrel — all components |
|
|
221
|
-
| `xertica-ui/ui` | `components/ui/index.ts` | All UI primitives |
|
|
222
|
-
| `xertica-ui/blocks` | `components/blocks/index.ts` | High-level composed patterns (ActivityCard, ProjectCard, etc.) |
|
|
223
|
-
| `xertica-ui/layout` | `components/layout/index.ts` | Sidebar, Header |
|
|
224
|
-
| `xertica-ui/brand` | `components/brand/index.ts` | XerticaProvider, XerticaLogo, ThemeToggle, LanguageSelector, etc. |
|
|
225
|
-
| `xertica-ui/assistant` | `components/assistant/index.ts` | XerticaAssistant, MarkdownMessage, CodeBlock, etc. |
|
|
226
|
-
| `xertica-ui/media` | `components/media/index.ts` | VideoPlayer, AudioPlayer, FloatingMediaWrapper |
|
|
227
|
-
| `xertica-ui/hooks` | `components/hooks/index.ts` | useLayout, useTheme, useLanguage, useBrandColors, useAssistente, useApiKey |
|
|
228
|
-
|
|
229
|
-
Each subpath exposes three fields in `exports`: `types` (`.d.ts`), `import` (ES module), `require` (UMD).
|
|
230
|
-
|
|
231
|
-
> TypeScript consumers need `"moduleResolution": "bundler"` (or `"node16"` / `"nodenext"`) to resolve subpath exports.
|
|
232
|
-
|
|
233
|
-
---
|
|
234
|
-
|
|
235
|
-
## Headless UI Pattern (v3)
|
|
236
|
-
|
|
237
|
-
The library follows a **three-tier composability model** for its complex components. Each tier is a superset of the previous — consumers can choose the level of control they need.
|
|
238
|
-
|
|
239
|
-
### Tier 1 — Monolithic API (drop-in)
|
|
240
|
-
|
|
241
|
-
The default export. Zero configuration, full functionality. Ideal for rapid integration.
|
|
242
|
-
|
|
243
|
-
```tsx
|
|
244
|
-
import { Sidebar } from 'xertica-ui/layout';
|
|
245
|
-
import { XerticaAssistant } from 'xertica-ui/assistant';
|
|
246
|
-
import { RichTextEditor } from 'xertica-ui/ui';
|
|
247
|
-
|
|
248
|
-
<Sidebar navigationGroups={groups} />
|
|
249
|
-
<XerticaAssistant demoMode={true} />
|
|
250
|
-
<RichTextEditor value={html} onChange={setHtml} />
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
### Tier 2 — Compound Components (structural control)
|
|
254
|
-
|
|
255
|
-
Sub-components exposed as static properties on the main component. Consumers control layout and composition while the shared React Context handles state propagation.
|
|
256
|
-
|
|
257
|
-
```tsx
|
|
258
|
-
import { Sidebar } from 'xertica-ui/layout';
|
|
259
|
-
|
|
260
|
-
<Sidebar.Root navigationGroups={groups}>
|
|
261
|
-
<Sidebar.Header logo={<MyLogo />} />
|
|
262
|
-
<Sidebar.Nav />
|
|
263
|
-
<Sidebar.Search search={searchConfig} />
|
|
264
|
-
<Sidebar.Footer showUser showSettings />
|
|
265
|
-
</Sidebar.Root>;
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
Available compound components:
|
|
269
|
-
|
|
270
|
-
| Component | Sub-components |
|
|
271
|
-
| --------- | ----------------------------------------------------------------------------------- |
|
|
272
|
-
| `Sidebar` | `Sidebar.Root`, `Sidebar.Header`, `Sidebar.Nav`, `Sidebar.Search`, `Sidebar.Footer` |
|
|
273
|
-
|
|
274
|
-
### Tier 3 — Headless Hooks (full control)
|
|
275
|
-
|
|
276
|
-
Pure logic hooks with zero UI. Consumers bring their own markup, styling, and layout. The hook manages all state, refs, effects, and handlers.
|
|
277
|
-
|
|
278
|
-
```tsx
|
|
279
|
-
import { useSidebar } from 'xertica-ui/layout';
|
|
280
|
-
import { useAssistant } from 'xertica-ui/assistant';
|
|
281
|
-
import { useRichTextEditor } from 'xertica-ui/ui';
|
|
282
|
-
|
|
283
|
-
// Full custom sidebar
|
|
284
|
-
const { expanded, toggleExpanded, navigationGroups } = useSidebar({ defaultExpanded: true });
|
|
285
|
-
|
|
286
|
-
// Full custom assistant
|
|
287
|
-
const { mensagens, mensagem, setMensagem, handleEnviarMensagem } = useAssistant({ demoMode: true });
|
|
288
|
-
|
|
289
|
-
// Full custom editor
|
|
290
|
-
const { editorRef, activeFormats, execCommand, handleInput } = useRichTextEditor({
|
|
291
|
-
value,
|
|
292
|
-
onChange,
|
|
293
|
-
});
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
### Available Headless Hooks
|
|
297
|
-
|
|
298
|
-
| Hook | Import | Description |
|
|
299
|
-
| ------------------- | ---------------------- | ------------------------------------------------------- |
|
|
300
|
-
| `useSidebar` | `xertica-ui/layout` | Sidebar expansion, overflow detection, navigation state |
|
|
301
|
-
| `useAssistant` | `xertica-ui/assistant` | Full assistant state: messages, conversations, handlers |
|
|
302
|
-
| `useRichTextEditor` | `xertica-ui/ui` | Editor formatting state, search, link management |
|
|
303
|
-
|
|
304
|
-
### Design Principles
|
|
305
|
-
|
|
306
|
-
1. **Hooks own all state** — No state lives in the presentational component; it is always delegated to the hook.
|
|
307
|
-
2. **Backward compatible** — The Tier 1 monolithic API is unchanged. Existing consumers are unaffected.
|
|
308
|
-
3. **Single source of truth** — The hook is the canonical implementation. The default component is a thin wrapper around it.
|
|
309
|
-
4. **`useCallback` everywhere** — All handlers in hooks are memoized to prevent unnecessary re-renders in custom UIs.
|
|
310
|
-
5. **TypeScript-first** — Every hook exports a `Props` interface and a `Return` interface for full type safety.
|
|
311
|
-
|
|
312
|
-
---
|
|
1
|
+
# Xertica UI — Architecture
|
|
2
|
+
|
|
3
|
+
## Audit Date
|
|
4
|
+
|
|
5
|
+
2026-05-20 (Post-Modularization + State Layer)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Summary of Changes
|
|
10
|
+
|
|
11
|
+
The library underwent a **complete architectural modularization**. The flat `components/` directory was reorganized into a domain-driven structure, and a dedicated **state layer** was introduced via `features/`, `AuthContext`, TanStack React Query, and Zustand.
|
|
12
|
+
|
|
13
|
+
### Component Domains
|
|
14
|
+
|
|
15
|
+
| Domain | Path | Contains |
|
|
16
|
+
| ----------- | ----------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
17
|
+
| `ui` | `components/ui/[name]/` | Design system primitives (Button, Card, Calendar, Chart, etc.) |
|
|
18
|
+
| `layout` | `components/layout/` | Sidebar, Header, SidebarPrimitive |
|
|
19
|
+
| `blocks` | `components/blocks/` | High-level composed components built from `ui/` primitives |
|
|
20
|
+
| `assistant` | `components/assistant/` | XerticaAssistant, MarkdownMessage, CodeBlock, etc. |
|
|
21
|
+
| `brand` | `components/brand/` | XerticaLogo, ThemeToggle, LanguageSelector, XerticaProvider |
|
|
22
|
+
| `pages` | `components/pages/` | LoginPage, HomePage, TemplatePage, etc. |
|
|
23
|
+
| `shared` | `components/shared/` | utils.ts, use-mobile.ts, layout-constants.ts, navigation.ts, **error-boundary.tsx**, **error-fallbacks.tsx** |
|
|
24
|
+
|
|
25
|
+
### State Layer — `features/`
|
|
26
|
+
|
|
27
|
+
Feature slices separate server state, client UI state, and mock data from the component tree.
|
|
28
|
+
|
|
29
|
+
**Library source** (in this repo, used by Storybook and the showcase pages):
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
features/
|
|
33
|
+
├── home/
|
|
34
|
+
│ ├── data/mock.ts ← typed mock data + async fetch functions (swap point for real API)
|
|
35
|
+
│ ├── hooks/
|
|
36
|
+
│ │ ├── useDashboardStats.ts ← React Query (staleTime 5 min) — library-only
|
|
37
|
+
│ │ ├── useTeamMembers.ts ← React Query (staleTime 2 min) — library-only
|
|
38
|
+
│ │ └── useFeatureCards.ts ← React Query (staleTime 10 min)
|
|
39
|
+
│ ├── store/dashboardStore.ts ← Zustand (progress, slider, activeTab — UI-only)
|
|
40
|
+
│ └── index.ts ← barrel
|
|
41
|
+
└── assistant/
|
|
42
|
+
├── data/mock.ts ← AssistantConfig + fetchAssistantConfig (swap point)
|
|
43
|
+
├── hooks/useAssistantConfig.ts ← React Query (staleTime 30 min)
|
|
44
|
+
└── index.ts ← barrel
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Scaffold template** (what `npx xertica-ui init` generates in a consumer project):
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
src/features/
|
|
51
|
+
├── home/
|
|
52
|
+
│ ├── data/mock.ts
|
|
53
|
+
│ ├── hooks/useFeatureCards.ts ← only useFeatureCards is scaffolded
|
|
54
|
+
│ ├── store/dashboardStore.ts
|
|
55
|
+
│ ├── ui/HomeContent.tsx
|
|
56
|
+
│ └── index.ts
|
|
57
|
+
└── assistant/
|
|
58
|
+
├── data/mock.ts ← exports getMockRichSuggestions() / getMockFeedbackOptions() factories
|
|
59
|
+
├── hooks/useAssistantConfig.ts
|
|
60
|
+
└── index.ts
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
> `useDashboardStats` and `useTeamMembers` exist only in the library source where they power `TemplateContent.tsx`'s design-system showcase. They are NOT generated in the scaffold template. Consumer projects that need them must scaffold their own following the same pattern.
|
|
64
|
+
|
|
65
|
+
All four hooks include the active **language** in their `queryKey` (`['home', 'feature-cards', language]`) so switching language triggers an automatic refetch in the new locale — see [`docs/i18n.md`](./i18n.md#language-aware-react-query-keys).
|
|
66
|
+
|
|
67
|
+
**Swap pattern**: to connect a feature to a real API, replace only the `async function fetch*()` in `data/mock.ts`. The hook, the component, and the type contract remain unchanged.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// data/mock.ts — before (mock)
|
|
71
|
+
export async function fetchTeamMembers(): Promise<TeamMember[]> {
|
|
72
|
+
await new Promise(resolve => setTimeout(resolve, 250));
|
|
73
|
+
return MOCK_TEAM_MEMBERS;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// data/mock.ts — after (real API)
|
|
77
|
+
export async function fetchTeamMembers(): Promise<TeamMember[]> {
|
|
78
|
+
return fetch('/api/team/members').then(r => r.json());
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### i18n Layer
|
|
83
|
+
|
|
84
|
+
Internationalization uses `i18next` + `react-i18next`. The setup is bootstrapped in `i18n.ts` (imported in `main.tsx`) and wired to `LanguageContext`:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
i18n.ts ← configures i18next via import.meta.glob (auto-discovers new JSON files)
|
|
88
|
+
locales/
|
|
89
|
+
├── pt-BR/
|
|
90
|
+
│ ├── common.json ← shared action labels
|
|
91
|
+
│ ├── nav.json ← navigation labels
|
|
92
|
+
│ ├── errors.json ← error boundary UI
|
|
93
|
+
│ ├── languageSelector.json ← language picker UI
|
|
94
|
+
│ ├── themeToggle.json ← theme toggle UI
|
|
95
|
+
│ ├── pages/
|
|
96
|
+
│ │ └── home.json, templates.json, login.json, resetPassword.json, verifyEmail.json,
|
|
97
|
+
│ │ loginTemplate.json, formTemplate.json, dashboardTemplate.json, crudTemplate.json
|
|
98
|
+
│ └── components/
|
|
99
|
+
│ └── assistant.json, sidebar.json, media.json, projectCard.json, profileCard.json,
|
|
100
|
+
│ notificationCard.json, activityCard.json, stats.json, team.json
|
|
101
|
+
├── en/ ← same structure
|
|
102
|
+
└── es/ ← same structure
|
|
103
|
+
contexts/LanguageContext.tsx ← setLanguage() calls i18n.changeLanguage() + persists to localStorage
|
|
104
|
+
components/brand/language-selector/LanguageSelector.tsx ← uses useLanguage() + useTranslation()
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
All page components use `useTranslation()` for UI strings. Mock data functions use `i18n.t()` (the instance) at query time so they respond to the active language.
|
|
108
|
+
|
|
109
|
+
### ErrorBoundary Layer
|
|
110
|
+
|
|
111
|
+
Three pre-configured wrappers for granular error isolation:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
components/shared/
|
|
115
|
+
├── error-boundary.tsx ← ErrorBoundary class + AppErrorBoundary, PageErrorBoundary, SectionErrorBoundary
|
|
116
|
+
└── error-fallbacks.tsx ← AppErrorFallback, PageErrorFallback, SectionErrorFallback
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Placement in `App.tsx`:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
AppErrorBoundary (outermost — before QueryClientProvider)
|
|
123
|
+
└─ QueryClientProvider
|
|
124
|
+
└─ ...providers...
|
|
125
|
+
└─ Router
|
|
126
|
+
└─ AuthProvider
|
|
127
|
+
└─ PageErrorBoundary (wraps Routes/AuthGuard)
|
|
128
|
+
└─ Suspense + Routes
|
|
129
|
+
└─ Pages
|
|
130
|
+
└─ SectionErrorBoundary (wraps data sections)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### AuthContext
|
|
134
|
+
|
|
135
|
+
Authentication state lives in `contexts/AuthContext.tsx` and is consumed via `useAuth()`:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
contexts/
|
|
139
|
+
└── AuthContext.tsx ← AuthProvider + useAuth() hook
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`AuthProvider` must be rendered **inside** `<BrowserRouter>` (it uses `useNavigate`). It:
|
|
143
|
+
|
|
144
|
+
- Hydrates session from `localStorage` on mount (`isLoading` flag prevents flash redirects)
|
|
145
|
+
- Exposes `user`, `login(email, password) → boolean`, `logout()`
|
|
146
|
+
- Redirects authenticated users away from auth-only pages automatically
|
|
147
|
+
|
|
148
|
+
Page components (`HomePage`, `TemplatePage`) consume `useAuth()` directly — no `user`/`onLogout` prop drilling.
|
|
149
|
+
|
|
150
|
+
### Lazy Loading
|
|
151
|
+
|
|
152
|
+
All routes in `App.tsx` use `React.lazy()` + `<Suspense>`. Each page is a separate chunk loaded only when the route is first visited:
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
const HomePage = React.lazy(() =>
|
|
156
|
+
import('./components/pages/home-page').then(m => ({ default: m.HomePage }))
|
|
157
|
+
);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Provider Stack
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
<QueryClientProvider client={queryClient}>
|
|
164
|
+
{' '}
|
|
165
|
+
// ← TanStack React Query
|
|
166
|
+
<ApiKeyProvider>
|
|
167
|
+
<GoogleMapsLoaderProvider>
|
|
168
|
+
<LanguageProvider>
|
|
169
|
+
<BrandColorsProvider>
|
|
170
|
+
<ThemeProvider>
|
|
171
|
+
<AssistenteProvider>
|
|
172
|
+
<LayoutProvider>
|
|
173
|
+
<Router>
|
|
174
|
+
<AuthProvider>
|
|
175
|
+
{' '}
|
|
176
|
+
// ← must be inside Router
|
|
177
|
+
<Suspense fallback={null}>
|
|
178
|
+
<AppRoutes />
|
|
179
|
+
</Suspense>
|
|
180
|
+
</AuthProvider>
|
|
181
|
+
</Router>
|
|
182
|
+
</LayoutProvider>
|
|
183
|
+
</AssistenteProvider>
|
|
184
|
+
</ThemeProvider>
|
|
185
|
+
</BrandColorsProvider>
|
|
186
|
+
</LanguageProvider>
|
|
187
|
+
</GoogleMapsLoaderProvider>
|
|
188
|
+
</ApiKeyProvider>
|
|
189
|
+
</QueryClientProvider>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### blocks/ domain
|
|
193
|
+
|
|
194
|
+
The `blocks/` domain contains **pre-composed patterns** built exclusively from `ui/` primitives. Unlike primitives, blocks encapsulate specific use-case logic and are ready to drop into dashboards and feature pages without additional composition.
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
components/blocks/
|
|
198
|
+
└── card-patterns/
|
|
199
|
+
├── ActivityCard.tsx — activity feed with avatars and type badges
|
|
200
|
+
├── ProfileCard.tsx — user/member card with stats and actions
|
|
201
|
+
├── ProjectCard.tsx — project status with progress bar and member avatars
|
|
202
|
+
├── QuickActionCard.tsx — icon + title + description + action button
|
|
203
|
+
├── NotificationCard.tsx — notification list with unread indicators
|
|
204
|
+
├── FeatureCard.tsx — colored icon + title + badge + description + CTA
|
|
205
|
+
└── index.ts
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
All block components are exported from both `components/blocks/index.ts` and the root `components/index.ts` barrel.
|
|
209
|
+
|
|
210
|
+
**Consumers can import from the root `xertica-ui` entrypoint (all components) or from granular subpath entries (v2, recommended for FSD/FDA projects).**
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Subpath Exports (v2)
|
|
215
|
+
|
|
216
|
+
The build system produces 7 distinct entry bundles from a multi-entry Vite `lib.entry` configuration. Each bundle maps to a `package.json` `exports` subpath:
|
|
217
|
+
|
|
218
|
+
| Subpath | Source entry | Contents |
|
|
219
|
+
| ---------------------- | ------------------------------- | -------------------------------------------------------------------------- |
|
|
220
|
+
| `xertica-ui` | `components/index.ts` | Full barrel — all components |
|
|
221
|
+
| `xertica-ui/ui` | `components/ui/index.ts` | All UI primitives |
|
|
222
|
+
| `xertica-ui/blocks` | `components/blocks/index.ts` | High-level composed patterns (ActivityCard, ProjectCard, etc.) |
|
|
223
|
+
| `xertica-ui/layout` | `components/layout/index.ts` | Sidebar, Header |
|
|
224
|
+
| `xertica-ui/brand` | `components/brand/index.ts` | XerticaProvider, XerticaLogo, ThemeToggle, LanguageSelector, etc. |
|
|
225
|
+
| `xertica-ui/assistant` | `components/assistant/index.ts` | XerticaAssistant, MarkdownMessage, CodeBlock, etc. |
|
|
226
|
+
| `xertica-ui/media` | `components/media/index.ts` | VideoPlayer, AudioPlayer, FloatingMediaWrapper |
|
|
227
|
+
| `xertica-ui/hooks` | `components/hooks/index.ts` | useLayout, useTheme, useLanguage, useBrandColors, useAssistente, useApiKey |
|
|
228
|
+
|
|
229
|
+
Each subpath exposes three fields in `exports`: `types` (`.d.ts`), `import` (ES module), `require` (UMD).
|
|
230
|
+
|
|
231
|
+
> TypeScript consumers need `"moduleResolution": "bundler"` (or `"node16"` / `"nodenext"`) to resolve subpath exports.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Headless UI Pattern (v3)
|
|
236
|
+
|
|
237
|
+
The library follows a **three-tier composability model** for its complex components. Each tier is a superset of the previous — consumers can choose the level of control they need.
|
|
238
|
+
|
|
239
|
+
### Tier 1 — Monolithic API (drop-in)
|
|
240
|
+
|
|
241
|
+
The default export. Zero configuration, full functionality. Ideal for rapid integration.
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
import { Sidebar } from 'xertica-ui/layout';
|
|
245
|
+
import { XerticaAssistant } from 'xertica-ui/assistant';
|
|
246
|
+
import { RichTextEditor } from 'xertica-ui/ui';
|
|
247
|
+
|
|
248
|
+
<Sidebar navigationGroups={groups} />
|
|
249
|
+
<XerticaAssistant demoMode={true} />
|
|
250
|
+
<RichTextEditor value={html} onChange={setHtml} />
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Tier 2 — Compound Components (structural control)
|
|
254
|
+
|
|
255
|
+
Sub-components exposed as static properties on the main component. Consumers control layout and composition while the shared React Context handles state propagation.
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
import { Sidebar } from 'xertica-ui/layout';
|
|
259
|
+
|
|
260
|
+
<Sidebar.Root navigationGroups={groups}>
|
|
261
|
+
<Sidebar.Header logo={<MyLogo />} />
|
|
262
|
+
<Sidebar.Nav />
|
|
263
|
+
<Sidebar.Search search={searchConfig} />
|
|
264
|
+
<Sidebar.Footer showUser showSettings />
|
|
265
|
+
</Sidebar.Root>;
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Available compound components:
|
|
269
|
+
|
|
270
|
+
| Component | Sub-components |
|
|
271
|
+
| --------- | ----------------------------------------------------------------------------------- |
|
|
272
|
+
| `Sidebar` | `Sidebar.Root`, `Sidebar.Header`, `Sidebar.Nav`, `Sidebar.Search`, `Sidebar.Footer` |
|
|
273
|
+
|
|
274
|
+
### Tier 3 — Headless Hooks (full control)
|
|
275
|
+
|
|
276
|
+
Pure logic hooks with zero UI. Consumers bring their own markup, styling, and layout. The hook manages all state, refs, effects, and handlers.
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
import { useSidebar } from 'xertica-ui/layout';
|
|
280
|
+
import { useAssistant } from 'xertica-ui/assistant';
|
|
281
|
+
import { useRichTextEditor } from 'xertica-ui/ui';
|
|
282
|
+
|
|
283
|
+
// Full custom sidebar
|
|
284
|
+
const { expanded, toggleExpanded, navigationGroups } = useSidebar({ defaultExpanded: true });
|
|
285
|
+
|
|
286
|
+
// Full custom assistant
|
|
287
|
+
const { mensagens, mensagem, setMensagem, handleEnviarMensagem } = useAssistant({ demoMode: true });
|
|
288
|
+
|
|
289
|
+
// Full custom editor
|
|
290
|
+
const { editorRef, activeFormats, execCommand, handleInput } = useRichTextEditor({
|
|
291
|
+
value,
|
|
292
|
+
onChange,
|
|
293
|
+
});
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Available Headless Hooks
|
|
297
|
+
|
|
298
|
+
| Hook | Import | Description |
|
|
299
|
+
| ------------------- | ---------------------- | ------------------------------------------------------- |
|
|
300
|
+
| `useSidebar` | `xertica-ui/layout` | Sidebar expansion, overflow detection, navigation state |
|
|
301
|
+
| `useAssistant` | `xertica-ui/assistant` | Full assistant state: messages, conversations, handlers |
|
|
302
|
+
| `useRichTextEditor` | `xertica-ui/ui` | Editor formatting state, search, link management |
|
|
303
|
+
|
|
304
|
+
### Design Principles
|
|
305
|
+
|
|
306
|
+
1. **Hooks own all state** — No state lives in the presentational component; it is always delegated to the hook.
|
|
307
|
+
2. **Backward compatible** — The Tier 1 monolithic API is unchanged. Existing consumers are unaffected.
|
|
308
|
+
3. **Single source of truth** — The hook is the canonical implementation. The default component is a thin wrapper around it.
|
|
309
|
+
4. **`useCallback` everywhere** — All handlers in hooks are memoized to prevent unnecessary re-renders in custom UIs.
|
|
310
|
+
5. **TypeScript-first** — Every hook exports a `Props` interface and a `Return` interface for full type safety.
|
|
311
|
+
|
|
312
|
+
---
|