xertica-ui 2.2.1 → 2.4.0
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 +564 -525
- package/README.md +417 -382
- package/bin/cli.ts +1244 -748
- package/bin/generate-tokens.ts +262 -262
- package/bin/language-config.ts +5 -8
- package/components/assets/xertica-orbe-animation.ts +1162 -1162
- package/components/assistant/code-block/CodeBlock.tsx +268 -268
- package/components/assistant/code-block/code-block.stories.tsx +57 -57
- package/components/assistant/code-block/code-block.test.tsx +44 -44
- package/components/assistant/code-block/index.ts +1 -1
- package/components/assistant/formatted-document/FormattedDocument.tsx +147 -147
- package/components/assistant/formatted-document/formatted-document.stories.tsx +51 -51
- package/components/assistant/formatted-document/formatted-document.test.tsx +42 -42
- package/components/assistant/formatted-document/index.ts +1 -1
- package/components/assistant/index.ts +6 -6
- package/components/assistant/markdown-message/MarkdownMessage.tsx +152 -152
- package/components/assistant/markdown-message/index.ts +1 -1
- package/components/assistant/markdown-message/markdown-message.stories.tsx +50 -50
- package/components/assistant/markdown-message/markdown-message.test.tsx +33 -33
- package/components/assistant/modern-chat-input/ModernChatInput.tsx +17 -7
- package/components/assistant/modern-chat-input/index.ts +1 -1
- package/components/assistant/modern-chat-input/modern-chat-input.stories.tsx +131 -131
- package/components/assistant/modern-chat-input/modern-chat-input.test.tsx +79 -79
- package/components/assistant/xertica-assistant/index.ts +3 -3
- package/components/assistant/xertica-assistant/parts/AssistantCollapsedView.tsx +99 -99
- package/components/assistant/xertica-assistant/parts/AssistantConversationList.tsx +104 -106
- package/components/assistant/xertica-assistant/parts/AssistantDocumentEditor.tsx +81 -81
- package/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.tsx +88 -78
- package/components/assistant/xertica-assistant/parts/AssistantHeader.tsx +75 -75
- package/components/assistant/xertica-assistant/parts/AssistantMessageBubble.tsx +564 -560
- package/components/assistant/xertica-assistant/parts/AssistantTabBar.tsx +67 -67
- package/components/assistant/xertica-assistant/parts/AssistantTypingIndicator.tsx +41 -41
- package/components/assistant/xertica-assistant/parts/AssistantWelcomeScreen.tsx +103 -103
- package/components/assistant/xertica-assistant/parts/index.ts +16 -16
- package/components/assistant/xertica-assistant/types.ts +134 -134
- package/components/assistant/xertica-assistant/use-assistant.ts +615 -615
- package/components/assistant/xertica-assistant/xertica-assistant.stories.tsx +407 -407
- package/components/assistant/xertica-assistant/xertica-assistant.test.tsx +65 -65
- package/components/assistant/xertica-assistant/xertica-assistant.tsx +611 -613
- package/components/blocks/card-patterns/ActivityCard.tsx +100 -100
- package/components/blocks/card-patterns/FeatureCard.tsx +109 -109
- package/components/blocks/card-patterns/FeatureCardSkeleton.tsx +1 -6
- package/components/blocks/card-patterns/NotificationCard.tsx +140 -140
- package/components/blocks/card-patterns/ProfileCard.tsx +112 -114
- package/components/blocks/card-patterns/ProjectCard.tsx +123 -123
- package/components/blocks/card-patterns/ProjectCardSkeleton.tsx +1 -6
- package/components/blocks/card-patterns/QuickActionCard.tsx +68 -68
- package/components/blocks/card-patterns/card-patterns.mdx +123 -123
- package/components/blocks/card-patterns/card-patterns.stories.tsx +594 -594
- package/components/blocks/card-patterns/index.ts +29 -29
- package/components/blocks/index.ts +1 -1
- package/components/brand/branding/branding.stories.tsx +57 -57
- package/components/brand/index.ts +6 -6
- package/components/brand/language-selector/index.ts +1 -1
- package/components/brand/language-selector/language-selector.mdx +126 -126
- package/components/brand/language-selector/language-selector.stories.tsx +1 -4
- package/components/brand/theme-toggle/ThemeToggle.tsx +74 -70
- package/components/brand/theme-toggle/index.ts +1 -1
- package/components/brand/theme-toggle/theme-toggle.stories.tsx +34 -34
- package/components/brand/theme-toggle/theme-toggle.test.tsx +34 -34
- package/components/brand/xertica-logo/XerticaLogo.stories.tsx +82 -82
- package/components/brand/xertica-logo/XerticaLogo.tsx +104 -104
- package/components/brand/xertica-logo/index.ts +1 -1
- package/components/brand/xertica-logo/xertica-logo.test.tsx +26 -26
- package/components/brand/xertica-orbe/XerticaOrbe.tsx +1927 -1927
- package/components/brand/xertica-orbe/index.ts +1 -1
- package/components/brand/xertica-orbe/xertica-orbe.stories.tsx +40 -40
- package/components/brand/xertica-orbe/xertica-orbe.test.tsx +19 -19
- package/components/brand/xertica-provider/XerticaProvider.tsx +1 -4
- package/components/brand/xertica-provider/index.ts +1 -1
- package/components/brand/xertica-provider/xertica-provider.test.tsx +74 -74
- package/components/brand/xertica-xlogo/XerticaXLogo.stories.tsx +79 -79
- package/components/brand/xertica-xlogo/XerticaXLogo.tsx +65 -65
- package/components/brand/xertica-xlogo/index.ts +1 -1
- package/components/brand/xertica-xlogo/xertica-xlogo.test.tsx +16 -16
- package/components/examples/ApiKeyMapExample.tsx +71 -71
- package/components/examples/DrawingMapExample.tsx +565 -565
- package/components/examples/FilterableMapExample.tsx +393 -393
- package/components/examples/LocationPickerExample.tsx +348 -348
- package/components/examples/MapExamples.tsx +268 -268
- package/components/examples/MapGmpExample.tsx +169 -169
- package/components/examples/MapShowcase.tsx +471 -471
- package/components/examples/RouteMapExamples.tsx +329 -329
- package/components/examples/SidebarLogoExample.tsx +65 -65
- package/components/examples/SimpleFilterableMap.tsx +219 -219
- package/components/examples/index.ts +45 -45
- package/components/figma/ImageWithFallback.tsx +27 -27
- package/components/hooks/index.ts +13 -13
- package/components/hooks/use-layout-shortcuts.ts +43 -43
- package/components/index.ts +86 -90
- package/components/layout/header/header.stories.tsx +204 -204
- package/components/layout/header/header.test.tsx +75 -75
- package/components/layout/header/header.tsx +349 -349
- package/components/layout/header/index.ts +1 -1
- package/components/layout/index.ts +2 -2
- package/components/layout/sidebar/index.ts +3 -3
- package/components/layout/sidebar/sidebar.stories.tsx +586 -586
- package/components/layout/sidebar/sidebar.test.tsx +76 -76
- package/components/layout/sidebar/sidebar.tsx +1079 -1073
- package/components/layout/sidebar/use-sidebar.ts +104 -104
- package/components/media/FloatingMediaWrapper.tsx +371 -371
- package/components/media/audio-player/AudioPlayer.stories.tsx +124 -124
- package/components/media/audio-player/AudioPlayer.test.tsx +106 -106
- package/components/media/audio-player/AudioPlayer.tsx +767 -765
- package/components/media/audio-player/index.ts +1 -1
- package/components/media/audio-player/use-audio-player.ts +312 -312
- package/components/media/index.ts +3 -3
- package/components/media/video-player/VideoPlayer.stories.tsx +98 -98
- package/components/media/video-player/VideoPlayer.test.tsx +73 -73
- package/components/media/video-player/VideoPlayer.tsx +310 -310
- package/components/media/video-player/index.ts +1 -1
- package/components/pages/forgot-password-page/ForgotPasswordPage.stories.tsx +24 -24
- package/components/pages/forgot-password-page/ForgotPasswordPage.tsx +188 -188
- package/components/pages/forgot-password-page/forgot-password-page.test.tsx +45 -45
- package/components/pages/forgot-password-page/index.ts +1 -1
- package/components/pages/home-content/HomeContent.stories.tsx +43 -43
- package/components/pages/home-content/HomeContent.tsx +120 -120
- package/components/pages/home-content/index.ts +1 -1
- package/components/pages/home-page/HomePage.stories.tsx +39 -39
- package/components/pages/home-page/HomePage.tsx +78 -74
- package/components/pages/home-page/home-page.test.tsx +53 -53
- package/components/pages/home-page/index.ts +1 -1
- package/components/pages/index.ts +8 -8
- package/components/pages/login-page/LoginPage.stories.tsx +39 -39
- package/components/pages/login-page/LoginPage.tsx +218 -216
- package/components/pages/login-page/index.ts +1 -1
- package/components/pages/login-page/login-page.test.tsx +63 -63
- package/components/pages/reset-password-page/ResetPasswordPage.stories.tsx +24 -24
- package/components/pages/reset-password-page/ResetPasswordPage.tsx +243 -239
- package/components/pages/reset-password-page/index.ts +1 -1
- package/components/pages/template-content/TemplateContent.stories.tsx +43 -43
- package/components/pages/template-content/TemplateContent.tsx +1354 -1235
- package/components/pages/template-content/index.ts +1 -1
- package/components/pages/template-page/TemplatePage.stories.tsx +39 -39
- package/components/pages/template-page/TemplatePage.tsx +62 -62
- package/components/pages/template-page/index.ts +1 -1
- package/components/pages/template-page/template-page.test.tsx +52 -52
- package/components/pages/verify-email-page/VerifyEmailPage.stories.tsx +41 -41
- package/components/pages/verify-email-page/VerifyEmailPage.tsx +206 -206
- package/components/pages/verify-email-page/index.ts +1 -1
- package/components/public-api-smoke.test.tsx +52 -52
- package/components/shared/CustomTooltipContent.tsx +48 -48
- package/components/shared/assistant-utils.test.ts +16 -16
- package/components/shared/assistant-utils.ts +225 -225
- package/components/shared/error-boundary.stories.tsx +114 -132
- package/components/shared/error-boundary.tsx +150 -154
- package/components/shared/error-fallbacks.tsx +222 -226
- package/components/shared/layout-constants.ts +8 -8
- package/components/shared/navigation.ts +35 -35
- package/components/shared/use-mobile.test.ts +16 -16
- package/components/shared/use-mobile.ts +36 -36
- package/components/shared/utils.test.ts +14 -14
- package/components/shared/utils.ts +6 -6
- package/components/ui/accordion/accordion.stories.tsx +105 -105
- package/components/ui/accordion/accordion.test.tsx +59 -59
- package/components/ui/accordion/accordion.tsx +77 -77
- package/components/ui/accordion/index.ts +1 -1
- package/components/ui/alert/alert.stories.tsx +86 -86
- package/components/ui/alert/alert.test.tsx +53 -53
- package/components/ui/alert/alert.tsx +93 -93
- package/components/ui/alert/index.ts +1 -1
- package/components/ui/alert-dialog/alert-dialog.stories.tsx +84 -84
- package/components/ui/alert-dialog/alert-dialog.test.tsx +70 -70
- package/components/ui/alert-dialog/alert-dialog.tsx +149 -149
- package/components/ui/alert-dialog/index.ts +1 -1
- package/components/ui/aspect-ratio/aspect-ratio.stories.tsx +46 -46
- package/components/ui/aspect-ratio/aspect-ratio.test.tsx +28 -28
- package/components/ui/aspect-ratio/aspect-ratio.tsx +20 -20
- package/components/ui/aspect-ratio/index.ts +1 -1
- package/components/ui/assistant-chart/AssistantChart.tsx +64 -64
- package/components/ui/assistant-chart/assistant-chart.stories.tsx +44 -44
- package/components/ui/assistant-chart/assistant-chart.test.tsx +46 -46
- package/components/ui/assistant-chart/index.ts +1 -1
- package/components/ui/avatar/avatar.stories.tsx +86 -86
- package/components/ui/avatar/avatar.test.tsx +55 -55
- package/components/ui/avatar/avatar.tsx +71 -71
- package/components/ui/avatar/index.ts +1 -1
- package/components/ui/badge/badge.stories.tsx +72 -72
- package/components/ui/badge/badge.test.tsx +40 -40
- package/components/ui/badge/badge.tsx +58 -58
- package/components/ui/badge/index.ts +1 -1
- package/components/ui/breadcrumb/breadcrumb.stories.tsx +123 -123
- package/components/ui/breadcrumb/breadcrumb.test.tsx +70 -70
- package/components/ui/breadcrumb/breadcrumb.tsx +114 -114
- package/components/ui/breadcrumb/index.ts +1 -1
- package/components/ui/button/button.stories.tsx +183 -183
- package/components/ui/button/button.test.tsx +64 -64
- package/components/ui/button/button.tsx +98 -98
- package/components/ui/button/index.ts +1 -1
- package/components/ui/calendar/calendar.stories.tsx +108 -108
- package/components/ui/calendar/calendar.test.tsx +53 -53
- package/components/ui/calendar/calendar.tsx +230 -230
- package/components/ui/calendar/index.ts +1 -1
- package/components/ui/card/card.stories.tsx +301 -301
- package/components/ui/card/card.test.tsx +55 -55
- package/components/ui/card/card.tsx +83 -83
- package/components/ui/card/index.ts +1 -1
- package/components/ui/carousel/carousel.stories.tsx +80 -80
- package/components/ui/carousel/carousel.test.tsx +75 -75
- package/components/ui/carousel/carousel.tsx +242 -242
- package/components/ui/carousel/index.ts +1 -1
- package/components/ui/chart/chart.stories.tsx +1328 -1328
- package/components/ui/chart/chart.test.tsx +178 -178
- package/components/ui/chart/chart.tsx +2232 -2232
- package/components/ui/chart/index.ts +1 -1
- package/components/ui/checkbox/checkbox.stories.tsx +109 -109
- package/components/ui/checkbox/checkbox.test.tsx +49 -49
- package/components/ui/checkbox/checkbox.tsx +68 -68
- package/components/ui/checkbox/index.ts +1 -1
- package/components/ui/collapsible/collapsible.stories.tsx +45 -45
- package/components/ui/collapsible/collapsible.test.tsx +51 -51
- package/components/ui/collapsible/collapsible.tsx +32 -32
- package/components/ui/collapsible/index.ts +1 -1
- package/components/ui/command/command.stories.tsx +134 -134
- package/components/ui/command/command.test.tsx +48 -48
- package/components/ui/command/command.tsx +163 -163
- package/components/ui/command/index.ts +1 -1
- package/components/ui/context-menu/context-menu.stories.tsx +76 -76
- package/components/ui/context-menu/context-menu.test.tsx +61 -61
- package/components/ui/context-menu/context-menu.tsx +236 -236
- package/components/ui/context-menu/index.ts +1 -1
- package/components/ui/dialog/dialog.stories.tsx +174 -174
- package/components/ui/dialog/dialog.test.tsx +78 -78
- package/components/ui/dialog/dialog.tsx +189 -189
- package/components/ui/dialog/index.ts +1 -1
- package/components/ui/drawer/drawer.stories.tsx +71 -71
- package/components/ui/drawer/drawer.test.tsx +67 -67
- package/components/ui/drawer/drawer.tsx +146 -146
- package/components/ui/drawer/index.ts +1 -1
- package/components/ui/dropdown-menu/dropdown-menu.stories.tsx +156 -156
- package/components/ui/dropdown-menu/dropdown-menu.test.tsx +62 -62
- package/components/ui/dropdown-menu/dropdown-menu.tsx +240 -240
- package/components/ui/dropdown-menu/index.ts +1 -1
- package/components/ui/empty/empty.stories.tsx +85 -85
- package/components/ui/empty/empty.test.tsx +31 -31
- package/components/ui/empty/empty.tsx +88 -88
- package/components/ui/empty/index.ts +1 -1
- package/components/ui/file-upload/file-upload.stories.tsx +144 -144
- package/components/ui/file-upload/file-upload.test.tsx +65 -65
- package/components/ui/file-upload/file-upload.tsx +142 -142
- package/components/ui/file-upload/index.ts +2 -2
- package/components/ui/file-upload/use-file-upload.ts +177 -177
- package/components/ui/form/form.stories.tsx +85 -85
- package/components/ui/form/form.test.tsx +75 -75
- package/components/ui/form/form.tsx +163 -163
- package/components/ui/form/index.ts +1 -1
- package/components/ui/google-maps-loader/google-maps-loader.test.tsx +35 -35
- package/components/ui/google-maps-loader/google-maps-loader.tsx +465 -465
- package/components/ui/google-maps-loader/index.ts +1 -1
- package/components/ui/hover-card/hover-card.stories.tsx +61 -61
- package/components/ui/hover-card/hover-card.test.tsx +48 -48
- package/components/ui/hover-card/hover-card.tsx +50 -50
- package/components/ui/hover-card/index.ts +1 -1
- package/components/ui/index.ts +400 -400
- package/components/ui/input/index.ts +1 -1
- package/components/ui/input/input.stories.tsx +153 -153
- package/components/ui/input/input.test.tsx +47 -47
- package/components/ui/input/input.tsx +57 -57
- package/components/ui/input-otp/index.ts +1 -1
- package/components/ui/input-otp/input-otp.stories.tsx +120 -120
- package/components/ui/input-otp/input-otp.test.tsx +74 -74
- package/components/ui/input-otp/input-otp.tsx +101 -101
- package/components/ui/label/index.ts +1 -1
- package/components/ui/label/label.stories.tsx +74 -74
- package/components/ui/label/label.test.tsx +45 -45
- package/components/ui/label/label.tsx +53 -53
- package/components/ui/map/index.ts +1 -1
- package/components/ui/map/map.stories.tsx +86 -86
- package/components/ui/map/map.test.tsx +82 -82
- package/components/ui/map/map.tsx +506 -506
- package/components/ui/map/mock.test.tsx +13 -13
- package/components/ui/map-config/index.ts +1 -1
- package/components/ui/map-config/map-config.ts +18 -18
- package/components/ui/map-layers/index.ts +1 -1
- package/components/ui/map-layers/map-layers.test.tsx +48 -48
- package/components/ui/map-layers/map-layers.tsx +126 -126
- package/components/ui/map.exports/index.ts +1 -1
- package/components/ui/map.exports/map.exports.ts +31 -31
- package/components/ui/menubar/index.ts +1 -1
- package/components/ui/menubar/menubar.stories.tsx +130 -130
- package/components/ui/menubar/menubar.test.tsx +53 -53
- package/components/ui/menubar/menubar.tsx +265 -265
- package/components/ui/navigation-menu/index.ts +1 -1
- package/components/ui/navigation-menu/navigation-menu.stories.tsx +126 -126
- package/components/ui/navigation-menu/navigation-menu.test.tsx +47 -47
- package/components/ui/navigation-menu/navigation-menu.tsx +165 -165
- package/components/ui/notification-badge/index.ts +1 -1
- package/components/ui/notification-badge/notification-badge.stories.tsx +66 -66
- package/components/ui/notification-badge/notification-badge.test.tsx +61 -61
- package/components/ui/notification-badge/notification-badge.tsx +91 -91
- package/components/ui/page-header/index.ts +1 -1
- package/components/ui/page-header/page-header.stories.tsx +69 -69
- package/components/ui/page-header/page-header.test.tsx +37 -37
- package/components/ui/page-header/page-header.tsx +124 -124
- package/components/ui/pagination/index.ts +3 -3
- package/components/ui/pagination/pagination.stories.tsx +210 -210
- package/components/ui/pagination/pagination.test.tsx +63 -63
- package/components/ui/pagination/pagination.tsx +140 -140
- package/components/ui/pagination/use-pagination.ts +173 -173
- package/components/ui/popover/index.ts +1 -1
- package/components/ui/popover/popover.stories.tsx +73 -73
- package/components/ui/popover/popover.test.tsx +48 -48
- package/components/ui/popover/popover.tsx +54 -54
- package/components/ui/progress/index.ts +1 -1
- package/components/ui/progress/progress.stories.tsx +55 -55
- package/components/ui/progress/progress.test.tsx +23 -23
- package/components/ui/progress/progress.tsx +68 -68
- package/components/ui/radio-group/index.ts +1 -1
- package/components/ui/radio-group/radio-group.stories.tsx +114 -114
- package/components/ui/radio-group/radio-group.test.tsx +78 -78
- package/components/ui/radio-group/radio-group.tsx +93 -93
- package/components/ui/rating/index.ts +1 -1
- package/components/ui/rating/rating.stories.tsx +50 -50
- package/components/ui/rating/rating.test.tsx +48 -48
- package/components/ui/rating/rating.tsx +145 -145
- package/components/ui/resizable/index.ts +1 -1
- package/components/ui/resizable/resizable.stories.tsx +88 -88
- package/components/ui/resizable/resizable.test.tsx +61 -61
- package/components/ui/resizable/resizable.tsx +452 -452
- package/components/ui/rich-text-editor/index.ts +7 -7
- package/components/ui/rich-text-editor/rich-text-editor.stories.tsx +290 -290
- package/components/ui/rich-text-editor/rich-text-editor.test.tsx +86 -86
- package/components/ui/rich-text-editor/rich-text-editor.tsx +634 -634
- package/components/ui/rich-text-editor/use-rich-text-editor.ts +453 -453
- package/components/ui/route-map/index.ts +1 -1
- package/components/ui/route-map/route-map.stories.tsx +48 -48
- package/components/ui/route-map/route-map.test.tsx +108 -108
- package/components/ui/route-map/route-map.tsx +349 -349
- package/components/ui/scroll-area/index.ts +1 -1
- package/components/ui/scroll-area/scroll-area.stories.tsx +31 -31
- package/components/ui/scroll-area/scroll-area.test.tsx +27 -27
- package/components/ui/scroll-area/scroll-area.tsx +70 -70
- package/components/ui/search/index.ts +1 -1
- package/components/ui/search/search.stories.tsx +107 -107
- package/components/ui/search/search.test.tsx +67 -67
- package/components/ui/search/search.tsx +141 -141
- package/components/ui/select/index.ts +1 -1
- package/components/ui/select/select.stories.tsx +163 -163
- package/components/ui/select/select.test.tsx +99 -99
- package/components/ui/select/select.tsx +195 -195
- package/components/ui/separator/index.ts +1 -1
- package/components/ui/separator/separator.stories.tsx +55 -55
- package/components/ui/separator/separator.test.tsx +23 -23
- package/components/ui/separator/separator.tsx +39 -39
- package/components/ui/sheet/index.ts +1 -1
- package/components/ui/sheet/sheet.stories.tsx +93 -93
- package/components/ui/sheet/sheet.test.tsx +62 -62
- package/components/ui/sheet/sheet.tsx +149 -149
- package/components/ui/simple-map/index.ts +1 -1
- package/components/ui/simple-map/simple-map.stories.tsx +44 -44
- package/components/ui/simple-map/simple-map.test.tsx +36 -36
- package/components/ui/simple-map/simple-map.tsx +92 -92
- package/components/ui/skeleton/index.ts +1 -1
- package/components/ui/skeleton/skeleton.stories.tsx +36 -36
- package/components/ui/skeleton/skeleton.test.tsx +19 -19
- package/components/ui/skeleton/skeleton.tsx +25 -25
- package/components/ui/slider/index.ts +1 -1
- package/components/ui/slider/slider.stories.tsx +44 -44
- package/components/ui/slider/slider.test.tsx +25 -25
- package/components/ui/slider/slider.tsx +66 -66
- package/components/ui/sonner/index.ts +1 -1
- package/components/ui/sonner/sonner.stories.tsx +41 -41
- package/components/ui/sonner/sonner.test.tsx +24 -24
- package/components/ui/sonner/sonner.tsx +74 -74
- package/components/ui/stats-card/index.ts +2 -2
- package/components/ui/stats-card/stats-card-skeleton.tsx +1 -3
- package/components/ui/stats-card/stats-card.stories.tsx +99 -99
- package/components/ui/stats-card/stats-card.test.tsx +34 -34
- package/components/ui/stats-card/stats-card.tsx +93 -93
- package/components/ui/stepper/index.ts +3 -3
- package/components/ui/stepper/stepper.stories.tsx +171 -171
- package/components/ui/stepper/stepper.test.tsx +47 -47
- package/components/ui/stepper/stepper.tsx +190 -190
- package/components/ui/stepper/use-stepper.ts +139 -139
- package/components/ui/switch/index.ts +1 -1
- package/components/ui/switch/switch.stories.tsx +93 -93
- package/components/ui/switch/switch.test.tsx +44 -44
- package/components/ui/switch/switch.tsx +70 -70
- package/components/ui/table/index.ts +1 -1
- package/components/ui/table/table.stories.tsx +114 -114
- package/components/ui/table/table.test.tsx +43 -43
- package/components/ui/table/table.tsx +104 -104
- package/components/ui/tabs/index.ts +1 -1
- package/components/ui/tabs/tabs.stories.tsx +140 -140
- package/components/ui/tabs/tabs.test.tsx +50 -50
- package/components/ui/tabs/tabs.tsx +66 -66
- package/components/ui/textarea/index.ts +1 -1
- package/components/ui/textarea/textarea.stories.tsx +69 -69
- package/components/ui/textarea/textarea.test.tsx +41 -41
- package/components/ui/textarea/textarea.tsx +61 -61
- package/components/ui/timeline/index.ts +1 -1
- package/components/ui/timeline/timeline.stories.tsx +97 -97
- package/components/ui/timeline/timeline.test.tsx +53 -53
- package/components/ui/timeline/timeline.tsx +124 -124
- package/components/ui/toggle/index.ts +1 -1
- package/components/ui/toggle/toggle.stories.tsx +56 -56
- package/components/ui/toggle/toggle.test.tsx +32 -32
- package/components/ui/toggle/toggle.tsx +55 -55
- package/components/ui/toggle-group/index.ts +1 -1
- package/components/ui/toggle-group/toggle-group.stories.tsx +66 -66
- package/components/ui/toggle-group/toggle-group.test.tsx +47 -47
- package/components/ui/toggle-group/toggle-group.tsx +79 -79
- package/components/ui/tooltip/index.ts +1 -1
- package/components/ui/tooltip/tooltip.stories.tsx +83 -83
- package/components/ui/tooltip/tooltip.test.tsx +39 -39
- package/components/ui/tooltip/tooltip.tsx +69 -69
- package/components/ui/tree-view/index.ts +4 -4
- package/components/ui/tree-view/tree-view.stories.tsx +154 -154
- package/components/ui/tree-view/tree-view.test.tsx +58 -58
- package/components/ui/tree-view/tree-view.tsx +171 -171
- package/components/ui/tree-view/use-tree-view.ts +237 -237
- package/components.json +892 -892
- package/contexts/ApiKeyContext.test.tsx +26 -26
- package/contexts/ApiKeyContext.tsx +196 -196
- package/contexts/AssistenteContext.test.tsx +17 -17
- package/contexts/AssistenteContext.tsx +113 -113
- package/contexts/AuthContext.tsx +121 -118
- package/contexts/BrandColorsContext.test.tsx +21 -21
- package/contexts/BrandColorsContext.tsx +251 -251
- package/contexts/LanguageContext.tsx +1 -2
- package/contexts/LayoutContext.test.tsx +29 -29
- package/contexts/LayoutContext.tsx +140 -140
- package/contexts/ThemeContext.test.tsx +38 -38
- package/contexts/ThemeContext.tsx +111 -111
- package/contexts/index.ts +8 -8
- package/contexts/theme-data.ts +340 -340
- package/dist/AssistantChart-COGiOV-g.cjs +3541 -0
- package/dist/AssistantChart-CWX1OWNM.js +3373 -0
- package/dist/AudioPlayer-9psiEucT.cjs +1282 -0
- package/dist/AudioPlayer-Dp2bD1Gk.js +1278 -0
- package/dist/BrandColorsContext-DZT7JjeD.js +659 -0
- package/dist/BrandColorsContext-awnBCmC4.cjs +666 -0
- package/dist/CodeBlock-DYkTfR0f.js +221 -0
- package/dist/CodeBlock-EOvp9cVu.cjs +223 -0
- package/dist/CustomTooltipContent-BhdIeBEg.cjs +54 -0
- package/dist/CustomTooltipContent-CNbVB2NS.js +33 -0
- package/dist/FeatureCard-BZ4CYxFf.cjs +497 -0
- package/dist/FeatureCard-DNycVGwT.js +485 -0
- package/dist/FeatureCardSkeleton-DZqc96mt.js +27 -0
- package/dist/FeatureCardSkeleton-pTa0YNKP.cjs +29 -0
- package/dist/LayoutContext-BEq_-n98.cjs +96 -0
- package/dist/LayoutContext-DNl1xSoX.js +92 -0
- package/dist/ThemeContext-CMD3z2Dz.cjs +1930 -0
- package/dist/ThemeContext-x_F2zsnv.js +1923 -0
- package/dist/VerifyEmailPage-BJjAMUTW.js +3223 -0
- package/dist/VerifyEmailPage-Bv8Ah_TK.cjs +3235 -0
- package/dist/VerifyEmailPage-CkBYfsNy.cjs +3232 -0
- package/dist/VerifyEmailPage-Cyl55sJb.js +3226 -0
- package/dist/VerifyEmailPage-X14vhdyl.js +3296 -0
- package/dist/VerifyEmailPage-u_Dn7t1U.cjs +3305 -0
- package/dist/XerticaOrbe-Uk2JML1-.cjs +1927 -0
- package/dist/XerticaOrbe-jA5T2iOk.js +1925 -0
- package/dist/XerticaProvider-BErr83Bg.js +42 -0
- package/dist/XerticaProvider-CwOkHxiT.cjs +44 -0
- package/dist/XerticaProvider-DUOJg9iX.js +49 -0
- package/dist/XerticaProvider-Dl_b72_l.cjs +51 -0
- package/dist/XerticaXLogo-BX3ueACh.js +255 -0
- package/dist/XerticaXLogo-mqjoBiLI.js +252 -0
- package/dist/XerticaXLogo-qBPhwK3g.cjs +260 -0
- package/dist/XerticaXLogo-uQgwns_E.cjs +257 -0
- package/dist/alert-dialog-DhwPioBa.cjs +885 -0
- package/dist/alert-dialog-DqlRW_An.js +831 -0
- package/dist/assistant.cjs.js +8 -4
- package/dist/assistant.es.js +5 -11
- package/dist/avatar-3kO2Anrp.js +54 -0
- package/dist/avatar-BCM7YQRC.cjs +77 -0
- package/dist/blocks.cjs.js +9 -4
- package/dist/blocks.es.js +2 -16
- package/dist/brand.cjs.js +10 -5
- package/dist/brand.es.js +3 -11
- package/dist/breadcrumb-BKtHF4gk.cjs +98 -0
- package/dist/breadcrumb-ifNsA7Zl.js +90 -0
- package/dist/button-0BlA47It.cjs +85 -0
- package/dist/button-DZHzN1Gd.js +62 -0
- package/dist/cli.js +471 -93
- package/dist/components/brand/theme-toggle/ThemeToggle.d.ts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/dropdown-menu-BMcykFDf.cjs +225 -0
- package/dist/dropdown-menu-Dn_eV2Xb.js +190 -0
- package/dist/google-maps-loader-BCe58h9D.js +308 -0
- package/dist/google-maps-loader-casMyxlo.cjs +316 -0
- package/dist/hooks.cjs.js +12 -8
- package/dist/hooks.es.js +10 -27
- package/dist/index-9GWd0qxq.cjs +12 -0
- package/dist/index-BabBx2pa.js +6 -0
- package/dist/index.cjs.js +37 -32
- package/dist/index.es.js +30 -363
- package/dist/input-C_UiS2Py.cjs +152 -0
- package/dist/input-cc-PTD4R.js +123 -0
- package/dist/layout.cjs.js +10 -6
- package/dist/layout.es.js +7 -9
- package/dist/media.cjs.js +8 -3
- package/dist/media.es.js +1 -6
- package/dist/pages.cjs.js +8 -3
- package/dist/pages.es.js +1 -11
- package/dist/progress-C7Lti5wo.js +80 -0
- package/dist/progress-Cqwxbqs1.cjs +103 -0
- package/dist/rich-text-editor-DqLICivI.js +2832 -0
- package/dist/rich-text-editor-DxO1Hz3a.cjs +2903 -0
- package/dist/select-CH6v_KcQ.cjs +161 -0
- package/dist/select-D-xvCZK2.js +130 -0
- package/dist/sidebar-3XyzjVBw.js +792 -0
- package/dist/sidebar-B4ZWaMrE.js +792 -0
- package/dist/sidebar-BS1p2V7t.cjs +795 -0
- package/dist/sidebar-DyYvgyBj.cjs +795 -0
- package/dist/skeleton-DjiHerJn.cjs +87 -0
- package/dist/skeleton-DtR5tkYe.js +78 -0
- package/dist/slider-B00b9SVK.cjs +78 -0
- package/dist/slider-DQCNUUMj.js +56 -0
- package/dist/sonner-B-jWlik1.cjs +68 -0
- package/dist/sonner-C9tiqj4f.js +47 -0
- package/dist/tooltip-D8n9UYoU.cjs +72 -0
- package/dist/tooltip-RtbSmPYJ.js +48 -0
- package/dist/ui.cjs.js +23 -18
- package/dist/ui.es.js +16 -303
- package/dist/use-audio-player-B78fd2ct.js +188 -0
- package/dist/use-audio-player-DGvhPrgR.cjs +190 -0
- package/dist/use-mobile-BdXTRb0Z.cjs +51 -0
- package/dist/use-mobile-Ce2cBAQe.js +29 -0
- package/dist/xertica-assistant-B1NaSFFj.js +2173 -0
- package/dist/xertica-assistant-B687qEPU.js +2165 -0
- package/dist/xertica-assistant-CIaUlbIt.cjs +2180 -0
- package/dist/xertica-assistant-sOHwTgIP.cjs +2172 -0
- package/dist/xertica-ui.css +1 -1
- package/docs/ai-usage.md +195 -195
- package/docs/architecture-improvements.md +456 -456
- package/docs/architecture.md +312 -306
- package/docs/components/accordion.md +109 -109
- package/docs/components/alert-dialog.md +127 -127
- package/docs/components/alert.md +106 -106
- package/docs/components/aspect-ratio.md +58 -58
- package/docs/components/assistant-chart.md +47 -47
- package/docs/components/assistant.md +428 -426
- package/docs/components/audio-player.md +167 -167
- package/docs/components/avatar.md +101 -101
- package/docs/components/badge.md +84 -84
- package/docs/components/branding.md +252 -252
- package/docs/components/breadcrumb.md +104 -104
- package/docs/components/button.md +156 -156
- package/docs/components/calendar.md +141 -141
- package/docs/components/card-patterns.md +447 -445
- package/docs/components/card.md +245 -245
- package/docs/components/carousel.md +100 -100
- package/docs/components/chart.md +638 -638
- package/docs/components/checkbox.md +88 -88
- package/docs/components/code-block.md +105 -105
- package/docs/components/collapsible.md +86 -86
- package/docs/components/command.md +113 -113
- package/docs/components/context-menu.md +81 -81
- package/docs/components/dialog.md +198 -198
- package/docs/components/drawer.md +105 -105
- package/docs/components/dropdown-menu.md +127 -127
- package/docs/components/empty.md +127 -127
- package/docs/components/error-boundary.md +201 -191
- package/docs/components/file-upload.md +189 -189
- package/docs/components/floating-media-wrapper.md +63 -63
- package/docs/components/form.md +177 -177
- package/docs/components/formatted-document.md +105 -105
- package/docs/components/google-maps-loader.md +44 -44
- package/docs/components/header.md +177 -177
- package/docs/components/hooks.md +432 -430
- package/docs/components/hover-card.md +86 -86
- package/docs/components/image-with-fallback.md +107 -107
- package/docs/components/input-otp.md +95 -95
- package/docs/components/input.md +130 -130
- package/docs/components/label.md +69 -69
- package/docs/components/language-selector.md +20 -16
- package/docs/components/map-layers.md +138 -138
- package/docs/components/map.md +84 -84
- package/docs/components/markdown-message.md +47 -47
- package/docs/components/menubar.md +89 -89
- package/docs/components/modern-chat-input.md +164 -164
- package/docs/components/navigation-menu.md +83 -83
- package/docs/components/notification-badge.md +78 -78
- package/docs/components/page-header.md +93 -93
- package/docs/components/pages.md +323 -309
- package/docs/components/pagination.md +334 -334
- package/docs/components/popover.md +116 -116
- package/docs/components/progress.md +103 -103
- package/docs/components/radio-group.md +133 -133
- package/docs/components/rating.md +77 -77
- package/docs/components/resizable.md +84 -84
- package/docs/components/rich-text-editor.md +255 -255
- package/docs/components/route-map.md +124 -124
- package/docs/components/scroll-area.md +58 -58
- package/docs/components/search.md +87 -87
- package/docs/components/select.md +144 -144
- package/docs/components/separator.md +58 -58
- package/docs/components/sheet.md +122 -122
- package/docs/components/sidebar.md +314 -314
- package/docs/components/simple-map.md +51 -51
- package/docs/components/skeleton.md +99 -99
- package/docs/components/slider.md +84 -84
- package/docs/components/sonner.md +115 -115
- package/docs/components/stats-card.md +120 -120
- package/docs/components/stepper.md +268 -268
- package/docs/components/switch.md +106 -106
- package/docs/components/table.md +138 -138
- package/docs/components/tabs.md +117 -117
- package/docs/components/textarea.md +86 -86
- package/docs/components/theme-toggle.md +73 -73
- package/docs/components/timeline.md +121 -121
- package/docs/components/toggle-group.md +68 -68
- package/docs/components/toggle.md +62 -62
- package/docs/components/tooltip.md +116 -116
- package/docs/components/tree-view.md +238 -238
- package/docs/components/use-mobile.md +96 -96
- package/docs/components/video-player.md +68 -68
- package/docs/components/xertica-logo.md +36 -36
- package/docs/components/xertica-orbe.md +35 -35
- package/docs/components/xertica-provider.md +65 -65
- package/docs/components/xertica-xlogo.md +35 -35
- package/docs/decision-tree.md +293 -293
- package/docs/doc-audit.md +244 -243
- package/docs/form-sizing.md +162 -162
- package/docs/getting-started.md +616 -591
- package/docs/guidelines.md +330 -328
- package/docs/i18n.md +61 -57
- package/docs/installation.md +268 -267
- package/docs/layout.md +143 -143
- package/docs/llms.md +295 -295
- package/docs/patterns/analytics.md +194 -194
- package/docs/patterns/crud.md +149 -149
- package/docs/patterns/dashboard.md +138 -138
- package/docs/patterns/detail-page.md +296 -296
- package/docs/patterns/form.md +241 -241
- package/docs/patterns/login.md +156 -156
- package/docs/patterns/settings.md +368 -368
- package/docs/patterns/wizard.md +213 -213
- package/docs/state-management.md +289 -289
- package/guidelines/Guidelines.md +409 -406
- package/hooks/useTheme.test.tsx +16 -16
- package/hooks/useTheme.ts +4 -4
- package/imports/Podcast.tsx +540 -540
- package/imports/XerticaAi.tsx +46 -46
- package/imports/XerticaX.tsx +15 -15
- package/imports/svg-aueiaqngck.ts +20 -20
- package/imports/svg-v9krss1ozd.ts +23 -23
- package/imports/svg-vhrdofe3qe.ts +6 -6
- package/llms-compact.txt +2 -1
- package/llms.txt +2 -1
- package/mcp/resources.json +22 -22
- package/mcp/tools.json +35 -35
- package/package.json +219 -213
- package/scripts/ai-validator.ts +91 -91
- package/scripts/cleanup-case-dupes.ts +62 -62
- package/scripts/generate-ai-manifests.ts +107 -107
- package/styles/globals.css +13 -13
- package/styles/xertica/app-overrides/chat.css +61 -61
- package/styles/xertica/app-overrides/scrollbar.css +33 -33
- package/styles/xertica/base.css +90 -71
- package/styles/xertica/integrations/google-maps.css +76 -76
- package/styles/xertica/integrations/sonner.css +73 -73
- package/styles/xertica/theme-map.css +102 -99
- package/styles/xertica/tokens.css +240 -236
- package/templates/CLAUDE.md +16 -1
- package/templates/eslint.config.js +26 -26
- package/templates/guidelines/Guidelines.md +577 -553
- package/templates/package.json +69 -69
- package/templates/postcss.config.js +6 -6
- package/templates/src/app/App.tsx +46 -46
- package/templates/src/app/components/AppLayout.tsx +55 -55
- package/templates/src/app/components/AuthGuard.tsx +131 -82
- package/templates/src/app/context/AuthContext.tsx +108 -108
- package/templates/src/features/assistant/index.ts +5 -5
- package/templates/src/features/auth/index.ts +4 -4
- package/templates/src/features/auth/ui/AuthPageShell.tsx +32 -32
- package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +70 -72
- package/templates/src/features/auth/ui/LoginContent.tsx +92 -92
- package/templates/src/features/auth/ui/ResetPasswordContent.tsx +6 -2
- package/templates/src/features/auth/ui/SocialLoginButtons.tsx +78 -78
- package/templates/src/features/auth/ui/VerifyEmailContent.tsx +2 -6
- package/templates/src/features/home/data/mock.ts +41 -35
- package/templates/src/features/home/index.ts +11 -11
- package/templates/src/features/home/store/dashboardStore.ts +25 -25
- package/templates/src/features/home/ui/HomeContent.tsx +117 -119
- package/templates/src/features/template/index.ts +5 -5
- package/templates/src/features/template/ui/CrudTemplate.tsx +1 -4
- package/templates/src/features/template/ui/LoginTemplate.tsx +1 -1
- package/templates/src/features/template/ui/TemplateContent.tsx +29 -21
- package/templates/src/locales/en/pages/templates.json +17 -17
- package/templates/src/locales/es/pages/templates.json +17 -17
- package/templates/src/locales/pt-BR/pages/templates.json +17 -17
- package/templates/src/main.tsx +11 -11
- package/templates/src/pages/AssistantPage.tsx +26 -20
- package/templates/src/pages/ForgotPasswordPage.tsx +6 -6
- package/templates/src/pages/HomePage.tsx +53 -49
- package/templates/src/pages/LoginPage.tsx +10 -10
- package/templates/src/pages/ResetPasswordPage.tsx +6 -6
- package/templates/src/pages/TemplatePage.tsx +28 -28
- package/templates/src/pages/VerifyEmailPage.tsx +6 -6
- package/templates/src/shared/config/navigation.ts +19 -19
- package/templates/src/shared/error-boundary.tsx +150 -154
- package/templates/src/shared/error-fallbacks.tsx +222 -226
- package/templates/src/shared/lib/auth.ts +20 -20
- package/templates/src/shared/types/auth.ts +3 -3
- package/templates/src/styles/index.css +95 -95
- package/templates/src/styles/xertica/tokens.css +240 -236
- package/templates/tsconfig.json +25 -25
- package/templates/tsconfig.node.json +12 -12
- package/templates/vite-env.d.ts +1 -1
- package/templates/vite.config.js +20 -20
- package/templates/vite.config.ts +54 -51
- package/utils/color-utils.ts +72 -72
- package/utils/demo-responses.test.ts +10 -10
- package/utils/demo-responses.ts +151 -151
- package/utils/gemini.test.ts +25 -25
- package/utils/gemini.ts +155 -155
package/dist/cli.js
CHANGED
|
@@ -691,9 +691,11 @@ export function registerLanguageResource(
|
|
|
691
691
|
export default i18n;
|
|
692
692
|
`;
|
|
693
693
|
}
|
|
694
|
-
function generateAppTsx(selectedCodes) {
|
|
694
|
+
function generateAppTsx(selectedCodes, disableDarkMode = false) {
|
|
695
695
|
const selectedLangs = SUPPORTED_LANGUAGES.filter((l) => selectedCodes.includes(l.code));
|
|
696
696
|
const isMonolingual = selectedLangs.length === 1;
|
|
697
|
+
const disableDarkModeProp = disableDarkMode ? `
|
|
698
|
+
disableDarkMode={true}` : "";
|
|
697
699
|
const isAllDefaults = selectedLangs.length === SUPPORTED_LANGUAGES.length && selectedLangs.every((l) => DEFAULT_SELECTION.includes(l.code));
|
|
698
700
|
const languagesArrayLiteral = selectedLangs.map(
|
|
699
701
|
(l) => ` { code: '${l.code}', label: '${l.label}', shortLabel: '${l.shortLabel}' },`
|
|
@@ -737,7 +739,7 @@ export default function App() {
|
|
|
737
739
|
<QueryClientProvider client={queryClient}>
|
|
738
740
|
<XerticaProvider
|
|
739
741
|
apiKey={geminiApiKey}
|
|
740
|
-
googleMapsApiKey={googleMapsApiKey}${availableLanguagesProp}
|
|
742
|
+
googleMapsApiKey={googleMapsApiKey}${availableLanguagesProp}${disableDarkModeProp}
|
|
741
743
|
>
|
|
742
744
|
<Router>
|
|
743
745
|
{/* AuthProvider must be inside Router (needs useNavigate) */}
|
|
@@ -761,17 +763,222 @@ function toJsIdent(code) {
|
|
|
761
763
|
}
|
|
762
764
|
|
|
763
765
|
// bin/cli.ts
|
|
766
|
+
var XERTICA_CONFIG_FILE = ".xertica.json";
|
|
767
|
+
async function readXerticaConfig(targetDir) {
|
|
768
|
+
const configPath = path2.join(targetDir, XERTICA_CONFIG_FILE);
|
|
769
|
+
if (!await fs2.pathExists(configPath)) return null;
|
|
770
|
+
try {
|
|
771
|
+
return await fs2.readJson(configPath);
|
|
772
|
+
} catch {
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
async function writeXerticaConfig(targetDir, config) {
|
|
777
|
+
const configPath = path2.join(targetDir, XERTICA_CONFIG_FILE);
|
|
778
|
+
const existing = await readXerticaConfig(targetDir) ?? {
|
|
779
|
+
version: 1,
|
|
780
|
+
hasAssistant: false
|
|
781
|
+
};
|
|
782
|
+
await fs2.writeJson(configPath, { ...existing, ...config, version: 1 }, { spaces: 2 });
|
|
783
|
+
}
|
|
764
784
|
var __filename = fileURLToPath(import.meta.url);
|
|
765
785
|
var __dirname = path2.dirname(__filename);
|
|
766
786
|
var pkgJson = JSON.parse(
|
|
767
787
|
fs2.readFileSync(path2.resolve(__dirname, "../package.json"), "utf-8")
|
|
768
788
|
);
|
|
789
|
+
function generateAuthGuard({
|
|
790
|
+
hasLogin,
|
|
791
|
+
hasHome,
|
|
792
|
+
hasTemplate,
|
|
793
|
+
hasAssistant,
|
|
794
|
+
firstProtectedPath
|
|
795
|
+
}) {
|
|
796
|
+
return `import React from 'react';
|
|
797
|
+
import { Routes, Route, Navigate } from 'react-router-dom';
|
|
798
|
+
import { useAuth } from '../context/AuthContext';
|
|
799
|
+
|
|
800
|
+
// \u2500\u2500\u2500 Lazy page imports \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
801
|
+
|
|
802
|
+
${hasLogin ? `const LoginPage = React.lazy(() => import('../../pages/LoginPage').then(m => ({ default: m.LoginPage })));
|
|
803
|
+
const ForgotPasswordPage = React.lazy(() => import('../../pages/ForgotPasswordPage').then(m => ({ default: m.ForgotPasswordPage })));
|
|
804
|
+
const VerifyEmailPage = React.lazy(() => import('../../pages/VerifyEmailPage').then(m => ({ default: m.VerifyEmailPage })));
|
|
805
|
+
const ResetPasswordPage = React.lazy(() => import('../../pages/ResetPasswordPage').then(m => ({ default: m.ResetPasswordPage })));` : ""}
|
|
806
|
+
|
|
807
|
+
${hasHome ? `const HomePage = React.lazy(() => import('../../pages/HomePage').then(m => ({ default: m.HomePage })));` : ""}
|
|
808
|
+
${hasTemplate ? `const TemplatePage = React.lazy(() => import('../../pages/TemplatePage').then(m => ({ default: m.TemplatePage })));` : ""}
|
|
809
|
+
${hasAssistant ? `const AssistantPage = React.lazy(() => import('../../pages/AssistantPage').then(m => ({ default: m.AssistantPage })));` : ""}
|
|
810
|
+
|
|
811
|
+
// \u2500\u2500\u2500 Route guards \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
812
|
+
|
|
813
|
+
function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
|
814
|
+
const { user, isLoading } = useAuth();
|
|
815
|
+
if (isLoading) return null;
|
|
816
|
+
if (!user) return <Navigate to="${hasLogin ? "/login" : firstProtectedPath}" replace />;
|
|
817
|
+
return <>{children}</>;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
${hasLogin ? `function GuestRoute({ children }: { children: React.ReactNode }) {
|
|
821
|
+
const { user, isLoading } = useAuth();
|
|
822
|
+
if (isLoading) return null;
|
|
823
|
+
if (user) return <Navigate to="${firstProtectedPath}" replace />;
|
|
824
|
+
return <>{children}</>;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
function LoginPageWithAuth() {
|
|
828
|
+
const { login } = useAuth();
|
|
829
|
+
return <LoginPage onLogin={login} />;
|
|
830
|
+
}` : ""}
|
|
831
|
+
|
|
832
|
+
// \u2500\u2500\u2500 Route tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
833
|
+
|
|
834
|
+
export function AuthGuard() {
|
|
835
|
+
const { user } = useAuth();
|
|
836
|
+
|
|
837
|
+
return (
|
|
838
|
+
<div className="min-h-screen bg-muted overflow-x-hidden max-w-full">
|
|
839
|
+
<Routes>
|
|
840
|
+
${hasLogin ? ` <Route path="/login" element={<GuestRoute><LoginPageWithAuth /></GuestRoute>} />
|
|
841
|
+
<Route path="/forgot-password" element={<GuestRoute><ForgotPasswordPage /></GuestRoute>} />
|
|
842
|
+
<Route path="/verify-email" element={<GuestRoute><VerifyEmailPage /></GuestRoute>} />
|
|
843
|
+
<Route path="/reset-password" element={<GuestRoute><ResetPasswordPage /></GuestRoute>} />` : ""}
|
|
844
|
+
|
|
845
|
+
${hasHome ? ` <Route path="/home" element={<ProtectedRoute><HomePage /></ProtectedRoute>} />` : ""}
|
|
846
|
+
${hasTemplate ? ` <Route path="/template" element={<ProtectedRoute><TemplatePage /></ProtectedRoute>} />` : ""}
|
|
847
|
+
${hasAssistant ? ` <Route path="/assistente" element={<ProtectedRoute><AssistantPage /></ProtectedRoute>} />` : ""}
|
|
848
|
+
|
|
849
|
+
<Route path="/" element={<Navigate to={user ? '${firstProtectedPath}' : '${hasLogin ? "/login" : firstProtectedPath}'} replace />} />
|
|
850
|
+
<Route path="*" element={<Navigate to={user ? '${firstProtectedPath}' : '${hasLogin ? "/login" : firstProtectedPath}'} replace />} />
|
|
851
|
+
</Routes>
|
|
852
|
+
</div>
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
`;
|
|
856
|
+
}
|
|
857
|
+
function generateHomePage(hasAssistant) {
|
|
858
|
+
if (hasAssistant) {
|
|
859
|
+
return `import React from 'react';
|
|
860
|
+
import { XerticaAssistant, generateDemoResponse } from 'xertica-ui/assistant';
|
|
861
|
+
import { useLayout } from 'xertica-ui/hooks';
|
|
862
|
+
import { useNavigate } from 'react-router-dom';
|
|
863
|
+
import { AppLayout } from '../app/components/AppLayout';
|
|
864
|
+
import { HomeContent } from '../features/home';
|
|
865
|
+
import { useAssistantConfig, getMockRichSuggestions, getMockFeedbackOptions } from '../features/assistant';
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
* Home page \u2014 thin layout shell.
|
|
869
|
+
*
|
|
870
|
+
* Assistant config (suggestions, feedback options) is fetched via React Query.
|
|
871
|
+
* To connect to a real API replace \`fetchAssistantConfig\` in
|
|
872
|
+
* \`features/assistant/data/mock.ts\`.
|
|
873
|
+
*/
|
|
874
|
+
export function HomePage() {
|
|
875
|
+
const { assistenteExpanded, toggleAssistente } = useLayout();
|
|
876
|
+
const navigate = useNavigate();
|
|
877
|
+
|
|
878
|
+
const { data: assistantConfig } = useAssistantConfig();
|
|
879
|
+
|
|
880
|
+
return (
|
|
881
|
+
<AppLayout
|
|
882
|
+
assistant={
|
|
883
|
+
<XerticaAssistant
|
|
884
|
+
isExpanded={assistenteExpanded}
|
|
885
|
+
onToggle={toggleAssistente}
|
|
886
|
+
defaultTab="chat"
|
|
887
|
+
demoMode={true}
|
|
888
|
+
userName="Ariel Santos"
|
|
889
|
+
responseGenerator={generateDemoResponse}
|
|
890
|
+
suggestions={assistantConfig?.suggestions}
|
|
891
|
+
richSuggestions={assistantConfig?.richSuggestions ?? getMockRichSuggestions()}
|
|
892
|
+
feedbackOptions={assistantConfig?.feedbackOptions ?? getMockFeedbackOptions()}
|
|
893
|
+
showHistory={false}
|
|
894
|
+
showFavorites={false}
|
|
895
|
+
onNavigateSettings={() => navigate('/settings')}
|
|
896
|
+
onNavigateFullPage={() => navigate('/assistente')}
|
|
897
|
+
onEvaluation={(messageId, type, reason) => {
|
|
898
|
+
// Wire your feedback persistence logic here
|
|
899
|
+
console.log(\`Avalia\xE7\xE3o: \${type} na mensagem \${messageId}. Motivo: \${reason}\`);
|
|
900
|
+
}}
|
|
901
|
+
/>
|
|
902
|
+
}
|
|
903
|
+
>
|
|
904
|
+
<HomeContent />
|
|
905
|
+
</AppLayout>
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
`;
|
|
909
|
+
}
|
|
910
|
+
return `import React from 'react';
|
|
911
|
+
import { AppLayout } from '../app/components/AppLayout';
|
|
912
|
+
import { HomeContent } from '../features/home';
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* Home page \u2014 thin layout shell.
|
|
916
|
+
*/
|
|
917
|
+
export function HomePage() {
|
|
918
|
+
return (
|
|
919
|
+
<AppLayout>
|
|
920
|
+
<HomeContent />
|
|
921
|
+
</AppLayout>
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
`;
|
|
925
|
+
}
|
|
926
|
+
function generateTemplatePage(hasAssistant) {
|
|
927
|
+
if (hasAssistant) {
|
|
928
|
+
return `import React from 'react';
|
|
929
|
+
import { XerticaAssistant } from 'xertica-ui/assistant';
|
|
930
|
+
import { useLayout } from 'xertica-ui/hooks';
|
|
931
|
+
import { AppLayout } from '../app/components/AppLayout';
|
|
932
|
+
import { TemplateContent } from '../features/template';
|
|
933
|
+
|
|
934
|
+
/**
|
|
935
|
+
* Template page \u2014 thin layout shell.
|
|
936
|
+
*
|
|
937
|
+
* Auth state is consumed from \`AuthContext\` via \`AppLayout\` \u2014 no props needed.
|
|
938
|
+
*/
|
|
939
|
+
export function TemplatePage() {
|
|
940
|
+
const { assistenteExpanded, toggleAssistente } = useLayout();
|
|
941
|
+
|
|
942
|
+
return (
|
|
943
|
+
<AppLayout
|
|
944
|
+
assistant={
|
|
945
|
+
<XerticaAssistant
|
|
946
|
+
isExpanded={assistenteExpanded}
|
|
947
|
+
onToggle={toggleAssistente}
|
|
948
|
+
onEvaluation={(id, type, reason) => console.log('Feedback:', id, type, reason)}
|
|
949
|
+
/>
|
|
950
|
+
}
|
|
951
|
+
>
|
|
952
|
+
<TemplateContent />
|
|
953
|
+
</AppLayout>
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
`;
|
|
957
|
+
}
|
|
958
|
+
return `import React from 'react';
|
|
959
|
+
import { AppLayout } from '../app/components/AppLayout';
|
|
960
|
+
import { TemplateContent } from '../features/template';
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* Template page \u2014 thin layout shell.
|
|
964
|
+
*
|
|
965
|
+
* Auth state is consumed from \`AuthContext\` via \`AppLayout\` \u2014 no props needed.
|
|
966
|
+
*/
|
|
967
|
+
export function TemplatePage() {
|
|
968
|
+
return (
|
|
969
|
+
<AppLayout>
|
|
970
|
+
<TemplateContent />
|
|
971
|
+
</AppLayout>
|
|
972
|
+
);
|
|
973
|
+
}
|
|
974
|
+
`;
|
|
975
|
+
}
|
|
769
976
|
var program = new Command();
|
|
770
977
|
program.name("xertica-ui").description("CLI to initialize Xertica UI projects").version(pkgJson.version);
|
|
771
978
|
program.command("init").description("Initialize a new Xertica UI project").argument("[directory]", "Directory to initialize in", ".").action(async (directory) => {
|
|
772
979
|
const targetDir = path2.resolve(process.cwd(), directory);
|
|
773
980
|
const templatesDir = path2.resolve(__dirname, "../templates");
|
|
774
|
-
console.log(chalk.blue(
|
|
981
|
+
console.log(chalk.blue(`\u{1F680} Welcome to Xertica UI CLI! ${chalk.dim(`v${pkgJson.version}`)}`));
|
|
775
982
|
const response = await prompts([
|
|
776
983
|
{
|
|
777
984
|
type: "multiselect",
|
|
@@ -811,6 +1018,18 @@ program.command("init").description("Initialize a new Xertica UI project").argum
|
|
|
811
1018
|
})),
|
|
812
1019
|
initial: 0
|
|
813
1020
|
},
|
|
1021
|
+
{
|
|
1022
|
+
type: "confirm",
|
|
1023
|
+
name: "hasAssistant",
|
|
1024
|
+
message: "Include AI Assistant? (XerticaAssistant chat page + sidebar variant)",
|
|
1025
|
+
initial: true
|
|
1026
|
+
},
|
|
1027
|
+
{
|
|
1028
|
+
type: "confirm",
|
|
1029
|
+
name: "enableDarkMode",
|
|
1030
|
+
message: "Enable dark mode support?",
|
|
1031
|
+
initial: true
|
|
1032
|
+
},
|
|
814
1033
|
{
|
|
815
1034
|
type: "confirm",
|
|
816
1035
|
name: "install",
|
|
@@ -826,6 +1045,7 @@ program.command("init").description("Initialize a new Xertica UI project").argum
|
|
|
826
1045
|
const hasLogin = pages.includes("login");
|
|
827
1046
|
const hasHome = pages.includes("home");
|
|
828
1047
|
const hasTemplate = pages.includes("template");
|
|
1048
|
+
const hasAssistant = response.hasAssistant ?? true;
|
|
829
1049
|
const selectedLanguages = Array.isArray(response.languages) && response.languages.length > 0 ? response.languages : DEFAULT_SELECTION;
|
|
830
1050
|
const rootFilesToCopy = [
|
|
831
1051
|
"index.html",
|
|
@@ -856,10 +1076,11 @@ program.command("init").description("Initialize a new Xertica UI project").argum
|
|
|
856
1076
|
path2.join(templatesDir, "src", "main.tsx"),
|
|
857
1077
|
path2.join(targetDir, "src", "main.tsx")
|
|
858
1078
|
);
|
|
1079
|
+
const disableDarkMode = response.enableDarkMode === false;
|
|
859
1080
|
await fs2.ensureDir(path2.join(targetDir, "src", "app"));
|
|
860
1081
|
await fs2.writeFile(
|
|
861
1082
|
path2.join(targetDir, "src", "app", "App.tsx"),
|
|
862
|
-
generateAppTsx(selectedLanguages)
|
|
1083
|
+
generateAppTsx(selectedLanguages, disableDarkMode)
|
|
863
1084
|
);
|
|
864
1085
|
await fs2.ensureDir(path2.join(targetDir, "src", "app", "components"));
|
|
865
1086
|
await fs2.copy(
|
|
@@ -876,6 +1097,7 @@ program.command("init").description("Initialize a new Xertica UI project").argum
|
|
|
876
1097
|
);
|
|
877
1098
|
await syncLocaleFiles(templatesDir, targetDir, selectedLanguages, { pruneOthers: true });
|
|
878
1099
|
await writeLanguagesConfig(targetDir, selectedLanguages);
|
|
1100
|
+
await writeXerticaConfig(targetDir, { hasAssistant, disableDarkMode });
|
|
879
1101
|
await fs2.ensureDir(path2.join(targetDir, "src", "app", "context"));
|
|
880
1102
|
await fs2.copy(
|
|
881
1103
|
path2.join(templatesDir, "src", "app", "context", "AuthContext.tsx"),
|
|
@@ -899,10 +1121,12 @@ program.command("init").description("Initialize a new Xertica UI project").argum
|
|
|
899
1121
|
path2.join(targetDir, "src", "features", "template")
|
|
900
1122
|
);
|
|
901
1123
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1124
|
+
if (hasAssistant) {
|
|
1125
|
+
await fs2.copy(
|
|
1126
|
+
path2.join(templatesDir, "src", "features", "assistant"),
|
|
1127
|
+
path2.join(targetDir, "src", "features", "assistant")
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
906
1130
|
await fs2.ensureDir(path2.join(targetDir, "src", "pages"));
|
|
907
1131
|
const pagesToCopy = [];
|
|
908
1132
|
if (hasLogin)
|
|
@@ -914,74 +1138,35 @@ program.command("init").description("Initialize a new Xertica UI project").argum
|
|
|
914
1138
|
);
|
|
915
1139
|
if (hasHome) pagesToCopy.push("HomePage.tsx");
|
|
916
1140
|
if (hasTemplate) pagesToCopy.push("TemplatePage.tsx");
|
|
917
|
-
pagesToCopy.push("AssistantPage.tsx");
|
|
1141
|
+
if (hasAssistant) pagesToCopy.push("AssistantPage.tsx");
|
|
918
1142
|
for (const pageFile of pagesToCopy) {
|
|
1143
|
+
if (pageFile === "HomePage.tsx") {
|
|
1144
|
+
await fs2.writeFile(
|
|
1145
|
+
path2.join(targetDir, "src", "pages", "HomePage.tsx"),
|
|
1146
|
+
generateHomePage(hasAssistant)
|
|
1147
|
+
);
|
|
1148
|
+
continue;
|
|
1149
|
+
}
|
|
1150
|
+
if (pageFile === "TemplatePage.tsx") {
|
|
1151
|
+
await fs2.writeFile(
|
|
1152
|
+
path2.join(targetDir, "src", "pages", "TemplatePage.tsx"),
|
|
1153
|
+
generateTemplatePage(hasAssistant)
|
|
1154
|
+
);
|
|
1155
|
+
continue;
|
|
1156
|
+
}
|
|
919
1157
|
const src = path2.join(templatesDir, "src", "pages", pageFile);
|
|
920
1158
|
if (await fs2.pathExists(src)) {
|
|
921
1159
|
await fs2.copy(src, path2.join(targetDir, "src", "pages", pageFile));
|
|
922
1160
|
}
|
|
923
1161
|
}
|
|
924
1162
|
const firstProtectedPath = hasHome ? "/home" : hasTemplate ? "/template" : "/login";
|
|
925
|
-
const authGuardContent =
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
const ForgotPasswordPage = React.lazy(() => import('../../pages/ForgotPasswordPage').then(m => ({ default: m.ForgotPasswordPage })));
|
|
933
|
-
const VerifyEmailPage = React.lazy(() => import('../../pages/VerifyEmailPage').then(m => ({ default: m.VerifyEmailPage })));
|
|
934
|
-
const ResetPasswordPage = React.lazy(() => import('../../pages/ResetPasswordPage').then(m => ({ default: m.ResetPasswordPage })));` : ""}
|
|
935
|
-
|
|
936
|
-
${hasHome ? `const HomePage = React.lazy(() => import('../../pages/HomePage').then(m => ({ default: m.HomePage })));` : ""}
|
|
937
|
-
${hasTemplate ? `const TemplatePage = React.lazy(() => import('../../pages/TemplatePage').then(m => ({ default: m.TemplatePage })));` : ""}
|
|
938
|
-
const AssistantPage = React.lazy(() => import('../../pages/AssistantPage').then(m => ({ default: m.AssistantPage })));
|
|
939
|
-
|
|
940
|
-
// \u2500\u2500\u2500 Route guards \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
941
|
-
|
|
942
|
-
function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
|
943
|
-
const { user, isLoading } = useAuth();
|
|
944
|
-
if (isLoading) return null;
|
|
945
|
-
if (!user) return <Navigate to="${hasLogin ? "/login" : firstProtectedPath}" replace />;
|
|
946
|
-
return <>{children}</>;
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
${hasLogin ? `function GuestRoute({ children }: { children: React.ReactNode }) {
|
|
950
|
-
const { user, isLoading } = useAuth();
|
|
951
|
-
if (isLoading) return null;
|
|
952
|
-
if (user) return <Navigate to="${firstProtectedPath}" replace />;
|
|
953
|
-
return <>{children}</>;
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
function LoginPageWithAuth() {
|
|
957
|
-
const { login } = useAuth();
|
|
958
|
-
return <LoginPage onLogin={login} />;
|
|
959
|
-
}` : ""}
|
|
960
|
-
|
|
961
|
-
// \u2500\u2500\u2500 Route tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
962
|
-
|
|
963
|
-
export function AuthGuard() {
|
|
964
|
-
const { user } = useAuth();
|
|
965
|
-
|
|
966
|
-
return (
|
|
967
|
-
<div className="min-h-screen bg-muted overflow-x-hidden max-w-full">
|
|
968
|
-
<Routes>
|
|
969
|
-
${hasLogin ? ` <Route path="/login" element={<GuestRoute><LoginPageWithAuth /></GuestRoute>} />
|
|
970
|
-
<Route path="/forgot-password" element={<GuestRoute><ForgotPasswordPage /></GuestRoute>} />
|
|
971
|
-
<Route path="/verify-email" element={<GuestRoute><VerifyEmailPage /></GuestRoute>} />
|
|
972
|
-
<Route path="/reset-password" element={<GuestRoute><ResetPasswordPage /></GuestRoute>} />` : ""}
|
|
973
|
-
|
|
974
|
-
${hasHome ? ` <Route path="/home" element={<ProtectedRoute><HomePage /></ProtectedRoute>} />` : ""}
|
|
975
|
-
${hasTemplate ? ` <Route path="/template" element={<ProtectedRoute><TemplatePage /></ProtectedRoute>} />` : ""}
|
|
976
|
-
<Route path="/assistente" element={<ProtectedRoute><AssistantPage /></ProtectedRoute>} />
|
|
977
|
-
|
|
978
|
-
<Route path="/" element={<Navigate to={user ? '${firstProtectedPath}' : '${hasLogin ? "/login" : firstProtectedPath}'} replace />} />
|
|
979
|
-
<Route path="*" element={<Navigate to={user ? '${firstProtectedPath}' : '${hasLogin ? "/login" : firstProtectedPath}'} replace />} />
|
|
980
|
-
</Routes>
|
|
981
|
-
</div>
|
|
982
|
-
);
|
|
983
|
-
}
|
|
984
|
-
`;
|
|
1163
|
+
const authGuardContent = generateAuthGuard({
|
|
1164
|
+
hasLogin,
|
|
1165
|
+
hasHome,
|
|
1166
|
+
hasTemplate,
|
|
1167
|
+
hasAssistant,
|
|
1168
|
+
firstProtectedPath
|
|
1169
|
+
});
|
|
985
1170
|
await fs2.writeFile(
|
|
986
1171
|
path2.join(targetDir, "src", "app", "components", "AuthGuard.tsx"),
|
|
987
1172
|
authGuardContent
|
|
@@ -1016,9 +1201,13 @@ ${hasTemplate ? ` <Route path="/template" element={<ProtectedRoute><Templ
|
|
|
1016
1201
|
` Languages: ${langLabels}${selectedLanguages.length === 1 ? " (monolingual \u2014 LanguageSelector hidden)" : ""}`
|
|
1017
1202
|
)
|
|
1018
1203
|
);
|
|
1204
|
+
console.log(chalk.gray(" To add/remove languages later: npx xertica-ui update \u2192 Languages"));
|
|
1019
1205
|
console.log(
|
|
1020
|
-
chalk.gray(
|
|
1206
|
+
chalk.gray(` AI Assistant: ${hasAssistant ? "included (/assistente)" : "not included"}`)
|
|
1021
1207
|
);
|
|
1208
|
+
if (!hasAssistant) {
|
|
1209
|
+
console.log(chalk.gray(" To add the assistant later: npx xertica-ui update \u2192 Assistant"));
|
|
1210
|
+
}
|
|
1022
1211
|
} catch (error) {
|
|
1023
1212
|
spinner.fail("Failed to initialize project");
|
|
1024
1213
|
console.error(error);
|
|
@@ -1026,6 +1215,8 @@ ${hasTemplate ? ` <Route path="/template" element={<ProtectedRoute><Templ
|
|
|
1026
1215
|
});
|
|
1027
1216
|
program.command("update").alias("update-theme").description("Update theme or project files to the latest version").action(async () => {
|
|
1028
1217
|
const targetDir = process.cwd();
|
|
1218
|
+
console.log(chalk.blue(`\u{1F527} Xertica UI CLI ${chalk.dim(`v${pkgJson.version}`)}`));
|
|
1219
|
+
const currentConfig = await readXerticaConfig(targetDir);
|
|
1029
1220
|
const { updateType } = await prompts({
|
|
1030
1221
|
type: "select",
|
|
1031
1222
|
name: "updateType",
|
|
@@ -1041,6 +1232,16 @@ program.command("update").alias("update-theme").description("Update theme or pro
|
|
|
1041
1232
|
description: "Add or remove supported languages (pt-BR, en, es, \u2026)",
|
|
1042
1233
|
value: "languages"
|
|
1043
1234
|
},
|
|
1235
|
+
{
|
|
1236
|
+
title: "Assistant",
|
|
1237
|
+
description: currentConfig?.hasAssistant ? "Remove the AI Assistant from your project" : "Add the AI Assistant to your project",
|
|
1238
|
+
value: "assistant"
|
|
1239
|
+
},
|
|
1240
|
+
{
|
|
1241
|
+
title: "Dark Mode",
|
|
1242
|
+
description: currentConfig?.disableDarkMode ? "Enable dark mode support in your project" : "Disable dark mode support in your project",
|
|
1243
|
+
value: "darkmode"
|
|
1244
|
+
},
|
|
1044
1245
|
{
|
|
1045
1246
|
title: "Project files",
|
|
1046
1247
|
description: "Update app shell, shared, features and pages to a specific version",
|
|
@@ -1123,10 +1324,8 @@ Current languages: ${SUPPORTED_LANGUAGES.filter((l) => currentCodes.includes(l.c
|
|
|
1123
1324
|
return;
|
|
1124
1325
|
}
|
|
1125
1326
|
const summary = [];
|
|
1126
|
-
if (toAdd.length > 0)
|
|
1127
|
-
|
|
1128
|
-
if (toRemove.length > 0)
|
|
1129
|
-
summary.push(chalk.red(` - ${toRemove.join(", ")}`));
|
|
1327
|
+
if (toAdd.length > 0) summary.push(chalk.green(` + ${toAdd.join(", ")}`));
|
|
1328
|
+
if (toRemove.length > 0) summary.push(chalk.red(` - ${toRemove.join(", ")}`));
|
|
1130
1329
|
console.log(`
|
|
1131
1330
|
${summary.join("\n")}
|
|
1132
1331
|
`);
|
|
@@ -1151,19 +1350,13 @@ ${summary.join("\n")}
|
|
|
1151
1350
|
"templates"
|
|
1152
1351
|
);
|
|
1153
1352
|
const templatesSourceDir = await fs2.pathExists(installedTemplatesDir) ? installedTemplatesDir : path2.resolve(__dirname, "../templates");
|
|
1154
|
-
const { copied, removed } = await syncLocaleFiles(
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
{ pruneOthers: true }
|
|
1159
|
-
);
|
|
1160
|
-
await fs2.writeFile(
|
|
1161
|
-
path2.join(targetDir, "src", "i18n.ts"),
|
|
1162
|
-
generateI18nFile(newCodes)
|
|
1163
|
-
);
|
|
1353
|
+
const { copied, removed } = await syncLocaleFiles(templatesSourceDir, targetDir, newCodes, {
|
|
1354
|
+
pruneOthers: true
|
|
1355
|
+
});
|
|
1356
|
+
await fs2.writeFile(path2.join(targetDir, "src", "i18n.ts"), generateI18nFile(newCodes));
|
|
1164
1357
|
await fs2.writeFile(
|
|
1165
1358
|
path2.join(targetDir, "src", "app", "App.tsx"),
|
|
1166
|
-
generateAppTsx(newCodes)
|
|
1359
|
+
generateAppTsx(newCodes, currentConfig?.disableDarkMode ?? false)
|
|
1167
1360
|
);
|
|
1168
1361
|
await writeLanguagesConfig(targetDir, newCodes);
|
|
1169
1362
|
spinner2.succeed("Languages updated successfully!");
|
|
@@ -1171,9 +1364,7 @@ ${summary.join("\n")}
|
|
|
1171
1364
|
if (removed.length > 0) console.log(chalk.red(` Removed: ${removed.join(", ")}`));
|
|
1172
1365
|
if (newCodes.length === 1) {
|
|
1173
1366
|
console.log(
|
|
1174
|
-
chalk.gray(
|
|
1175
|
-
` Project is now monolingual \u2014 the LanguageSelector will auto-hide.`
|
|
1176
|
-
)
|
|
1367
|
+
chalk.gray(` Project is now monolingual \u2014 the LanguageSelector will auto-hide.`)
|
|
1177
1368
|
);
|
|
1178
1369
|
}
|
|
1179
1370
|
} catch (error) {
|
|
@@ -1182,6 +1373,162 @@ ${summary.join("\n")}
|
|
|
1182
1373
|
}
|
|
1183
1374
|
return;
|
|
1184
1375
|
}
|
|
1376
|
+
if (updateType === "assistant") {
|
|
1377
|
+
let currentlyHas;
|
|
1378
|
+
if (currentConfig !== null) {
|
|
1379
|
+
currentlyHas = currentConfig.hasAssistant;
|
|
1380
|
+
} else {
|
|
1381
|
+
const assistantFeatureDir = path2.join(targetDir, "src", "features", "assistant");
|
|
1382
|
+
const assistantPage = path2.join(targetDir, "src", "pages", "AssistantPage.tsx");
|
|
1383
|
+
currentlyHas = await fs2.pathExists(assistantFeatureDir) || await fs2.pathExists(assistantPage);
|
|
1384
|
+
await writeXerticaConfig(targetDir, { hasAssistant: currentlyHas });
|
|
1385
|
+
}
|
|
1386
|
+
console.log(
|
|
1387
|
+
chalk.cyan(
|
|
1388
|
+
`
|
|
1389
|
+
AI Assistant is currently: ${currentlyHas ? chalk.green("enabled") : chalk.red("disabled")}
|
|
1390
|
+
`
|
|
1391
|
+
)
|
|
1392
|
+
);
|
|
1393
|
+
const { action } = await prompts({
|
|
1394
|
+
type: "select",
|
|
1395
|
+
name: "action",
|
|
1396
|
+
message: currentlyHas ? "Remove the AI Assistant from your project?" : "Add the AI Assistant to your project?",
|
|
1397
|
+
choices: currentlyHas ? [
|
|
1398
|
+
{
|
|
1399
|
+
title: "Remove assistant",
|
|
1400
|
+
description: "Deletes AssistantPage and assistant feature files",
|
|
1401
|
+
value: "remove"
|
|
1402
|
+
},
|
|
1403
|
+
{ title: "Cancel", value: "cancel" }
|
|
1404
|
+
] : [
|
|
1405
|
+
{
|
|
1406
|
+
title: "Add assistant",
|
|
1407
|
+
description: "Copies AssistantPage and assistant feature files",
|
|
1408
|
+
value: "add"
|
|
1409
|
+
},
|
|
1410
|
+
{ title: "Cancel", value: "cancel" }
|
|
1411
|
+
]
|
|
1412
|
+
});
|
|
1413
|
+
if (!action || action === "cancel") {
|
|
1414
|
+
console.log(chalk.gray("Update cancelled."));
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1417
|
+
const { confirmed: confirmed2 } = await prompts({
|
|
1418
|
+
type: "confirm",
|
|
1419
|
+
name: "confirmed",
|
|
1420
|
+
message: chalk.yellow(
|
|
1421
|
+
action === "remove" ? "\u26A0\uFE0F This will delete src/features/assistant/ and src/pages/AssistantPage.tsx and regenerate AuthGuard.tsx. Continue?" : "\u26A0\uFE0F This will copy src/features/assistant/ and src/pages/AssistantPage.tsx and regenerate AuthGuard.tsx. Continue?"
|
|
1422
|
+
),
|
|
1423
|
+
initial: action === "add"
|
|
1424
|
+
});
|
|
1425
|
+
if (!confirmed2) {
|
|
1426
|
+
console.log(chalk.gray("Update cancelled."));
|
|
1427
|
+
return;
|
|
1428
|
+
}
|
|
1429
|
+
const spinner2 = ora(
|
|
1430
|
+
action === "add" ? "Adding assistant..." : "Removing assistant..."
|
|
1431
|
+
).start();
|
|
1432
|
+
try {
|
|
1433
|
+
const installedTemplatesDir = path2.join(
|
|
1434
|
+
targetDir,
|
|
1435
|
+
"node_modules",
|
|
1436
|
+
"xertica-ui",
|
|
1437
|
+
"templates"
|
|
1438
|
+
);
|
|
1439
|
+
const templatesSourceDir = await fs2.pathExists(installedTemplatesDir) ? installedTemplatesDir : path2.resolve(__dirname, "../templates");
|
|
1440
|
+
const pagesDir = path2.join(targetDir, "src", "pages");
|
|
1441
|
+
const existingPages = await fs2.pathExists(pagesDir) ? await fs2.readdir(pagesDir) : [];
|
|
1442
|
+
const hasLogin = existingPages.includes("LoginPage.tsx");
|
|
1443
|
+
const hasHome = existingPages.includes("HomePage.tsx");
|
|
1444
|
+
const hasTemplate = existingPages.includes("TemplatePage.tsx");
|
|
1445
|
+
const firstProtectedPath = hasHome ? "/home" : hasTemplate ? "/template" : "/login";
|
|
1446
|
+
const persistedCodes = await readLanguagesConfig(targetDir);
|
|
1447
|
+
const selectedCodes = persistedCodes && persistedCodes.length > 0 ? persistedCodes : DEFAULT_SELECTION;
|
|
1448
|
+
if (action === "add") {
|
|
1449
|
+
await fs2.copy(
|
|
1450
|
+
path2.join(templatesSourceDir, "src", "features", "assistant"),
|
|
1451
|
+
path2.join(targetDir, "src", "features", "assistant"),
|
|
1452
|
+
{ overwrite: true }
|
|
1453
|
+
);
|
|
1454
|
+
await fs2.copy(
|
|
1455
|
+
path2.join(templatesSourceDir, "src", "pages", "AssistantPage.tsx"),
|
|
1456
|
+
path2.join(targetDir, "src", "pages", "AssistantPage.tsx"),
|
|
1457
|
+
{ overwrite: true }
|
|
1458
|
+
);
|
|
1459
|
+
} else {
|
|
1460
|
+
await fs2.remove(path2.join(targetDir, "src", "features", "assistant"));
|
|
1461
|
+
await fs2.remove(path2.join(targetDir, "src", "pages", "AssistantPage.tsx"));
|
|
1462
|
+
}
|
|
1463
|
+
const newHasAssistant = action === "add";
|
|
1464
|
+
if (hasHome) {
|
|
1465
|
+
await fs2.writeFile(
|
|
1466
|
+
path2.join(targetDir, "src", "pages", "HomePage.tsx"),
|
|
1467
|
+
generateHomePage(newHasAssistant)
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
if (hasTemplate) {
|
|
1471
|
+
await fs2.writeFile(
|
|
1472
|
+
path2.join(targetDir, "src", "pages", "TemplatePage.tsx"),
|
|
1473
|
+
generateTemplatePage(newHasAssistant)
|
|
1474
|
+
);
|
|
1475
|
+
}
|
|
1476
|
+
await fs2.writeFile(
|
|
1477
|
+
path2.join(targetDir, "src", "app", "components", "AuthGuard.tsx"),
|
|
1478
|
+
generateAuthGuard({
|
|
1479
|
+
hasLogin,
|
|
1480
|
+
hasHome,
|
|
1481
|
+
hasTemplate,
|
|
1482
|
+
hasAssistant: newHasAssistant,
|
|
1483
|
+
firstProtectedPath
|
|
1484
|
+
})
|
|
1485
|
+
);
|
|
1486
|
+
await writeXerticaConfig(targetDir, { hasAssistant: newHasAssistant });
|
|
1487
|
+
spinner2.succeed(
|
|
1488
|
+
action === "add" ? "AI Assistant added successfully!" : "AI Assistant removed successfully!"
|
|
1489
|
+
);
|
|
1490
|
+
if (action === "add") {
|
|
1491
|
+
console.log(chalk.gray("\n Route /assistente is now available."));
|
|
1492
|
+
console.log(chalk.gray(" Configure your Gemini API key in VITE_GEMINI_API_KEY."));
|
|
1493
|
+
} else {
|
|
1494
|
+
console.log(chalk.gray("\n Assistant files removed and AuthGuard updated."));
|
|
1495
|
+
}
|
|
1496
|
+
} catch (error) {
|
|
1497
|
+
spinner2.fail("Failed to update assistant");
|
|
1498
|
+
console.error(error);
|
|
1499
|
+
}
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
if (updateType === "darkmode") {
|
|
1503
|
+
const currentlyDisabled = currentConfig?.disableDarkMode ?? false;
|
|
1504
|
+
const { enableDarkMode } = await prompts({
|
|
1505
|
+
type: "confirm",
|
|
1506
|
+
name: "enableDarkMode",
|
|
1507
|
+
message: currentlyDisabled ? "Enable dark mode support in your project?" : "Disable dark mode support in your project? (This will hide the toggle and force light mode)",
|
|
1508
|
+
initial: !currentlyDisabled
|
|
1509
|
+
});
|
|
1510
|
+
if (enableDarkMode === void 0) return;
|
|
1511
|
+
const newDisableDarkMode = !enableDarkMode;
|
|
1512
|
+
const spinner2 = ora(
|
|
1513
|
+
newDisableDarkMode ? "Disabling dark mode..." : "Enabling dark mode..."
|
|
1514
|
+
).start();
|
|
1515
|
+
try {
|
|
1516
|
+
await writeXerticaConfig(targetDir, { disableDarkMode: newDisableDarkMode });
|
|
1517
|
+
const persistedCodes = await readLanguagesConfig(targetDir);
|
|
1518
|
+
const selectedCodes = persistedCodes && persistedCodes.length > 0 ? persistedCodes : DEFAULT_SELECTION;
|
|
1519
|
+
await fs2.writeFile(
|
|
1520
|
+
path2.join(targetDir, "src", "app", "App.tsx"),
|
|
1521
|
+
generateAppTsx(selectedCodes, newDisableDarkMode)
|
|
1522
|
+
);
|
|
1523
|
+
spinner2.succeed(
|
|
1524
|
+
newDisableDarkMode ? "Dark mode disabled successfully! (Locked to Light Mode)" : "Dark mode enabled successfully!"
|
|
1525
|
+
);
|
|
1526
|
+
} catch (error) {
|
|
1527
|
+
spinner2.fail("Failed to update dark mode configuration");
|
|
1528
|
+
console.error(error);
|
|
1529
|
+
}
|
|
1530
|
+
return;
|
|
1531
|
+
}
|
|
1185
1532
|
const { versionType } = await prompts({
|
|
1186
1533
|
type: "select",
|
|
1187
1534
|
name: "versionType",
|
|
@@ -1281,17 +1628,32 @@ ${summary.join("\n")}
|
|
|
1281
1628
|
if (selectedCodes.length === 0) selectedCodes = DEFAULT_SELECTION;
|
|
1282
1629
|
await writeLanguagesConfig(targetDir, selectedCodes);
|
|
1283
1630
|
}
|
|
1631
|
+
const projectConfig = await readXerticaConfig(targetDir);
|
|
1284
1632
|
await fs2.writeFile(
|
|
1285
1633
|
path2.join(targetDir, "src", "app", "App.tsx"),
|
|
1286
|
-
generateAppTsx(selectedCodes)
|
|
1287
|
-
);
|
|
1288
|
-
await fs2.writeFile(
|
|
1289
|
-
path2.join(targetDir, "src", "i18n.ts"),
|
|
1290
|
-
generateI18nFile(selectedCodes)
|
|
1634
|
+
generateAppTsx(selectedCodes, projectConfig?.disableDarkMode ?? false)
|
|
1291
1635
|
);
|
|
1636
|
+
await fs2.writeFile(path2.join(targetDir, "src", "i18n.ts"), generateI18nFile(selectedCodes));
|
|
1292
1637
|
await syncLocaleFiles(updatedTemplatesDir, targetDir, selectedCodes, {
|
|
1293
1638
|
pruneOthers: true
|
|
1294
1639
|
});
|
|
1640
|
+
const pagesDir = path2.join(targetDir, "src", "pages");
|
|
1641
|
+
const existingPages = await fs2.pathExists(pagesDir) ? await fs2.readdir(pagesDir) : [];
|
|
1642
|
+
const hasLoginP = existingPages.includes("LoginPage.tsx");
|
|
1643
|
+
const hasHomeP = existingPages.includes("HomePage.tsx");
|
|
1644
|
+
const hasTemplateP = existingPages.includes("TemplatePage.tsx");
|
|
1645
|
+
const hasAssistantP = projectConfig?.hasAssistant ?? existingPages.includes("AssistantPage.tsx");
|
|
1646
|
+
const firstProtectedP = hasHomeP ? "/home" : hasTemplateP ? "/template" : "/login";
|
|
1647
|
+
await fs2.writeFile(
|
|
1648
|
+
path2.join(targetDir, "src", "app", "components", "AuthGuard.tsx"),
|
|
1649
|
+
generateAuthGuard({
|
|
1650
|
+
hasLogin: hasLoginP,
|
|
1651
|
+
hasHome: hasHomeP,
|
|
1652
|
+
hasTemplate: hasTemplateP,
|
|
1653
|
+
hasAssistant: hasAssistantP,
|
|
1654
|
+
firstProtectedPath: firstProtectedP
|
|
1655
|
+
})
|
|
1656
|
+
);
|
|
1295
1657
|
}
|
|
1296
1658
|
if (filesToUpdate.includes("shared")) {
|
|
1297
1659
|
await fs2.copy(
|
|
@@ -1313,8 +1675,24 @@ ${summary.join("\n")}
|
|
|
1313
1675
|
const pagesDir = path2.join(targetDir, "src", "pages");
|
|
1314
1676
|
const srcPagesDir = path2.join(updatedTemplatesDir, "src", "pages");
|
|
1315
1677
|
if (await fs2.pathExists(pagesDir) && await fs2.pathExists(srcPagesDir)) {
|
|
1678
|
+
const projectCfg = await readXerticaConfig(targetDir);
|
|
1316
1679
|
const existingPages = await fs2.readdir(pagesDir);
|
|
1680
|
+
const assistantEnabled = projectCfg?.hasAssistant ?? existingPages.includes("AssistantPage.tsx");
|
|
1317
1681
|
for (const pageFile of existingPages) {
|
|
1682
|
+
if (pageFile === "HomePage.tsx") {
|
|
1683
|
+
await fs2.writeFile(
|
|
1684
|
+
path2.join(pagesDir, "HomePage.tsx"),
|
|
1685
|
+
generateHomePage(assistantEnabled)
|
|
1686
|
+
);
|
|
1687
|
+
continue;
|
|
1688
|
+
}
|
|
1689
|
+
if (pageFile === "TemplatePage.tsx") {
|
|
1690
|
+
await fs2.writeFile(
|
|
1691
|
+
path2.join(pagesDir, "TemplatePage.tsx"),
|
|
1692
|
+
generateTemplatePage(assistantEnabled)
|
|
1693
|
+
);
|
|
1694
|
+
continue;
|
|
1695
|
+
}
|
|
1318
1696
|
const src = path2.join(srcPagesDir, pageFile);
|
|
1319
1697
|
if (await fs2.pathExists(src)) {
|
|
1320
1698
|
await fs2.copy(src, path2.join(pagesDir, pageFile), { overwrite: true });
|