xertica-ui 2.2.1 → 2.3.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 +27 -0
- package/README.md +27 -3
- package/assets/xertica-logo.svg +37 -37
- package/assets/xertica-x-logo.svg +20 -20
- package/bin/cli.ts +477 -70
- package/bin/generate-tokens.ts +262 -262
- package/bin/language-config.ts +361 -361
- package/components/assets/xertica-orbe-animation.ts +1162 -1162
- 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/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 +554 -554
- 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/AssistantTypingIndicator.tsx +41 -41
- package/components/assistant/xertica-assistant/parts/index.ts +16 -16
- package/components/assistant/xertica-assistant/types.ts +134 -134
- package/components/assistant/xertica-assistant/xertica-assistant.stories.tsx +407 -407
- package/components/assistant/xertica-assistant/xertica-assistant.test.tsx +65 -65
- package/components/blocks/card-patterns/ActivityCardSkeleton.tsx +56 -56
- package/components/blocks/card-patterns/FeatureCard.tsx +109 -109
- package/components/blocks/card-patterns/FeatureCardSkeleton.tsx +63 -63
- package/components/blocks/card-patterns/NotificationCardSkeleton.tsx +81 -81
- package/components/blocks/card-patterns/ProfileCardSkeleton.tsx +69 -69
- package/components/blocks/card-patterns/ProjectCardSkeleton.tsx +72 -72
- package/components/blocks/card-patterns/QuickActionCard.tsx +68 -68
- package/components/blocks/card-patterns/QuickActionCardSkeleton.tsx +44 -44
- package/components/blocks/card-patterns/card-patterns.mdx +123 -123
- 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/LanguageSelector.tsx +102 -102
- 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 +114 -114
- package/components/brand/language-selector/language-selector.test.tsx +101 -101
- 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 +112 -112
- package/components/brand/xertica-provider/index.ts +1 -1
- package/components/brand/xertica-provider/xertica-provider.mdx +61 -61
- 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/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.mdx +1 -1
- package/components/layout/sidebar/sidebar.stories.tsx +586 -586
- package/components/layout/sidebar/sidebar.test.tsx +76 -76
- package/components/layout/sidebar/use-sidebar.ts +104 -104
- 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 +1 -1
- 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/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 +1 -1
- package/components/pages/home-content/home-content.mdx +62 -62
- package/components/pages/home-content/index.ts +1 -1
- package/components/pages/home-page/HomePage.stories.tsx +39 -39
- package/components/pages/home-page/home-page.mdx +53 -53
- 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/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/index.ts +1 -1
- package/components/pages/template-content/TemplateContent.stories.tsx +43 -43
- package/components/pages/template-content/TemplateContent.tsx +1 -1
- package/components/pages/template-content/index.ts +1 -1
- package/components/pages/template-content/template-content.mdx +61 -61
- 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.mdx +53 -53
- 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/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 +132 -132
- package/components/shared/error-boundary.tsx +154 -154
- package/components/shared/error-fallbacks.tsx +226 -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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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/stats-card-skeleton.tsx +62 -62
- package/components/ui/stats-card/stats-card.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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.mdx +8 -8
- 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/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 +118 -118
- package/contexts/BrandColorsContext.test.tsx +21 -21
- package/contexts/BrandColorsContext.tsx +251 -251
- package/contexts/LanguageContext.test.tsx +121 -121
- package/contexts/LanguageContext.tsx +251 -251
- 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-BAx9VQvb.cjs → AssistantChart-Bdd44uBn.cjs} +388 -127
- package/dist/{AssistantChart-CVko2A1W.js → AssistantChart-CFhDdGyU.js} +391 -130
- package/dist/AssistantChart-COGiOV-g.cjs +3541 -0
- package/dist/AssistantChart-CWX1OWNM.js +3373 -0
- package/dist/{AssistantChart-CVzmmhx4.js → AssistantChart-C_hwFRRr.js} +4 -4
- package/dist/{AssistantChart-BAudAfne.cjs → AssistantChart-CldVCVDe.cjs} +5 -5
- package/dist/{AssistantChart-BP8upjMk.js → AssistantChart-Cu3m7RBo.js} +5 -5
- package/dist/AssistantChart-CxGjH7Qk.js +3477 -0
- package/dist/AssistantChart-DIpshm3i.js +4784 -0
- package/dist/AssistantChart-D_PTeu8P.cjs +3503 -0
- package/dist/{AssistantChart-9w31gdAb.cjs → AssistantChart-DoZCyS5r.cjs} +4 -4
- package/dist/AssistantChart-zjsy2GaZ.cjs +4810 -0
- package/dist/AudioPlayer-9psiEucT.cjs +1282 -0
- package/dist/AudioPlayer-B1lt5cPl.cjs +989 -0
- package/dist/AudioPlayer-BZ7bibzU.cjs +982 -0
- package/dist/AudioPlayer-BpRPS4-1.cjs +1277 -0
- package/dist/AudioPlayer-C12BjQBV.cjs +997 -0
- package/dist/{AudioPlayer-1ypwE2Wh.cjs → AudioPlayer-CFeV8t-5.cjs} +1 -1
- package/dist/{AudioPlayer-DuKXrCfy.js → AudioPlayer-CGRUtUdN.js} +1 -1
- package/dist/AudioPlayer-Coly3q5R.js +1278 -0
- package/dist/AudioPlayer-CySJIyvL.js +937 -0
- package/dist/AudioPlayer-DMcG_c7L.js +990 -0
- package/dist/AudioPlayer-DcFKRJE_.js +998 -0
- package/dist/AudioPlayer-Dp2bD1Gk.js +1278 -0
- package/dist/AudioPlayer-IAU5q5T1.cjs +936 -0
- package/dist/AudioPlayer-e8LfNoqO.js +983 -0
- package/dist/BrandColorsContext-565dDHd5.js +660 -0
- package/dist/BrandColorsContext-BcJbtkqn.cjs +659 -0
- package/dist/BrandColorsContext-DZT7JjeD.js +659 -0
- package/dist/BrandColorsContext-awnBCmC4.cjs +666 -0
- package/dist/{xertica-assistant-Qp3ydksa.cjs → CodeBlock-7TTgmdGG.cjs} +263 -51
- package/dist/{xertica-assistant-gnCJdcZY.js → CodeBlock-BeSt1h5P.js} +219 -7
- package/dist/CodeBlock-BgfYL_rD.cjs +2094 -0
- package/dist/CodeBlock-BlcqlA9M.cjs +2094 -0
- package/dist/CodeBlock-Bnmeu5ez.cjs +2094 -0
- package/dist/CodeBlock-BtfPlbAI.js +2078 -0
- package/dist/CodeBlock-CIySIuYr.js +2078 -0
- package/dist/CodeBlock-CuPtUM-7.cjs +2094 -0
- package/dist/CodeBlock-D6ffWXgc.js +2078 -0
- package/dist/CodeBlock-D8dcwbit.cjs +2094 -0
- package/dist/CodeBlock-DMZrFnlw.cjs +2094 -0
- package/dist/CodeBlock-DYkTfR0f.js +221 -0
- package/dist/CodeBlock-DlBehYN8.js +2078 -0
- package/dist/CodeBlock-DnYNI8rQ.js +2078 -0
- package/dist/CodeBlock-DvKWbSnE.cjs +2094 -0
- package/dist/CodeBlock-DwMCfkFY.js +2078 -0
- package/dist/CodeBlock-Dy6CNYyj.js +2078 -0
- package/dist/CodeBlock-EOvp9cVu.cjs +223 -0
- package/dist/CodeBlock-U1pPOQI7.cjs +2094 -0
- package/dist/CodeBlock-f_GpNhEB.js +2078 -0
- package/dist/CodeBlock-oB6u8nI1.js +2078 -0
- package/dist/CodeBlock-tZC31B73.cjs +2094 -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-CxC-7C-C.cjs +300 -0
- package/dist/FeatureCard-DNycVGwT.js +485 -0
- package/dist/FeatureCard-DbHWCb4E.js +301 -0
- package/dist/FeatureCardSkeleton-DZqc96mt.js +27 -0
- package/dist/FeatureCardSkeleton-pTa0YNKP.cjs +29 -0
- package/dist/ImageWithFallback-CGtidP6B.cjs +4542 -0
- package/dist/ImageWithFallback-lsg3pdFg.js +4508 -0
- package/dist/{LanguageContext-DvUt5jBg.cjs → LanguageContext-B_KFTCzT.cjs} +2 -2
- package/dist/{LanguageContext-BwhwC3G2.js → LanguageContext-CS14yCpi.js} +2 -2
- package/dist/{XerticaXLogo-BWaag64t.js → LanguageSelector-B5YfbHra.js} +115 -136
- package/dist/{XerticaXLogo-DTee_y8X.cjs → LanguageSelector-D6uacAIM.cjs} +115 -136
- package/dist/LayoutContext-B45-e9DI.cjs +93 -0
- package/dist/LayoutContext-BAql6ZRY.js +97 -0
- package/dist/LayoutContext-BEq_-n98.cjs +96 -0
- package/dist/LayoutContext-Bav3UMEA.js +94 -0
- package/dist/LayoutContext-BvK-ggDa.cjs +96 -0
- package/dist/LayoutContext-DNl1xSoX.js +92 -0
- package/dist/{ThemeContext-Bo-W2WZH.js → ThemeContext-BWq9ACPo.js} +8 -13
- package/dist/{ThemeContext-ept8jhXI.js → ThemeContext-BXjrgUjW.js} +261 -200
- package/dist/{ThemeContext-BblcjQup.cjs → ThemeContext-Bmod0Cg2.cjs} +8 -13
- package/dist/ThemeContext-BoH4NLfN.js +734 -0
- package/dist/{ThemeContext-BbBNoFTG.js → ThemeContext-C2EwAPDt.js} +2 -2
- package/dist/{ThemeContext-U4dEYc6C.cjs → ThemeContext-CGk3KK0k.cjs} +1 -8
- package/dist/{ThemeContext-CP3a0jxy.cjs → ThemeContext-CMD3z2Dz.cjs} +268 -193
- package/dist/{ThemeContext-D3LzacmG.js → ThemeContext-CQSo4Iwc.js} +1 -8
- package/dist/ThemeContext-j5aGtPky.cjs +1924 -0
- package/dist/ThemeContext-r69W20Xg.cjs +733 -0
- package/dist/{ThemeContext-Cmr8Ex8H.cjs → ThemeContext-vTjumZeM.cjs} +2 -2
- package/dist/ThemeContext-x_F2zsnv.js +1923 -0
- package/dist/{VerifyEmailPage-BRSP-Pwt.cjs → VerifyEmailPage--1Vurewl.cjs} +3 -3
- package/dist/{VerifyEmailPage-BE-L9mB7.js → VerifyEmailPage-1WwWczAn.js} +12 -22
- package/dist/{VerifyEmailPage-DF2ilhum.cjs → VerifyEmailPage-B4peJjAT.cjs} +356 -334
- package/dist/{VerifyEmailPage-CR7kb5df.cjs → VerifyEmailPage-BComraR7.cjs} +12 -22
- package/dist/{VerifyEmailPage-hdB8JQGv.cjs → VerifyEmailPage-By3Jf__L.cjs} +348 -329
- package/dist/{VerifyEmailPage-BiRm7Nh4.cjs → VerifyEmailPage-ByerOcm4.cjs} +348 -329
- package/dist/{VerifyEmailPage-CbgjOF0v.js → VerifyEmailPage-C0c2e5n0.js} +7 -7
- package/dist/{VerifyEmailPage-EhudUdqF.js → VerifyEmailPage-C5TNQTBa.js} +355 -343
- package/dist/{VerifyEmailPage-Dt7zgA4w.cjs → VerifyEmailPage-CFLMls1p.cjs} +4 -4
- package/dist/{VerifyEmailPage-vYHbYK3q.js → VerifyEmailPage-CJLz3jrn.js} +347 -338
- package/dist/VerifyEmailPage-COiyNl1y.js +2825 -0
- package/dist/{VerifyEmailPage-DMBh4NM9.cjs → VerifyEmailPage-CYXtbKi3.cjs} +1 -1
- package/dist/{VerifyEmailPage-DTtFfC-J.js → VerifyEmailPage-CgMxRb4z.js} +3 -3
- package/dist/VerifyEmailPage-CqKsR2v8.js +2827 -0
- package/dist/{VerifyEmailPage-Bae2cBXT.cjs → VerifyEmailPage-Cwi3kbol.cjs} +7 -7
- package/dist/{VerifyEmailPage-BIBOKV7Z.js → VerifyEmailPage-DSBMRHtl.js} +36 -41
- package/dist/{VerifyEmailPage-D-FRj5TU.cjs → VerifyEmailPage-De6bQjrz.cjs} +36 -41
- package/dist/{VerifyEmailPage-Bvfv8HVQ.js → VerifyEmailPage-DgIid028.js} +347 -338
- package/dist/VerifyEmailPage-DjQKRlUS.cjs +2824 -0
- package/dist/{VerifyEmailPage-CdYPSJoO.js → VerifyEmailPage-DvMLZgFt.js} +1 -1
- package/dist/{VerifyEmailPage-C_ihbcth.js → VerifyEmailPage-MTD7AG1Z.js} +4 -4
- package/dist/VerifyEmailPage-s-1X3LDJ.cjs +2826 -0
- package/dist/XerticaOrbe-KL1RBHzw.cjs +1354 -0
- package/dist/XerticaOrbe-Uk2JML1-.cjs +1927 -0
- package/dist/XerticaOrbe-jA5T2iOk.js +1925 -0
- package/dist/XerticaOrbe-zwS1p2a8.js +1355 -0
- package/dist/XerticaProvider-6btlAlzc.js +17 -0
- package/dist/{XerticaProvider-siSt9uG2.js → XerticaProvider-B7EVH-NF.js} +2 -2
- package/dist/{XerticaProvider-AbWlr7Af.cjs → XerticaProvider-BIrqfZ-i.cjs} +11 -8
- package/dist/XerticaProvider-BNoNOxQ5.cjs +16 -0
- package/dist/XerticaProvider-BlY2limY.cjs +38 -0
- package/dist/{XerticaProvider-CWgby5mY.js → XerticaProvider-C1DKnvLh.js} +4 -4
- package/dist/{XerticaProvider-AChwphCO.cjs → XerticaProvider-CBGc4EMA.cjs} +4 -4
- package/dist/{XerticaProvider-BITjgC5p.js → XerticaProvider-CEoWMTxu.js} +2 -2
- package/dist/{XerticaProvider-By8q3Roe.cjs → XerticaProvider-CllrbMEJ.cjs} +2 -2
- package/dist/{XerticaProvider-B8CaV7xu.cjs → XerticaProvider-D-yNhF94.cjs} +1 -1
- package/dist/XerticaProvider-DDuiIcKo.js +39 -0
- package/dist/{XerticaProvider-CWs6EwNa.js → XerticaProvider-DUOJg9iX.js} +10 -10
- package/dist/{XerticaProvider-DQtvJU7m.js → XerticaProvider-DYq4JWtg.js} +1 -1
- package/dist/{XerticaProvider-CjQAQPcn.cjs → XerticaProvider-Dl_b72_l.cjs} +11 -8
- package/dist/{XerticaProvider-D5lLumH-.js → XerticaProvider-Dt5HEzbQ.js} +10 -10
- package/dist/{XerticaProvider-CW9hpCdF.cjs → XerticaProvider-ET0ihewn.cjs} +2 -2
- package/dist/XerticaProvider-cI9hSs27.cjs +38 -0
- package/dist/XerticaProvider-hSwhNQex.js +39 -0
- package/dist/{XerticaXLogo-ChryA6xj.js → XerticaXLogo-B7xQ5dhi.js} +1 -1
- package/dist/{XerticaXLogo-CziKMQil.cjs → XerticaXLogo-CQUUjXoH.cjs} +8 -8
- package/dist/{XerticaXLogo-DfUvz-lD.js → XerticaXLogo-Cmsp-Eey.js} +9 -9
- package/dist/{XerticaXLogo-CFuIlYFH.js → XerticaXLogo-DZbo4vOE.js} +12 -12
- package/dist/{XerticaXLogo-8TTzBjHw.cjs → XerticaXLogo-Zw2B276b.cjs} +1 -1
- package/dist/{XerticaXLogo-kslQ8Tk_.cjs → XerticaXLogo-bvZSgwGF.cjs} +13 -7
- package/dist/{XerticaXLogo-DHz5SugF.js → XerticaXLogo-mqjoBiLI.js} +12 -12
- package/dist/{XerticaXLogo-CU-U-GP4.cjs → XerticaXLogo-uQgwns_E.cjs} +13 -7
- package/dist/alert-dialog-BOje--vD.js +847 -0
- package/dist/alert-dialog-BtEuQqrg.cjs +870 -0
- package/dist/{alert-dialog-yckpaOpy.cjs → alert-dialog-DSKByiKZ.cjs} +3 -3
- package/dist/alert-dialog-DhwPioBa.cjs +885 -0
- package/dist/alert-dialog-DqlRW_An.js +831 -0
- package/dist/{alert-dialog-iDe5VE5o.js → alert-dialog-s-vmNkJ_.js} +3 -3
- 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-CqJ7bHY5.js +161 -0
- package/dist/breadcrumb-ifNsA7Zl.js +90 -0
- package/dist/breadcrumb-m9Hb2_XN.cjs +177 -0
- package/dist/button-0BlA47It.cjs +85 -0
- package/dist/button-DZHzN1Gd.js +62 -0
- package/dist/cli.js +391 -66
- package/dist/components/assistant/xertica-assistant/hooks/index.d.ts +6 -0
- package/dist/components/assistant/xertica-assistant/hooks/use-assistant-conversations.d.ts +21 -0
- package/dist/components/assistant/xertica-assistant/hooks/use-assistant-messages.d.ts +49 -0
- package/dist/components/assistant/xertica-assistant/hooks/use-assistant-suggestions.d.ts +16 -0
- package/dist/components/blocks/audio-player/AudioPlayer.d.ts +35 -0
- package/dist/components/blocks/audio-player/index.d.ts +1 -0
- package/dist/components/blocks/document-editor/DocumentEditor.d.ts +26 -0
- package/dist/components/blocks/document-editor/index.d.ts +1 -0
- package/dist/components/blocks/podcast-player/PodcastPlayer.d.ts +41 -0
- package/dist/components/blocks/podcast-player/index.d.ts +1 -0
- package/dist/components/ui/chart/parts/chart-dashboard.d.ts +113 -0
- package/dist/components/ui/chart/parts/chart-metric.d.ts +118 -0
- package/dist/components/ui/chart/parts/chart-primitives.d.ts +101 -0
- package/dist/components/ui/chart/parts/chart-shared.d.ts +20 -0
- package/dist/components/ui/chart/parts/chart-utils.d.ts +12 -0
- package/dist/components/ui/chart/parts/index.d.ts +5 -0
- package/dist/dropdown-menu-BDB5CmQs.cjs +247 -0
- package/dist/dropdown-menu-BMcykFDf.cjs +225 -0
- package/dist/dropdown-menu-DQidbKBD.js +231 -0
- package/dist/dropdown-menu-Dn_eV2Xb.js +190 -0
- package/dist/google-maps-loader-BCe58h9D.js +308 -0
- package/dist/google-maps-loader-BFWp6VPd.js +287 -0
- package/dist/google-maps-loader-BKcdgFbu.cjs +312 -0
- package/dist/{google-maps-loader-t2IlYBzw.js → google-maps-loader-CTYySAun.js} +4 -0
- package/dist/google-maps-loader-CumCNXeG.js +312 -0
- package/dist/{google-maps-loader-BqsYL48U.cjs → google-maps-loader-Y-QkD-Li.cjs} +5 -0
- package/dist/google-maps-loader-casMyxlo.cjs +316 -0
- package/dist/google-maps-loader-eS3uQ5TA.cjs +287 -0
- package/dist/header-Cgy6vYPk.cjs +731 -0
- package/dist/header-DRlT4jgI.js +715 -0
- package/dist/header-Dux00SI4.cjs +731 -0
- package/dist/header-EkGKXPsD.js +715 -0
- package/dist/header-WfEywpyc.cjs +731 -0
- package/dist/header-tifNQn2U.js +715 -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-BhapVLVj.js +8 -0
- package/dist/{index-D3RLKRAs.cjs → index-COtD8bRW.cjs} +1 -1
- package/dist/index-D6fxYEY8.cjs +7 -0
- package/dist/index-DAIp0_HK.js +8 -0
- package/dist/index-DW5tYe26.js +8 -0
- package/dist/index-GA__GvnG.cjs +7 -0
- package/dist/index.cjs.js +37 -32
- package/dist/index.es.js +30 -363
- package/dist/index.umd.js +1043 -470
- package/dist/input-2R4loU86.js +127 -0
- package/dist/input-C_UiS2Py.cjs +152 -0
- package/dist/input-DWANSKGb.cjs +145 -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/progress-DPtzoVV8.js +175 -0
- package/dist/progress-EeaoqqUs.cjs +191 -0
- package/dist/rich-text-editor-0mraWT5y.cjs +2376 -0
- package/dist/rich-text-editor-B-IkcPD0.js +2874 -0
- package/dist/rich-text-editor-B6jMRLzk.cjs +1939 -0
- package/dist/rich-text-editor-B8_oYcIR.js +1730 -0
- package/dist/rich-text-editor-B9UbSXNb.js +1203 -0
- package/dist/rich-text-editor-BYuRBNBU.js +2373 -0
- package/dist/rich-text-editor-Bb9pySTs.cjs +2374 -0
- package/dist/rich-text-editor-BcL6L3cm.cjs +2374 -0
- package/dist/rich-text-editor-BoVZYtTs.cjs +2391 -0
- package/dist/rich-text-editor-Bp3zQqMC.js +2954 -0
- package/dist/rich-text-editor-CMgSN_w2.js +1189 -0
- package/dist/rich-text-editor-CPV1lEPH.cjs +1748 -0
- package/dist/rich-text-editor-CeucBdIv.cjs +2971 -0
- package/dist/rich-text-editor-CoKqbCtu.cjs +1799 -0
- package/dist/rich-text-editor-Cw56T_mB.js +2356 -0
- package/dist/rich-text-editor-Cyt8qs2b.js +1921 -0
- package/dist/rich-text-editor-D6H84OcX.cjs +1220 -0
- package/dist/rich-text-editor-D76gD-QI.js +2328 -0
- package/dist/rich-text-editor-DKkokOnA.js +1781 -0
- package/dist/rich-text-editor-DNsdpN64.cjs +2359 -0
- package/dist/rich-text-editor-DfG8bCyY.js +2358 -0
- package/dist/rich-text-editor-DqLICivI.js +2832 -0
- package/dist/rich-text-editor-DxO1Hz3a.cjs +2903 -0
- package/dist/rich-text-editor-Dxjw31Z4.js +2341 -0
- package/dist/rich-text-editor-DzP0Epmb.js +2356 -0
- package/dist/rich-text-editor-bRkNoeZY.cjs +2891 -0
- package/dist/rich-text-editor-lyYE2ZG5.cjs +1207 -0
- package/dist/rich-text-editor-skplNlBM.cjs +2345 -0
- package/dist/select-Bkbr0f-Z.cjs +162 -0
- package/dist/select-CH6v_KcQ.cjs +161 -0
- package/dist/select-CvIVdX2n.js +145 -0
- package/dist/select-D-xvCZK2.js +130 -0
- package/dist/{sidebar-CA6_ek3f.js → sidebar-3XyzjVBw.js} +40 -49
- package/dist/{sidebar-CplprZpM.js → sidebar-B6SlKZYN.js} +40 -49
- package/dist/{sidebar-CmvwjnVb.js → sidebar-BViy8Eeu.js} +17 -9
- package/dist/{sidebar-Dz7bd3zP.js → sidebar-BbVIQvlP.js} +1 -1
- package/dist/{sidebar-CVUGHOS_.cjs → sidebar-BxGXsDAd.cjs} +16 -8
- package/dist/sidebar-CK_0ZQHj.cjs +803 -0
- package/dist/sidebar-CUuOvYhK.js +787 -0
- package/dist/{sidebar-KIS0C2JH.js → sidebar-CrQDDdcz.js} +24 -33
- package/dist/{sidebar-zowjejT2.cjs → sidebar-DAaY8bRU.cjs} +24 -33
- package/dist/{sidebar-B9NR0lCe.cjs → sidebar-DQj1z3jG.cjs} +227 -269
- package/dist/sidebar-Djn5syhi.cjs +786 -0
- package/dist/{sidebar-BvF5I2Ue.cjs → sidebar-DyYvgyBj.cjs} +41 -46
- package/dist/sidebar-LluMXfam.js +759 -0
- package/dist/sidebar-_rT7rBMk.js +787 -0
- package/dist/{sidebar-B3EYhli0.cjs → sidebar-nzPoVHBQ.cjs} +41 -46
- package/dist/{sidebar-C5B_LHek.cjs → sidebar-q7P2Godd.cjs} +1 -1
- package/dist/skeleton-DjiHerJn.cjs +87 -0
- package/dist/skeleton-DtR5tkYe.js +78 -0
- package/dist/slider-B00b9SVK.cjs +78 -0
- package/dist/slider-Bc5Hd0y1.js +56 -0
- package/dist/slider-DQCNUUMj.js +56 -0
- package/dist/slider-N7hFFj6X.cjs +73 -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-Ded96neP.cjs +137 -0
- package/dist/tooltip-HDOoD2-0.js +120 -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-B31J-aqh.cjs +187 -0
- package/dist/use-audio-player-B78fd2ct.js +188 -0
- package/dist/use-audio-player-BkmEmj8Q.js +185 -0
- package/dist/use-audio-player-CLFTWFW1.cjs +184 -0
- package/dist/use-audio-player-CLLn00I6.js +188 -0
- package/dist/use-audio-player-DGvhPrgR.cjs +190 -0
- package/dist/{use-audio-player-Dn1NR9xN.cjs → use-audio-player-NKsWyjWu.cjs} +7 -3
- package/dist/{use-audio-player-Bkh23vQ3.js → use-audio-player-nv8ZSGa1.js} +7 -3
- package/dist/use-file-upload-BcjEo2S5.js +404 -0
- package/dist/use-file-upload-CRJR68Tj.cjs +403 -0
- package/dist/use-mobile-B0hNy_Y6.cjs +4303 -0
- package/dist/use-mobile-BXuYROXM.js +4202 -0
- package/dist/use-mobile-Bbd51ASU.cjs +4392 -0
- package/dist/use-mobile-BdXTRb0Z.cjs +51 -0
- package/dist/use-mobile-Bk6CX-TC.js +4359 -0
- package/dist/use-mobile-BvYdisLP.js +4202 -0
- package/dist/use-mobile-BzuxjzNX.cjs +4392 -0
- package/dist/use-mobile-CG2-SdXV.cjs +4235 -0
- package/dist/use-mobile-CKb5pqTs.js +4269 -0
- package/dist/use-mobile-CYuAuGDl.js +4202 -0
- package/dist/use-mobile-CaENcqm-.js +4508 -0
- package/dist/use-mobile-CbrYgJGJ.js +4203 -0
- package/dist/use-mobile-Cd4xPrKq.cjs +46 -0
- package/dist/use-mobile-Ce2cBAQe.js +29 -0
- package/dist/use-mobile-DMOvImGQ.cjs +4542 -0
- package/dist/use-mobile-DRB3BQgD.cjs +4235 -0
- package/dist/use-mobile-DZvv7QMR.js +4359 -0
- package/dist/use-mobile-DdI_TXam.cjs +4235 -0
- package/dist/use-mobile-DlceKf8a.js +4359 -0
- package/dist/use-mobile-DsOnow1o.cjs +4236 -0
- package/dist/use-mobile-Kcj6jSnK.cjs +4392 -0
- package/dist/use-mobile-bnKcua_i.js +4202 -0
- package/dist/use-mobile-j4w2Jrf1.js +30 -0
- package/dist/use-mobile-ncXBeE2z.cjs +4235 -0
- package/dist/use-rich-text-editor-DjiddBGv.js +282 -0
- package/dist/use-rich-text-editor-lpeswbCs.cjs +281 -0
- package/dist/xertica-assistant-B687qEPU.js +2165 -0
- package/dist/xertica-assistant-BdiZag0h.js +2187 -0
- package/dist/xertica-assistant-CrgTb6Hs.cjs +2155 -0
- package/dist/xertica-assistant-DCsnQyi5.js +2156 -0
- package/dist/xertica-assistant-DUBpmEgo.cjs +2186 -0
- package/dist/{xertica-assistant-Bj3vBCq_.cjs → xertica-assistant-V_IdW4WF.cjs} +27 -9
- package/dist/{xertica-assistant-BMqdyRVi.js → xertica-assistant-ciJaWqm1.js} +28 -10
- package/dist/{xertica-assistant-B1IaHXnB.cjs → xertica-assistant-dyP7KHM5.cjs} +533 -392
- package/dist/xertica-assistant-sOHwTgIP.cjs +2172 -0
- package/dist/{xertica-assistant-DPsESB6t.js → xertica-assistant-yX1CFBBo.js} +535 -394
- package/dist/xertica-ui.css +2 -2
- package/docs/ai-usage.md +195 -195
- 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 +2 -0
- 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/breadcrumb.md +104 -104
- package/docs/components/button.md +156 -156
- package/docs/components/calendar.md +141 -141
- 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 +191 -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/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 +172 -172
- 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 +309 -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/form-sizing.md +162 -162
- package/docs/getting-started.md +24 -12
- package/docs/i18n.md +476 -476
- package/docs/installation.md +267 -267
- package/docs/layout.md +143 -143
- 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/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 +10 -4
- 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 +84 -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/.prettierignore +4 -4
- package/templates/.prettierrc +10 -10
- package/templates/CLAUDE.md +165 -165
- package/templates/eslint.config.js +26 -26
- package/templates/package.json +3 -3
- package/templates/postcss.config.js +6 -6
- package/templates/src/app/components/AppLayout.tsx +55 -55
- package/templates/src/app/components/AuthGuard.tsx +82 -82
- package/templates/src/app/context/AuthContext.tsx +108 -108
- package/templates/src/features/assistant/data/mock.ts +75 -75
- package/templates/src/features/assistant/hooks/useAssistantConfig.ts +20 -20
- 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/ResetPasswordContent.tsx +179 -179
- package/templates/src/features/auth/ui/VerifyEmailContent.tsx +84 -84
- package/templates/src/features/home/data/mock.ts +35 -35
- package/templates/src/features/home/hooks/useFeatureCards.ts +20 -20
- package/templates/src/features/home/store/dashboardStore.ts +25 -25
- package/templates/src/features/home/ui/HomeContent.tsx +1 -1
- package/templates/src/features/template/index.ts +5 -5
- package/templates/src/features/template/ui/CrudTemplate.tsx +115 -115
- 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 +1314 -1314
- 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/main.tsx +11 -11
- package/templates/src/pages/AssistantPage.tsx +464 -464
- package/templates/src/pages/ForgotPasswordPage.tsx +6 -6
- 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 +154 -154
- package/templates/src/shared/error-fallbacks.tsx +226 -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.ts +1 -1
- 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/ThemeContext-CpqYShLq.cjs +0 -324
- package/dist/ThemeContext-Du2nE1PL.js +0 -325
- package/dist/ThemeContext-GeEBTJ3q.cjs +0 -1621
- package/dist/ThemeContext-JyLK9B1o.js +0 -1622
- package/dist/XerticaProvider-CUYJZc32.js +0 -49
- package/dist/XerticaProvider-qQUDop71.cjs +0 -48
- package/dist/index-CkTUgOwX.js +0 -8
- package/dist/sidebar-OTO_up7Z.js +0 -801
- package/dist/{rich-text-editor-BmsjY03B.js → rich-text-editor-DgF8s7xW.js} +26 -26
- package/dist/{rich-text-editor-GS2kpTAK.cjs → rich-text-editor-mWoaSCE4.cjs} +26 -26
|
@@ -1,1328 +1,1328 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import {
|
|
3
|
-
ChartContainer,
|
|
4
|
-
ChartTooltip,
|
|
5
|
-
ChartTooltipContent,
|
|
6
|
-
ChartLegend,
|
|
7
|
-
ChartLegendContent,
|
|
8
|
-
ChartCard,
|
|
9
|
-
DashboardBarChart,
|
|
10
|
-
DashboardLineChart,
|
|
11
|
-
HorizontalBarChart,
|
|
12
|
-
InteractiveTimeSeriesChart,
|
|
13
|
-
ComboMetricChart,
|
|
14
|
-
DonutBreakdownChart,
|
|
15
|
-
SparklineChart,
|
|
16
|
-
RadarMetricChart,
|
|
17
|
-
PieMetricChart,
|
|
18
|
-
RadialBarMetricChart,
|
|
19
|
-
GaugeChart,
|
|
20
|
-
type ChartConfig,
|
|
21
|
-
type GaugeChartThreshold,
|
|
22
|
-
} from './chart';
|
|
23
|
-
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, LineChart, Line } from 'recharts';
|
|
24
|
-
import { Card, CardHeader, CardTitle, CardContent } from '../card';
|
|
25
|
-
import React from 'react';
|
|
26
|
-
import { TrendingUp, TrendingDown, Minus } from 'lucide-react';
|
|
27
|
-
|
|
28
|
-
const meta: Meta<typeof DashboardBarChart> = {
|
|
29
|
-
title: 'UI/Chart',
|
|
30
|
-
component: DashboardBarChart,
|
|
31
|
-
render: args => <DashboardBarChart {...args} />,
|
|
32
|
-
parameters: {
|
|
33
|
-
layout: 'fullscreen',
|
|
34
|
-
},
|
|
35
|
-
decorators: [
|
|
36
|
-
Story => (
|
|
37
|
-
<div className="w-full min-w-0 p-8">
|
|
38
|
-
<Story />
|
|
39
|
-
</div>
|
|
40
|
-
),
|
|
41
|
-
],
|
|
42
|
-
argTypes: {
|
|
43
|
-
barSize: {
|
|
44
|
-
control: 'select',
|
|
45
|
-
options: ['sm', 'md', 'lg', 'xl'],
|
|
46
|
-
description: 'Controls only the bar thickness.',
|
|
47
|
-
},
|
|
48
|
-
stacked: { control: 'boolean' },
|
|
49
|
-
showGrid: { control: 'boolean' },
|
|
50
|
-
showLegend: { control: 'boolean' },
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export default meta;
|
|
55
|
-
type Story = StoryObj<typeof DashboardBarChart>;
|
|
56
|
-
|
|
57
|
-
// ─── Shared data ──────────────────────────────────────────────────────────────
|
|
58
|
-
|
|
59
|
-
const data = [
|
|
60
|
-
{ month: 'Jan', revenue: 4000, expenses: 2400 },
|
|
61
|
-
{ month: 'Feb', revenue: 3000, expenses: 1398 },
|
|
62
|
-
{ month: 'Mar', revenue: 6000, expenses: 3200 },
|
|
63
|
-
{ month: 'Apr', revenue: 2780, expenses: 3908 },
|
|
64
|
-
{ month: 'May', revenue: 1890, expenses: 4800 },
|
|
65
|
-
{ month: 'Jun', revenue: 2390, expenses: 3800 },
|
|
66
|
-
];
|
|
67
|
-
|
|
68
|
-
const chartConfig: ChartConfig = {
|
|
69
|
-
revenue: { label: 'Revenue', color: 'var(--chart-1)' },
|
|
70
|
-
expenses: { label: 'Expenses', color: 'var(--chart-5)' },
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const richChartConfig: ChartConfig = {
|
|
74
|
-
revenue: { label: 'Revenue', color: 'var(--chart-1)' },
|
|
75
|
-
pipeline: { label: 'Pipeline', color: 'var(--chart-4)' },
|
|
76
|
-
conversion: { label: 'Conversion', color: 'var(--chart-2)' },
|
|
77
|
-
churn: { label: 'Churn', color: 'var(--chart-5)' },
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const richData = [
|
|
81
|
-
{ date: 'Apr 01', revenue: 4200, pipeline: 2600, conversion: 32, churn: 8 },
|
|
82
|
-
{ date: 'Apr 08', revenue: 5200, pipeline: 3200, conversion: 38, churn: 7 },
|
|
83
|
-
{ date: 'Apr 15', revenue: 6100, pipeline: 3900, conversion: 42, churn: 6 },
|
|
84
|
-
{ date: 'Apr 22', revenue: 5600, pipeline: 4300, conversion: 41, churn: 9 },
|
|
85
|
-
{ date: 'Apr 29', revenue: 7200, pipeline: 4700, conversion: 48, churn: 5 },
|
|
86
|
-
{ date: 'May 06', revenue: 7900, pipeline: 5300, conversion: 52, churn: 4 },
|
|
87
|
-
{ date: 'May 13', revenue: 8400, pipeline: 5800, conversion: 55, churn: 3 },
|
|
88
|
-
{ date: 'May 20', revenue: 9100, pipeline: 6200, conversion: 58, churn: 4 },
|
|
89
|
-
];
|
|
90
|
-
|
|
91
|
-
const breakdownConfig: ChartConfig = {
|
|
92
|
-
enterprise: { label: 'Enterprise', color: 'var(--chart-1)' },
|
|
93
|
-
midmarket: { label: 'Mid-market', color: 'var(--chart-4)' },
|
|
94
|
-
startup: { label: 'Startup', color: 'var(--chart-2)' },
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const breakdownData = [
|
|
98
|
-
{ name: 'enterprise', value: 52 },
|
|
99
|
-
{ name: 'midmarket', value: 31 },
|
|
100
|
-
{ name: 'startup', value: 17 },
|
|
101
|
-
];
|
|
102
|
-
|
|
103
|
-
// ─── Primitive stories ────────────────────────────────────────────────────────
|
|
104
|
-
|
|
105
|
-
export const BarChartExample: Story = {
|
|
106
|
-
name: 'Primitive / Bar Chart',
|
|
107
|
-
render: () => (
|
|
108
|
-
<Card className="w-full max-w-4xl">
|
|
109
|
-
<CardHeader>
|
|
110
|
-
<CardTitle>Monthly Performance</CardTitle>
|
|
111
|
-
</CardHeader>
|
|
112
|
-
<CardContent>
|
|
113
|
-
<ChartContainer config={chartConfig} className="h-[300px] w-full">
|
|
114
|
-
<BarChart data={data}>
|
|
115
|
-
<CartesianGrid vertical={false} strokeDasharray="3 3" />
|
|
116
|
-
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
|
117
|
-
<ChartTooltip content={<ChartTooltipContent />} />
|
|
118
|
-
<ChartLegend content={<ChartLegendContent />} />
|
|
119
|
-
<Bar dataKey="revenue" fill="var(--color-revenue)" radius={[4, 4, 0, 0]} />
|
|
120
|
-
<Bar dataKey="expenses" fill="var(--color-expenses)" radius={[4, 4, 0, 0]} />
|
|
121
|
-
</BarChart>
|
|
122
|
-
</ChartContainer>
|
|
123
|
-
</CardContent>
|
|
124
|
-
</Card>
|
|
125
|
-
),
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
export const LineChartExample: Story = {
|
|
129
|
-
name: 'Primitive / Line Chart',
|
|
130
|
-
render: () => (
|
|
131
|
-
<Card className="w-full max-w-4xl">
|
|
132
|
-
<CardHeader>
|
|
133
|
-
<CardTitle>Revenue Trends</CardTitle>
|
|
134
|
-
</CardHeader>
|
|
135
|
-
<CardContent>
|
|
136
|
-
<ChartContainer config={chartConfig} className="h-[300px] w-full">
|
|
137
|
-
<LineChart data={data}>
|
|
138
|
-
<CartesianGrid vertical={false} strokeDasharray="3 3" />
|
|
139
|
-
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
|
140
|
-
<ChartTooltip content={<ChartTooltipContent />} />
|
|
141
|
-
<Line
|
|
142
|
-
type="monotone"
|
|
143
|
-
dataKey="revenue"
|
|
144
|
-
stroke="var(--color-revenue)"
|
|
145
|
-
strokeWidth={3}
|
|
146
|
-
dot={{ r: 4, fill: 'var(--color-revenue)', strokeWidth: 0 }}
|
|
147
|
-
activeDot={{ r: 6, strokeWidth: 0 }}
|
|
148
|
-
/>
|
|
149
|
-
</LineChart>
|
|
150
|
-
</ChartContainer>
|
|
151
|
-
</CardContent>
|
|
152
|
-
</Card>
|
|
153
|
-
),
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// ─── Dashboard chart stories ──────────────────────────────────────────────────
|
|
157
|
-
|
|
158
|
-
export const DashboardBarChartExample: Story = {
|
|
159
|
-
name: 'Bar Chart',
|
|
160
|
-
args: {
|
|
161
|
-
data: richData,
|
|
162
|
-
indexKey: 'date',
|
|
163
|
-
config: richChartConfig,
|
|
164
|
-
colors: {
|
|
165
|
-
revenue: 'var(--chart-1)',
|
|
166
|
-
pipeline: 'var(--chart-4)',
|
|
167
|
-
},
|
|
168
|
-
barSize: 'lg',
|
|
169
|
-
series: [
|
|
170
|
-
{ key: 'revenue', stackId: 'money' },
|
|
171
|
-
{ key: 'pipeline', stackId: 'money' },
|
|
172
|
-
],
|
|
173
|
-
stacked: true,
|
|
174
|
-
},
|
|
175
|
-
render: args => (
|
|
176
|
-
<ChartCard title="Revenue by Week" description="Stacked dashboard-ready comparison">
|
|
177
|
-
<DashboardBarChart {...args} />
|
|
178
|
-
</ChartCard>
|
|
179
|
-
),
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
export const DashboardLineChartExample: Story = {
|
|
183
|
-
name: 'Line Chart',
|
|
184
|
-
render: () => (
|
|
185
|
-
<ChartCard title="Growth Trend" description="Multi-series line chart with smooth curves">
|
|
186
|
-
<DashboardLineChart
|
|
187
|
-
data={richData}
|
|
188
|
-
indexKey="date"
|
|
189
|
-
config={richChartConfig}
|
|
190
|
-
colors={{
|
|
191
|
-
revenue: 'var(--chart-1)',
|
|
192
|
-
pipeline: 'var(--chart-4)',
|
|
193
|
-
conversion: 'var(--chart-2)',
|
|
194
|
-
}}
|
|
195
|
-
series={[
|
|
196
|
-
{ key: 'revenue', label: 'Revenue' },
|
|
197
|
-
{ key: 'pipeline', label: 'Pipeline' },
|
|
198
|
-
{ key: 'conversion', label: 'Conversion' },
|
|
199
|
-
]}
|
|
200
|
-
showDots
|
|
201
|
-
curveType="monotone"
|
|
202
|
-
strokeWidth={2.5}
|
|
203
|
-
/>
|
|
204
|
-
</ChartCard>
|
|
205
|
-
),
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
export const HorizontalBarChartExample: Story = {
|
|
209
|
-
name: 'Horizontal Bar Chart',
|
|
210
|
-
render: () => (
|
|
211
|
-
<ChartCard title="Top Segments" description="Ranking chart for dashboard comparisons">
|
|
212
|
-
<HorizontalBarChart
|
|
213
|
-
data={[
|
|
214
|
-
{ segment: 'Enterprise', revenue: 7600 },
|
|
215
|
-
{ segment: 'Mid-market', revenue: 5400 },
|
|
216
|
-
{ segment: 'Startup', revenue: 3100 },
|
|
217
|
-
{ segment: 'Partners', revenue: 2200 },
|
|
218
|
-
]}
|
|
219
|
-
indexKey="segment"
|
|
220
|
-
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
|
|
221
|
-
colors={{ revenue: 'var(--chart-1)' }}
|
|
222
|
-
barSize="xl"
|
|
223
|
-
categoryWidth={110}
|
|
224
|
-
showLegend={false}
|
|
225
|
-
/>
|
|
226
|
-
</ChartCard>
|
|
227
|
-
),
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
export const InteractiveTimeSeriesExample: Story = {
|
|
231
|
-
name: 'Interactive Time Series',
|
|
232
|
-
render: () => (
|
|
233
|
-
<ChartCard
|
|
234
|
-
title="Executive Trend"
|
|
235
|
-
description="Switch metric and period without leaving the card"
|
|
236
|
-
>
|
|
237
|
-
<InteractiveTimeSeriesChart
|
|
238
|
-
data={richData}
|
|
239
|
-
indexKey="date"
|
|
240
|
-
config={richChartConfig}
|
|
241
|
-
colors={['var(--chart-1)', 'var(--chart-4)', 'var(--chart-2)']}
|
|
242
|
-
series={[
|
|
243
|
-
{ key: 'revenue', label: 'Revenue' },
|
|
244
|
-
{ key: 'pipeline', label: 'Pipeline' },
|
|
245
|
-
{ key: 'conversion', label: 'Conversion' },
|
|
246
|
-
]}
|
|
247
|
-
gradientFill
|
|
248
|
-
/>
|
|
249
|
-
</ChartCard>
|
|
250
|
-
),
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
export const GradientAreaChartExample: Story = {
|
|
254
|
-
name: 'Gradient Area Chart',
|
|
255
|
-
render: () => (
|
|
256
|
-
<ChartCard
|
|
257
|
-
title="Revenue Over Time"
|
|
258
|
-
description="Area chart with gradient fill for a modern look"
|
|
259
|
-
>
|
|
260
|
-
<InteractiveTimeSeriesChart
|
|
261
|
-
data={richData}
|
|
262
|
-
indexKey="date"
|
|
263
|
-
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
|
|
264
|
-
colors={['var(--chart-1)']}
|
|
265
|
-
series={[{ key: 'revenue', label: 'Revenue' }]}
|
|
266
|
-
gradientFill
|
|
267
|
-
showDots
|
|
268
|
-
periods={[
|
|
269
|
-
{ value: '7d', label: '7 days' },
|
|
270
|
-
{ value: '30d', label: '30 days' },
|
|
271
|
-
]}
|
|
272
|
-
/>
|
|
273
|
-
</ChartCard>
|
|
274
|
-
),
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
export const ComboMetricChartExample: Story = {
|
|
278
|
-
name: 'Combo Metric Chart',
|
|
279
|
-
render: () => (
|
|
280
|
-
<ChartCard title="Pipeline Health" description="Bars for volume with a line for rate">
|
|
281
|
-
<ComboMetricChart
|
|
282
|
-
data={richData}
|
|
283
|
-
indexKey="date"
|
|
284
|
-
config={richChartConfig}
|
|
285
|
-
colors={{
|
|
286
|
-
pipeline: 'var(--chart-4)',
|
|
287
|
-
conversion: 'var(--chart-2)',
|
|
288
|
-
}}
|
|
289
|
-
barSize="lg"
|
|
290
|
-
series={[
|
|
291
|
-
{ key: 'pipeline', type: 'bar' },
|
|
292
|
-
{ key: 'conversion', type: 'line' },
|
|
293
|
-
]}
|
|
294
|
-
/>
|
|
295
|
-
</ChartCard>
|
|
296
|
-
),
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
export const ComboWithGradientAreaExample: Story = {
|
|
300
|
-
name: 'Combo Chart with Gradient Area',
|
|
301
|
-
render: () => (
|
|
302
|
-
<ChartCard
|
|
303
|
-
title="Revenue & Pipeline"
|
|
304
|
-
description="Gradient area for revenue, line for conversion rate"
|
|
305
|
-
>
|
|
306
|
-
<ComboMetricChart
|
|
307
|
-
data={richData}
|
|
308
|
-
indexKey="date"
|
|
309
|
-
config={richChartConfig}
|
|
310
|
-
colors={{
|
|
311
|
-
revenue: 'var(--chart-1)',
|
|
312
|
-
conversion: 'var(--chart-2)',
|
|
313
|
-
}}
|
|
314
|
-
series={[
|
|
315
|
-
{ key: 'revenue', type: 'area' },
|
|
316
|
-
{ key: 'conversion', type: 'line' },
|
|
317
|
-
]}
|
|
318
|
-
gradientFill
|
|
319
|
-
curveType="monotone"
|
|
320
|
-
/>
|
|
321
|
-
</ChartCard>
|
|
322
|
-
),
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
export const DonutBreakdownExample: Story = {
|
|
326
|
-
name: 'Donut Chart',
|
|
327
|
-
render: () => (
|
|
328
|
-
<ChartCard title="Customer Mix" description="Interactive segment breakdown">
|
|
329
|
-
<DonutBreakdownChart
|
|
330
|
-
data={breakdownData}
|
|
331
|
-
config={breakdownConfig}
|
|
332
|
-
colors={['var(--chart-1)', 'var(--chart-4)', 'var(--chart-2)']}
|
|
333
|
-
centerValue="100%"
|
|
334
|
-
centerLabel="Accounts"
|
|
335
|
-
/>
|
|
336
|
-
</ChartCard>
|
|
337
|
-
),
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
// ─── Sparkline stories ────────────────────────────────────────────────────────
|
|
341
|
-
|
|
342
|
-
const sparkData = [
|
|
343
|
-
{ v: 12 },
|
|
344
|
-
{ v: 18 },
|
|
345
|
-
{ v: 14 },
|
|
346
|
-
{ v: 22 },
|
|
347
|
-
{ v: 19 },
|
|
348
|
-
{ v: 28 },
|
|
349
|
-
{ v: 24 },
|
|
350
|
-
{ v: 31 },
|
|
351
|
-
{ v: 27 },
|
|
352
|
-
{ v: 35 },
|
|
353
|
-
];
|
|
354
|
-
|
|
355
|
-
const sparkDataDown = [
|
|
356
|
-
{ v: 35 },
|
|
357
|
-
{ v: 30 },
|
|
358
|
-
{ v: 28 },
|
|
359
|
-
{ v: 22 },
|
|
360
|
-
{ v: 25 },
|
|
361
|
-
{ v: 18 },
|
|
362
|
-
{ v: 20 },
|
|
363
|
-
{ v: 14 },
|
|
364
|
-
{ v: 12 },
|
|
365
|
-
{ v: 8 },
|
|
366
|
-
];
|
|
367
|
-
|
|
368
|
-
export const SparklineExample: Story = {
|
|
369
|
-
name: 'Sparkline Chart',
|
|
370
|
-
render: () => (
|
|
371
|
-
<div className="space-y-6 max-w-2xl">
|
|
372
|
-
<p className="text-sm text-muted-foreground">
|
|
373
|
-
Sparklines are minimal inline charts designed for stat cards and table cells.
|
|
374
|
-
</p>
|
|
375
|
-
|
|
376
|
-
{/* Stat cards with sparklines */}
|
|
377
|
-
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
|
378
|
-
<Card className="p-4">
|
|
379
|
-
<div className="flex items-start justify-between mb-3">
|
|
380
|
-
<div>
|
|
381
|
-
<p className="text-xs text-muted-foreground font-medium uppercase tracking-wide">
|
|
382
|
-
Revenue
|
|
383
|
-
</p>
|
|
384
|
-
<p className="text-2xl font-bold mt-0.5">$35.2K</p>
|
|
385
|
-
</div>
|
|
386
|
-
<span className="inline-flex items-center gap-1 text-xs font-medium text-emerald-600 bg-emerald-50 dark:bg-emerald-950 dark:text-emerald-400 px-2 py-0.5 rounded-full">
|
|
387
|
-
<TrendingUp className="size-3" />
|
|
388
|
-
+12%
|
|
389
|
-
</span>
|
|
390
|
-
</div>
|
|
391
|
-
<SparklineChart
|
|
392
|
-
data={sparkData}
|
|
393
|
-
dataKey="v"
|
|
394
|
-
color="var(--chart-2)"
|
|
395
|
-
filled
|
|
396
|
-
showEndDot
|
|
397
|
-
className="h-12"
|
|
398
|
-
/>
|
|
399
|
-
</Card>
|
|
400
|
-
|
|
401
|
-
<Card className="p-4">
|
|
402
|
-
<div className="flex items-start justify-between mb-3">
|
|
403
|
-
<div>
|
|
404
|
-
<p className="text-xs text-muted-foreground font-medium uppercase tracking-wide">
|
|
405
|
-
Churn
|
|
406
|
-
</p>
|
|
407
|
-
<p className="text-2xl font-bold mt-0.5">8.4%</p>
|
|
408
|
-
</div>
|
|
409
|
-
<span className="inline-flex items-center gap-1 text-xs font-medium text-red-600 bg-red-50 dark:bg-red-950 dark:text-red-400 px-2 py-0.5 rounded-full">
|
|
410
|
-
<TrendingDown className="size-3" />
|
|
411
|
-
-3%
|
|
412
|
-
</span>
|
|
413
|
-
</div>
|
|
414
|
-
<SparklineChart
|
|
415
|
-
data={sparkDataDown}
|
|
416
|
-
dataKey="v"
|
|
417
|
-
color="var(--chart-5)"
|
|
418
|
-
filled
|
|
419
|
-
showEndDot
|
|
420
|
-
className="h-12"
|
|
421
|
-
/>
|
|
422
|
-
</Card>
|
|
423
|
-
|
|
424
|
-
<Card className="p-4">
|
|
425
|
-
<div className="flex items-start justify-between mb-3">
|
|
426
|
-
<div>
|
|
427
|
-
<p className="text-xs text-muted-foreground font-medium uppercase tracking-wide">
|
|
428
|
-
Pipeline
|
|
429
|
-
</p>
|
|
430
|
-
<p className="text-2xl font-bold mt-0.5">$128K</p>
|
|
431
|
-
</div>
|
|
432
|
-
<span className="inline-flex items-center gap-1 text-xs font-medium text-muted-foreground bg-muted px-2 py-0.5 rounded-full">
|
|
433
|
-
<Minus className="size-3" />
|
|
434
|
-
0%
|
|
435
|
-
</span>
|
|
436
|
-
</div>
|
|
437
|
-
<SparklineChart
|
|
438
|
-
data={[
|
|
439
|
-
{ v: 20 },
|
|
440
|
-
{ v: 22 },
|
|
441
|
-
{ v: 19 },
|
|
442
|
-
{ v: 23 },
|
|
443
|
-
{ v: 21 },
|
|
444
|
-
{ v: 24 },
|
|
445
|
-
{ v: 22 },
|
|
446
|
-
{ v: 25 },
|
|
447
|
-
{ v: 23 },
|
|
448
|
-
{ v: 24 },
|
|
449
|
-
]}
|
|
450
|
-
dataKey="v"
|
|
451
|
-
color="var(--chart-4)"
|
|
452
|
-
filled
|
|
453
|
-
showEndDot
|
|
454
|
-
className="h-12"
|
|
455
|
-
/>
|
|
456
|
-
</Card>
|
|
457
|
-
</div>
|
|
458
|
-
|
|
459
|
-
{/* Sparkline variants */}
|
|
460
|
-
<ChartCard title="Sparkline Variants" description="Line-only vs filled area">
|
|
461
|
-
<div className="space-y-4 py-2">
|
|
462
|
-
<div className="flex items-center gap-4">
|
|
463
|
-
<span className="text-xs text-muted-foreground w-24 shrink-0">Filled (default)</span>
|
|
464
|
-
<SparklineChart
|
|
465
|
-
data={sparkData}
|
|
466
|
-
dataKey="v"
|
|
467
|
-
color="var(--chart-1)"
|
|
468
|
-
filled
|
|
469
|
-
className="h-10 flex-1"
|
|
470
|
-
/>
|
|
471
|
-
</div>
|
|
472
|
-
<div className="flex items-center gap-4">
|
|
473
|
-
<span className="text-xs text-muted-foreground w-24 shrink-0">Line only</span>
|
|
474
|
-
<SparklineChart
|
|
475
|
-
data={sparkData}
|
|
476
|
-
dataKey="v"
|
|
477
|
-
color="var(--chart-3)"
|
|
478
|
-
filled={false}
|
|
479
|
-
showEndDot={false}
|
|
480
|
-
className="h-10 flex-1"
|
|
481
|
-
/>
|
|
482
|
-
</div>
|
|
483
|
-
<div className="flex items-center gap-4">
|
|
484
|
-
<span className="text-xs text-muted-foreground w-24 shrink-0">Step curve</span>
|
|
485
|
-
<SparklineChart
|
|
486
|
-
data={sparkData}
|
|
487
|
-
dataKey="v"
|
|
488
|
-
color="var(--chart-6)"
|
|
489
|
-
filled
|
|
490
|
-
curveType="step"
|
|
491
|
-
className="h-10 flex-1"
|
|
492
|
-
/>
|
|
493
|
-
</div>
|
|
494
|
-
</div>
|
|
495
|
-
</ChartCard>
|
|
496
|
-
</div>
|
|
497
|
-
),
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
// ─── Dashboard layout story ───────────────────────────────────────────────────
|
|
501
|
-
|
|
502
|
-
export const DashboardLayoutExample: Story = {
|
|
503
|
-
name: 'Dashboard Layout',
|
|
504
|
-
render: () => {
|
|
505
|
-
const kpiData = [
|
|
506
|
-
{
|
|
507
|
-
label: 'Total Revenue',
|
|
508
|
-
value: '$128.4K',
|
|
509
|
-
trend: '+18%',
|
|
510
|
-
up: true,
|
|
511
|
-
sparkData: sparkData,
|
|
512
|
-
color: 'var(--chart-1)',
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
label: 'Active Pipeline',
|
|
516
|
-
value: '$62.1K',
|
|
517
|
-
trend: '+9%',
|
|
518
|
-
up: true,
|
|
519
|
-
sparkData: sparkData.map(d => ({ v: d.v * 0.7 })),
|
|
520
|
-
color: 'var(--chart-4)',
|
|
521
|
-
},
|
|
522
|
-
{
|
|
523
|
-
label: 'Conversion Rate',
|
|
524
|
-
value: '58%',
|
|
525
|
-
trend: '+4%',
|
|
526
|
-
up: true,
|
|
527
|
-
sparkData: sparkData.map(d => ({ v: d.v * 0.5 })),
|
|
528
|
-
color: 'var(--chart-2)',
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
label: 'Churn Rate',
|
|
532
|
-
value: '3.2%',
|
|
533
|
-
trend: '-1%',
|
|
534
|
-
up: false,
|
|
535
|
-
sparkData: sparkDataDown,
|
|
536
|
-
color: 'var(--chart-5)',
|
|
537
|
-
},
|
|
538
|
-
];
|
|
539
|
-
|
|
540
|
-
return (
|
|
541
|
-
<div className="space-y-6">
|
|
542
|
-
{/* KPI row */}
|
|
543
|
-
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
|
544
|
-
{kpiData.map(kpi => (
|
|
545
|
-
<Card key={kpi.label} className="p-4">
|
|
546
|
-
<div className="flex items-start justify-between mb-3">
|
|
547
|
-
<div>
|
|
548
|
-
<p className="text-xs text-muted-foreground font-medium">{kpi.label}</p>
|
|
549
|
-
<p className="text-xl font-bold mt-0.5">{kpi.value}</p>
|
|
550
|
-
</div>
|
|
551
|
-
<span
|
|
552
|
-
className={`inline-flex items-center gap-1 text-xs font-medium px-2 py-0.5 rounded-full ${
|
|
553
|
-
kpi.up
|
|
554
|
-
? 'text-emerald-600 bg-emerald-50 dark:bg-emerald-950 dark:text-emerald-400'
|
|
555
|
-
: 'text-red-600 bg-red-50 dark:bg-red-950 dark:text-red-400'
|
|
556
|
-
}`}
|
|
557
|
-
>
|
|
558
|
-
{kpi.up ? <TrendingUp className="size-3" /> : <TrendingDown className="size-3" />}
|
|
559
|
-
{kpi.trend}
|
|
560
|
-
</span>
|
|
561
|
-
</div>
|
|
562
|
-
<SparklineChart
|
|
563
|
-
data={kpi.sparkData}
|
|
564
|
-
dataKey="v"
|
|
565
|
-
color={kpi.color}
|
|
566
|
-
filled
|
|
567
|
-
showEndDot
|
|
568
|
-
className="h-10"
|
|
569
|
-
/>
|
|
570
|
-
</Card>
|
|
571
|
-
))}
|
|
572
|
-
</div>
|
|
573
|
-
|
|
574
|
-
{/* Main charts row */}
|
|
575
|
-
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
|
|
576
|
-
<div className="lg:col-span-2">
|
|
577
|
-
<ChartCard title="Revenue & Pipeline" description="Weekly performance overview">
|
|
578
|
-
<InteractiveTimeSeriesChart
|
|
579
|
-
data={richData}
|
|
580
|
-
indexKey="date"
|
|
581
|
-
config={richChartConfig}
|
|
582
|
-
colors={['var(--chart-1)', 'var(--chart-4)', 'var(--chart-2)']}
|
|
583
|
-
series={[
|
|
584
|
-
{ key: 'revenue', label: 'Revenue' },
|
|
585
|
-
{ key: 'pipeline', label: 'Pipeline' },
|
|
586
|
-
{ key: 'conversion', label: 'Conversion' },
|
|
587
|
-
]}
|
|
588
|
-
gradientFill
|
|
589
|
-
periods={[
|
|
590
|
-
{ value: '7d', label: '7 days' },
|
|
591
|
-
{ value: '30d', label: '30 days' },
|
|
592
|
-
]}
|
|
593
|
-
/>
|
|
594
|
-
</ChartCard>
|
|
595
|
-
</div>
|
|
596
|
-
|
|
597
|
-
<ChartCard title="Customer Mix" description="Segment breakdown">
|
|
598
|
-
<DonutBreakdownChart
|
|
599
|
-
data={breakdownData}
|
|
600
|
-
config={breakdownConfig}
|
|
601
|
-
colors={['var(--chart-1)', 'var(--chart-4)', 'var(--chart-2)']}
|
|
602
|
-
centerValue="100%"
|
|
603
|
-
centerLabel="Accounts"
|
|
604
|
-
/>
|
|
605
|
-
</ChartCard>
|
|
606
|
-
</div>
|
|
607
|
-
|
|
608
|
-
{/* Bottom row */}
|
|
609
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
610
|
-
<ChartCard title="Top Segments" description="Revenue by customer segment">
|
|
611
|
-
<HorizontalBarChart
|
|
612
|
-
data={[
|
|
613
|
-
{ segment: 'Enterprise', revenue: 7600 },
|
|
614
|
-
{ segment: 'Mid-market', revenue: 5400 },
|
|
615
|
-
{ segment: 'Startup', revenue: 3100 },
|
|
616
|
-
{ segment: 'Partners', revenue: 2200 },
|
|
617
|
-
]}
|
|
618
|
-
indexKey="segment"
|
|
619
|
-
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
|
|
620
|
-
colors={{ revenue: 'var(--chart-1)' }}
|
|
621
|
-
barSize="xl"
|
|
622
|
-
categoryWidth={110}
|
|
623
|
-
showLegend={false}
|
|
624
|
-
/>
|
|
625
|
-
</ChartCard>
|
|
626
|
-
|
|
627
|
-
<ChartCard title="Pipeline Health" description="Volume vs conversion rate">
|
|
628
|
-
<ComboMetricChart
|
|
629
|
-
data={richData}
|
|
630
|
-
indexKey="date"
|
|
631
|
-
config={richChartConfig}
|
|
632
|
-
colors={{
|
|
633
|
-
pipeline: 'var(--chart-4)',
|
|
634
|
-
conversion: 'var(--chart-2)',
|
|
635
|
-
}}
|
|
636
|
-
barSize="lg"
|
|
637
|
-
series={[
|
|
638
|
-
{ key: 'pipeline', type: 'bar' },
|
|
639
|
-
{ key: 'conversion', type: 'line' },
|
|
640
|
-
]}
|
|
641
|
-
/>
|
|
642
|
-
</ChartCard>
|
|
643
|
-
</div>
|
|
644
|
-
</div>
|
|
645
|
-
);
|
|
646
|
-
},
|
|
647
|
-
};
|
|
648
|
-
|
|
649
|
-
// ─── State stories ────────────────────────────────────────────────────────────
|
|
650
|
-
|
|
651
|
-
export const EmptyStateExample: Story = {
|
|
652
|
-
name: 'State / Empty',
|
|
653
|
-
render: () => (
|
|
654
|
-
<ChartCard
|
|
655
|
-
title="Revenue by Week"
|
|
656
|
-
description="The empty state is rendered by the chart wrapper"
|
|
657
|
-
>
|
|
658
|
-
<DashboardBarChart
|
|
659
|
-
data={[]}
|
|
660
|
-
indexKey="date"
|
|
661
|
-
config={richChartConfig}
|
|
662
|
-
emptyDescription="No revenue events were found for the selected period."
|
|
663
|
-
/>
|
|
664
|
-
</ChartCard>
|
|
665
|
-
),
|
|
666
|
-
};
|
|
667
|
-
|
|
668
|
-
export const ConnectionErrorExample: Story = {
|
|
669
|
-
name: 'State / Connection Error',
|
|
670
|
-
render: () => (
|
|
671
|
-
<ChartCard title="Pipeline Health" description="Connection errors stay inside the chart panel">
|
|
672
|
-
<ComboMetricChart
|
|
673
|
-
data={richData}
|
|
674
|
-
indexKey="date"
|
|
675
|
-
config={richChartConfig}
|
|
676
|
-
error="Unable to connect to the analytics service."
|
|
677
|
-
onRetry={() => undefined}
|
|
678
|
-
/>
|
|
679
|
-
</ChartCard>
|
|
680
|
-
),
|
|
681
|
-
};
|
|
682
|
-
|
|
683
|
-
export const LoadingStateExample: Story = {
|
|
684
|
-
name: 'State / Loading',
|
|
685
|
-
render: () => (
|
|
686
|
-
<ChartCard title="Revenue by Week" description="Loading skeleton while data is fetched">
|
|
687
|
-
<DashboardBarChart data={[]} indexKey="date" config={richChartConfig} isLoading />
|
|
688
|
-
</ChartCard>
|
|
689
|
-
),
|
|
690
|
-
};
|
|
691
|
-
|
|
692
|
-
// ─── Variant stories ──────────────────────────────────────────────────────────
|
|
693
|
-
|
|
694
|
-
export const BarSizeVariantsExample: Story = {
|
|
695
|
-
name: 'Variants / Bar Sizes',
|
|
696
|
-
render: () => (
|
|
697
|
-
<div className="space-y-6">
|
|
698
|
-
<ChartCard title="Thin Bars" description='barSize="sm"'>
|
|
699
|
-
<DashboardBarChart
|
|
700
|
-
data={richData}
|
|
701
|
-
indexKey="date"
|
|
702
|
-
config={richChartConfig}
|
|
703
|
-
series={[{ key: 'revenue' }]}
|
|
704
|
-
barSize="sm"
|
|
705
|
-
showLegend={false}
|
|
706
|
-
/>
|
|
707
|
-
</ChartCard>
|
|
708
|
-
<ChartCard title="Wide Bars" description='barSize="xl"'>
|
|
709
|
-
<DashboardBarChart
|
|
710
|
-
data={richData}
|
|
711
|
-
indexKey="date"
|
|
712
|
-
config={richChartConfig}
|
|
713
|
-
series={[{ key: 'revenue' }]}
|
|
714
|
-
barSize="xl"
|
|
715
|
-
showLegend={false}
|
|
716
|
-
/>
|
|
717
|
-
</ChartCard>
|
|
718
|
-
</div>
|
|
719
|
-
),
|
|
720
|
-
};
|
|
721
|
-
|
|
722
|
-
export const CurveTypeVariantsExample: Story = {
|
|
723
|
-
name: 'Variants / Curve Types',
|
|
724
|
-
render: () => (
|
|
725
|
-
<div className="space-y-6">
|
|
726
|
-
{(['monotone', 'linear', 'step', 'natural', 'basis'] as const).map(curve => (
|
|
727
|
-
<ChartCard
|
|
728
|
-
key={curve}
|
|
729
|
-
title={`curveType="${curve}"`}
|
|
730
|
-
description="Line chart curve interpolation"
|
|
731
|
-
>
|
|
732
|
-
<DashboardLineChart
|
|
733
|
-
data={richData}
|
|
734
|
-
indexKey="date"
|
|
735
|
-
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
|
|
736
|
-
series={[{ key: 'revenue' }]}
|
|
737
|
-
curveType={curve}
|
|
738
|
-
showLegend={false}
|
|
739
|
-
showDots={curve === 'linear'}
|
|
740
|
-
/>
|
|
741
|
-
</ChartCard>
|
|
742
|
-
))}
|
|
743
|
-
</div>
|
|
744
|
-
),
|
|
745
|
-
};
|
|
746
|
-
|
|
747
|
-
export const ColorPaletteExample: Story = {
|
|
748
|
-
name: 'Variants / Color Palette',
|
|
749
|
-
render: () => {
|
|
750
|
-
const paletteConfig: ChartConfig = {
|
|
751
|
-
chart1: { label: 'chart-1 (indigo)', color: 'var(--chart-1)' },
|
|
752
|
-
chart2: { label: 'chart-2 (emerald)', color: 'var(--chart-2)' },
|
|
753
|
-
chart3: { label: 'chart-3 (amber)', color: 'var(--chart-3)' },
|
|
754
|
-
chart4: { label: 'chart-4 (blue)', color: 'var(--chart-4)' },
|
|
755
|
-
chart5: { label: 'chart-5 (red)', color: 'var(--chart-5)' },
|
|
756
|
-
chart6: { label: 'chart-6 (purple)', color: 'var(--chart-6)' },
|
|
757
|
-
chart7: { label: 'chart-7 (teal)', color: 'var(--chart-7)' },
|
|
758
|
-
chart8: { label: 'chart-8 (rose)', color: 'var(--chart-8)' },
|
|
759
|
-
};
|
|
760
|
-
|
|
761
|
-
const paletteData = [
|
|
762
|
-
{
|
|
763
|
-
name: 'A',
|
|
764
|
-
chart1: 80,
|
|
765
|
-
chart2: 70,
|
|
766
|
-
chart3: 60,
|
|
767
|
-
chart4: 75,
|
|
768
|
-
chart5: 55,
|
|
769
|
-
chart6: 65,
|
|
770
|
-
chart7: 72,
|
|
771
|
-
chart8: 68,
|
|
772
|
-
},
|
|
773
|
-
];
|
|
774
|
-
|
|
775
|
-
return (
|
|
776
|
-
<ChartCard
|
|
777
|
-
title="Chart Color Palette"
|
|
778
|
-
description="All 8 chart tokens — vibrant, accessible, harmonious"
|
|
779
|
-
>
|
|
780
|
-
<DashboardBarChart
|
|
781
|
-
data={paletteData}
|
|
782
|
-
indexKey="name"
|
|
783
|
-
config={paletteConfig}
|
|
784
|
-
barSize="xl"
|
|
785
|
-
showGrid={false}
|
|
786
|
-
/>
|
|
787
|
-
</ChartCard>
|
|
788
|
-
);
|
|
789
|
-
},
|
|
790
|
-
};
|
|
791
|
-
|
|
792
|
-
// ─── Radar Chart Stories ───────────────────────────────────────────────────────
|
|
793
|
-
|
|
794
|
-
const radarData = [
|
|
795
|
-
{ skill: 'Performance', score: 88 },
|
|
796
|
-
{ skill: 'Reliability', score: 72 },
|
|
797
|
-
{ skill: 'Security', score: 95 },
|
|
798
|
-
{ skill: 'Scalability', score: 65 },
|
|
799
|
-
{ skill: 'Usability', score: 80 },
|
|
800
|
-
{ skill: 'Maintainability', score: 58 },
|
|
801
|
-
];
|
|
802
|
-
|
|
803
|
-
const radarMultiData = [
|
|
804
|
-
{ skill: 'Performance', teamA: 88, teamB: 62 },
|
|
805
|
-
{ skill: 'Reliability', teamA: 72, teamB: 85 },
|
|
806
|
-
{ skill: 'Security', teamA: 95, teamB: 70 },
|
|
807
|
-
{ skill: 'Scalability', teamA: 65, teamB: 90 },
|
|
808
|
-
{ skill: 'Usability', teamA: 80, teamB: 55 },
|
|
809
|
-
{ skill: 'Maintainability', teamA: 58, teamB: 78 },
|
|
810
|
-
];
|
|
811
|
-
|
|
812
|
-
export const RadarChartFilled: Story = {
|
|
813
|
-
name: 'Radar Chart / Filled',
|
|
814
|
-
render: () => (
|
|
815
|
-
<ChartCard title="System Health Score" description="Filled radar — single series">
|
|
816
|
-
<RadarMetricChart
|
|
817
|
-
data={radarData}
|
|
818
|
-
labelKey="skill"
|
|
819
|
-
series={[{ key: 'score', label: 'Score' }]}
|
|
820
|
-
filled
|
|
821
|
-
showLegend={false}
|
|
822
|
-
/>
|
|
823
|
-
</ChartCard>
|
|
824
|
-
),
|
|
825
|
-
};
|
|
826
|
-
|
|
827
|
-
export const RadarChartOutline: Story = {
|
|
828
|
-
name: 'Radar Chart / Outline',
|
|
829
|
-
render: () => (
|
|
830
|
-
<ChartCard title="System Health Score" description="Outline only — no fill">
|
|
831
|
-
<RadarMetricChart
|
|
832
|
-
data={radarData}
|
|
833
|
-
labelKey="skill"
|
|
834
|
-
series={[{ key: 'score', label: 'Score' }]}
|
|
835
|
-
filled={false}
|
|
836
|
-
showDots
|
|
837
|
-
showLegend={false}
|
|
838
|
-
/>
|
|
839
|
-
</ChartCard>
|
|
840
|
-
),
|
|
841
|
-
};
|
|
842
|
-
|
|
843
|
-
export const RadarChartMultiSeries: Story = {
|
|
844
|
-
name: 'Radar Chart / Multi-Series',
|
|
845
|
-
render: () => (
|
|
846
|
-
<ChartCard title="Team Comparison" description="Two teams across 6 dimensions">
|
|
847
|
-
<RadarMetricChart
|
|
848
|
-
data={radarMultiData}
|
|
849
|
-
labelKey="skill"
|
|
850
|
-
series={[
|
|
851
|
-
{ key: 'teamA', label: 'Team Alpha' },
|
|
852
|
-
{ key: 'teamB', label: 'Team Beta' },
|
|
853
|
-
]}
|
|
854
|
-
filled
|
|
855
|
-
fillOpacity={0.2}
|
|
856
|
-
showDots
|
|
857
|
-
/>
|
|
858
|
-
</ChartCard>
|
|
859
|
-
),
|
|
860
|
-
};
|
|
861
|
-
|
|
862
|
-
export const RadarChartVariants: Story = {
|
|
863
|
-
name: 'Radar Chart / All Variants',
|
|
864
|
-
render: () => (
|
|
865
|
-
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
866
|
-
<ChartCard title="Filled" description="Default filled area">
|
|
867
|
-
<RadarMetricChart
|
|
868
|
-
data={radarData}
|
|
869
|
-
labelKey="skill"
|
|
870
|
-
series={[{ key: 'score', label: 'Score' }]}
|
|
871
|
-
filled
|
|
872
|
-
showLegend={false}
|
|
873
|
-
/>
|
|
874
|
-
</ChartCard>
|
|
875
|
-
<ChartCard title="Outline + Dots" description="No fill, with dots">
|
|
876
|
-
<RadarMetricChart
|
|
877
|
-
data={radarData}
|
|
878
|
-
labelKey="skill"
|
|
879
|
-
series={[{ key: 'score', label: 'Score' }]}
|
|
880
|
-
filled={false}
|
|
881
|
-
showDots
|
|
882
|
-
showLegend={false}
|
|
883
|
-
/>
|
|
884
|
-
</ChartCard>
|
|
885
|
-
<ChartCard title="Multi-Series" description="Comparison overlay">
|
|
886
|
-
<RadarMetricChart
|
|
887
|
-
data={radarMultiData}
|
|
888
|
-
labelKey="skill"
|
|
889
|
-
series={[
|
|
890
|
-
{ key: 'teamA', label: 'Team A' },
|
|
891
|
-
{ key: 'teamB', label: 'Team B' },
|
|
892
|
-
]}
|
|
893
|
-
filled
|
|
894
|
-
fillOpacity={0.18}
|
|
895
|
-
/>
|
|
896
|
-
</ChartCard>
|
|
897
|
-
</div>
|
|
898
|
-
),
|
|
899
|
-
};
|
|
900
|
-
|
|
901
|
-
// ─── Pie Chart Stories ────────────────────────────────────────────────────────
|
|
902
|
-
|
|
903
|
-
const pieData = [
|
|
904
|
-
{ category: 'Infrastructure', spend: 42000 },
|
|
905
|
-
{ category: 'Engineering', spend: 31000 },
|
|
906
|
-
{ category: 'Marketing', spend: 18500 },
|
|
907
|
-
{ category: 'Operations', spend: 12000 },
|
|
908
|
-
{ category: 'Other', spend: 6500 },
|
|
909
|
-
];
|
|
910
|
-
|
|
911
|
-
export const PieChartSimple: Story = {
|
|
912
|
-
name: 'Pie Chart / Simple',
|
|
913
|
-
render: () => (
|
|
914
|
-
<ChartCard title="Budget Breakdown" description="Simple pie — no labels">
|
|
915
|
-
<PieMetricChart
|
|
916
|
-
data={pieData}
|
|
917
|
-
nameKey="category"
|
|
918
|
-
valueKey="spend"
|
|
919
|
-
valueFormatter={v => `$${(v as number).toLocaleString()}`}
|
|
920
|
-
/>
|
|
921
|
-
</ChartCard>
|
|
922
|
-
),
|
|
923
|
-
};
|
|
924
|
-
|
|
925
|
-
export const PieChartWithLabels: Story = {
|
|
926
|
-
name: 'Pie Chart / With Labels',
|
|
927
|
-
render: () => (
|
|
928
|
-
<ChartCard title="Budget Breakdown" description="Pie with percentage labels">
|
|
929
|
-
<PieMetricChart
|
|
930
|
-
data={pieData}
|
|
931
|
-
nameKey="category"
|
|
932
|
-
valueKey="spend"
|
|
933
|
-
showLabels
|
|
934
|
-
valueFormatter={v => `$${(v as number).toLocaleString()}`}
|
|
935
|
-
/>
|
|
936
|
-
</ChartCard>
|
|
937
|
-
),
|
|
938
|
-
};
|
|
939
|
-
|
|
940
|
-
export const PieChartExploded: Story = {
|
|
941
|
-
name: 'Pie Chart / Exploded Slice',
|
|
942
|
-
render: () => (
|
|
943
|
-
<ChartCard title="Budget Breakdown" description="Largest slice highlighted with drop shadow">
|
|
944
|
-
<PieMetricChart
|
|
945
|
-
data={pieData}
|
|
946
|
-
nameKey="category"
|
|
947
|
-
valueKey="spend"
|
|
948
|
-
showLabels
|
|
949
|
-
explodeIndex={0}
|
|
950
|
-
valueFormatter={v => `$${(v as number).toLocaleString()}`}
|
|
951
|
-
/>
|
|
952
|
-
</ChartCard>
|
|
953
|
-
),
|
|
954
|
-
};
|
|
955
|
-
|
|
956
|
-
export const PieChartDonutVariant: Story = {
|
|
957
|
-
name: 'Pie Chart / Donut Variant',
|
|
958
|
-
render: () => (
|
|
959
|
-
<ChartCard title="Budget Breakdown" description="Pie with inner radius (donut style)">
|
|
960
|
-
<PieMetricChart
|
|
961
|
-
data={pieData}
|
|
962
|
-
nameKey="category"
|
|
963
|
-
valueKey="spend"
|
|
964
|
-
innerRadius="45%"
|
|
965
|
-
showLabels
|
|
966
|
-
valueFormatter={v => `$${(v as number).toLocaleString()}`}
|
|
967
|
-
/>
|
|
968
|
-
</ChartCard>
|
|
969
|
-
),
|
|
970
|
-
};
|
|
971
|
-
|
|
972
|
-
export const PieChartVariants: Story = {
|
|
973
|
-
name: 'Pie Chart / All Variants',
|
|
974
|
-
render: () => (
|
|
975
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
976
|
-
<ChartCard title="Simple" description="No labels">
|
|
977
|
-
<PieMetricChart data={pieData} nameKey="category" valueKey="spend" />
|
|
978
|
-
</ChartCard>
|
|
979
|
-
<ChartCard title="With Labels" description="Percentage labels">
|
|
980
|
-
<PieMetricChart data={pieData} nameKey="category" valueKey="spend" showLabels />
|
|
981
|
-
</ChartCard>
|
|
982
|
-
<ChartCard title="Exploded" description="First slice highlighted">
|
|
983
|
-
<PieMetricChart
|
|
984
|
-
data={pieData}
|
|
985
|
-
nameKey="category"
|
|
986
|
-
valueKey="spend"
|
|
987
|
-
showLabels
|
|
988
|
-
explodeIndex={0}
|
|
989
|
-
/>
|
|
990
|
-
</ChartCard>
|
|
991
|
-
<ChartCard title="Donut" description="Inner radius 45%">
|
|
992
|
-
<PieMetricChart
|
|
993
|
-
data={pieData}
|
|
994
|
-
nameKey="category"
|
|
995
|
-
valueKey="spend"
|
|
996
|
-
innerRadius="45%"
|
|
997
|
-
showLabels
|
|
998
|
-
/>
|
|
999
|
-
</ChartCard>
|
|
1000
|
-
</div>
|
|
1001
|
-
),
|
|
1002
|
-
};
|
|
1003
|
-
|
|
1004
|
-
// ─── Radial Bar Chart Stories ─────────────────────────────────────────────────
|
|
1005
|
-
|
|
1006
|
-
const radialData = [
|
|
1007
|
-
{ name: 'Infrastructure', value: 78 },
|
|
1008
|
-
{ name: 'Engineering', value: 62 },
|
|
1009
|
-
{ name: 'Marketing', value: 45 },
|
|
1010
|
-
{ name: 'Operations', value: 91 },
|
|
1011
|
-
];
|
|
1012
|
-
|
|
1013
|
-
export const RadialBarChartSingle: Story = {
|
|
1014
|
-
name: 'Radial Bar / Single Bar',
|
|
1015
|
-
render: () => (
|
|
1016
|
-
<ChartCard title="Deployment Success Rate" description="Single radial bar — full circle">
|
|
1017
|
-
<RadialBarMetricChart
|
|
1018
|
-
data={[{ name: 'Success Rate', value: 87 }]}
|
|
1019
|
-
dataKey="value"
|
|
1020
|
-
nameKey="name"
|
|
1021
|
-
showLegend={false}
|
|
1022
|
-
innerRadius="60%"
|
|
1023
|
-
outerRadius="90%"
|
|
1024
|
-
valueFormatter={v => `${v}%`}
|
|
1025
|
-
/>
|
|
1026
|
-
</ChartCard>
|
|
1027
|
-
),
|
|
1028
|
-
};
|
|
1029
|
-
|
|
1030
|
-
export const RadialBarChartMulti: Story = {
|
|
1031
|
-
name: 'Radial Bar / Multi-Bar',
|
|
1032
|
-
render: () => (
|
|
1033
|
-
<ChartCard title="Department KPIs" description="Multiple radial bars with background track">
|
|
1034
|
-
<RadialBarMetricChart
|
|
1035
|
-
data={radialData}
|
|
1036
|
-
dataKey="value"
|
|
1037
|
-
nameKey="name"
|
|
1038
|
-
innerRadius="20%"
|
|
1039
|
-
outerRadius="90%"
|
|
1040
|
-
valueFormatter={v => `${v}%`}
|
|
1041
|
-
/>
|
|
1042
|
-
</ChartCard>
|
|
1043
|
-
),
|
|
1044
|
-
};
|
|
1045
|
-
|
|
1046
|
-
export const RadialBarChartSemiCircle: Story = {
|
|
1047
|
-
name: 'Radial Bar / Semi-Circle',
|
|
1048
|
-
render: () => (
|
|
1049
|
-
<ChartCard
|
|
1050
|
-
title="Department KPIs"
|
|
1051
|
-
description="Semi-circle layout (startAngle=180, endAngle=0)"
|
|
1052
|
-
>
|
|
1053
|
-
<RadialBarMetricChart
|
|
1054
|
-
data={radialData}
|
|
1055
|
-
dataKey="value"
|
|
1056
|
-
nameKey="name"
|
|
1057
|
-
innerRadius="30%"
|
|
1058
|
-
outerRadius="90%"
|
|
1059
|
-
startAngle={180}
|
|
1060
|
-
endAngle={0}
|
|
1061
|
-
valueFormatter={v => `${v}%`}
|
|
1062
|
-
/>
|
|
1063
|
-
</ChartCard>
|
|
1064
|
-
),
|
|
1065
|
-
};
|
|
1066
|
-
|
|
1067
|
-
export const RadialBarChartVariants: Story = {
|
|
1068
|
-
name: 'Radial Bar / All Variants',
|
|
1069
|
-
render: () => (
|
|
1070
|
-
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
1071
|
-
<ChartCard title="Single Bar" description="Full circle">
|
|
1072
|
-
<RadialBarMetricChart
|
|
1073
|
-
data={[{ name: 'Success', value: 87 }]}
|
|
1074
|
-
dataKey="value"
|
|
1075
|
-
nameKey="name"
|
|
1076
|
-
showLegend={false}
|
|
1077
|
-
innerRadius="60%"
|
|
1078
|
-
outerRadius="90%"
|
|
1079
|
-
valueFormatter={v => `${v}%`}
|
|
1080
|
-
/>
|
|
1081
|
-
</ChartCard>
|
|
1082
|
-
<ChartCard title="Multi-Bar" description="Stacked radial bars">
|
|
1083
|
-
<RadialBarMetricChart
|
|
1084
|
-
data={radialData}
|
|
1085
|
-
dataKey="value"
|
|
1086
|
-
nameKey="name"
|
|
1087
|
-
innerRadius="20%"
|
|
1088
|
-
outerRadius="90%"
|
|
1089
|
-
valueFormatter={v => `${v}%`}
|
|
1090
|
-
/>
|
|
1091
|
-
</ChartCard>
|
|
1092
|
-
<ChartCard title="Semi-Circle" description="180° arc layout">
|
|
1093
|
-
<RadialBarMetricChart
|
|
1094
|
-
data={radialData}
|
|
1095
|
-
dataKey="value"
|
|
1096
|
-
nameKey="name"
|
|
1097
|
-
innerRadius="30%"
|
|
1098
|
-
outerRadius="90%"
|
|
1099
|
-
startAngle={180}
|
|
1100
|
-
endAngle={0}
|
|
1101
|
-
valueFormatter={v => `${v}%`}
|
|
1102
|
-
/>
|
|
1103
|
-
</ChartCard>
|
|
1104
|
-
</div>
|
|
1105
|
-
),
|
|
1106
|
-
};
|
|
1107
|
-
|
|
1108
|
-
// ─── Gauge Chart Stories ──────────────────────────────────────────────────────
|
|
1109
|
-
|
|
1110
|
-
const gaugeThresholds: GaugeChartThreshold[] = [
|
|
1111
|
-
{ value: 33, color: 'var(--chart-5)', label: 'Critical' },
|
|
1112
|
-
{ value: 66, color: 'var(--chart-3)', label: 'Warning' },
|
|
1113
|
-
{ value: 100, color: 'var(--chart-2)', label: 'Healthy' },
|
|
1114
|
-
];
|
|
1115
|
-
|
|
1116
|
-
export const GaugeChartSimple: Story = {
|
|
1117
|
-
name: 'Gauge Chart / Simple',
|
|
1118
|
-
render: () => (
|
|
1119
|
-
<ChartCard
|
|
1120
|
-
title="CPU Usage"
|
|
1121
|
-
description="Simple gauge — single color"
|
|
1122
|
-
className="max-w-sm mx-auto"
|
|
1123
|
-
>
|
|
1124
|
-
<div className="flex justify-center py-4">
|
|
1125
|
-
<GaugeChart value={67} label="CPU Usage" />
|
|
1126
|
-
</div>
|
|
1127
|
-
</ChartCard>
|
|
1128
|
-
),
|
|
1129
|
-
};
|
|
1130
|
-
|
|
1131
|
-
export const GaugeChartWithThresholds: Story = {
|
|
1132
|
-
name: 'Gauge Chart / With Thresholds',
|
|
1133
|
-
render: () => (
|
|
1134
|
-
<ChartCard
|
|
1135
|
-
title="System Health"
|
|
1136
|
-
description="Color zones: critical / warning / healthy"
|
|
1137
|
-
className="max-w-sm mx-auto"
|
|
1138
|
-
>
|
|
1139
|
-
<div className="flex justify-center py-4">
|
|
1140
|
-
<GaugeChart value={72} label="Overall Health" thresholds={gaugeThresholds} />
|
|
1141
|
-
</div>
|
|
1142
|
-
</ChartCard>
|
|
1143
|
-
),
|
|
1144
|
-
};
|
|
1145
|
-
|
|
1146
|
-
export const GaugeChartNoNeedle: Story = {
|
|
1147
|
-
name: 'Gauge Chart / No Needle',
|
|
1148
|
-
render: () => (
|
|
1149
|
-
<ChartCard
|
|
1150
|
-
title="Memory Usage"
|
|
1151
|
-
description="Arc only — no needle indicator"
|
|
1152
|
-
className="max-w-sm mx-auto"
|
|
1153
|
-
>
|
|
1154
|
-
<div className="flex justify-center py-4">
|
|
1155
|
-
<GaugeChart value={45} label="Memory" showNeedle={false} thresholds={gaugeThresholds} />
|
|
1156
|
-
</div>
|
|
1157
|
-
</ChartCard>
|
|
1158
|
-
),
|
|
1159
|
-
};
|
|
1160
|
-
|
|
1161
|
-
export const GaugeChartVariants: Story = {
|
|
1162
|
-
name: 'Gauge Chart / All Variants',
|
|
1163
|
-
render: () => (
|
|
1164
|
-
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
1165
|
-
<ChartCard title="Low (22%)" description="Critical zone">
|
|
1166
|
-
<div className="flex justify-center py-2">
|
|
1167
|
-
<GaugeChart value={22} label="CPU" thresholds={gaugeThresholds} />
|
|
1168
|
-
</div>
|
|
1169
|
-
</ChartCard>
|
|
1170
|
-
<ChartCard title="Medium (55%)" description="Warning zone">
|
|
1171
|
-
<div className="flex justify-center py-2">
|
|
1172
|
-
<GaugeChart value={55} label="Memory" thresholds={gaugeThresholds} />
|
|
1173
|
-
</div>
|
|
1174
|
-
</ChartCard>
|
|
1175
|
-
<ChartCard title="High (88%)" description="Healthy zone">
|
|
1176
|
-
<div className="flex justify-center py-2">
|
|
1177
|
-
<GaugeChart value={88} label="Disk I/O" thresholds={gaugeThresholds} />
|
|
1178
|
-
</div>
|
|
1179
|
-
</ChartCard>
|
|
1180
|
-
</div>
|
|
1181
|
-
),
|
|
1182
|
-
};
|
|
1183
|
-
|
|
1184
|
-
export const GaugeChartDashboard: Story = {
|
|
1185
|
-
name: 'Gauge Chart / Infrastructure Dashboard',
|
|
1186
|
-
render: () => {
|
|
1187
|
-
const metrics = [
|
|
1188
|
-
{ label: 'CPU', value: 34, unit: '%' },
|
|
1189
|
-
{ label: 'Memory', value: 71, unit: '%' },
|
|
1190
|
-
{ label: 'Disk', value: 58, unit: '%' },
|
|
1191
|
-
{ label: 'Network', value: 22, unit: '%' },
|
|
1192
|
-
];
|
|
1193
|
-
|
|
1194
|
-
return (
|
|
1195
|
-
<div className="space-y-4">
|
|
1196
|
-
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
1197
|
-
{metrics.map(m => (
|
|
1198
|
-
<ChartCard key={m.label} title={m.label} description={`Current ${m.label} utilization`}>
|
|
1199
|
-
<div className="flex justify-center py-2">
|
|
1200
|
-
<GaugeChart
|
|
1201
|
-
value={m.value}
|
|
1202
|
-
label={m.label}
|
|
1203
|
-
thresholds={gaugeThresholds}
|
|
1204
|
-
valueFormatter={v => `${v}${m.unit}`}
|
|
1205
|
-
/>
|
|
1206
|
-
</div>
|
|
1207
|
-
</ChartCard>
|
|
1208
|
-
))}
|
|
1209
|
-
</div>
|
|
1210
|
-
</div>
|
|
1211
|
-
);
|
|
1212
|
-
},
|
|
1213
|
-
};
|
|
1214
|
-
|
|
1215
|
-
// ─── Complete Chart Library Overview ─────────────────────────────────────────
|
|
1216
|
-
|
|
1217
|
-
export const CompleteLibraryOverview: Story = {
|
|
1218
|
-
name: 'Complete Library / All Chart Types',
|
|
1219
|
-
render: () => (
|
|
1220
|
-
<div className="space-y-6">
|
|
1221
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
1222
|
-
{/* Bar */}
|
|
1223
|
-
<ChartCard title="Bar Chart" description="Categorical comparison">
|
|
1224
|
-
<DashboardBarChart
|
|
1225
|
-
data={[
|
|
1226
|
-
{ month: 'Jan', revenue: 42000 },
|
|
1227
|
-
{ month: 'Feb', revenue: 38000 },
|
|
1228
|
-
{ month: 'Mar', revenue: 51000 },
|
|
1229
|
-
{ month: 'Apr', revenue: 47000 },
|
|
1230
|
-
{ month: 'May', revenue: 55000 },
|
|
1231
|
-
]}
|
|
1232
|
-
indexKey="month"
|
|
1233
|
-
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
|
|
1234
|
-
series={[{ key: 'revenue', label: 'Revenue' }]}
|
|
1235
|
-
showLegend={false}
|
|
1236
|
-
/>
|
|
1237
|
-
</ChartCard>
|
|
1238
|
-
|
|
1239
|
-
{/* Line */}
|
|
1240
|
-
<ChartCard title="Line Chart" description="Trend over time">
|
|
1241
|
-
<DashboardLineChart
|
|
1242
|
-
data={[
|
|
1243
|
-
{ month: 'Jan', users: 1200 },
|
|
1244
|
-
{ month: 'Feb', users: 1450 },
|
|
1245
|
-
{ month: 'Mar', users: 1380 },
|
|
1246
|
-
{ month: 'Apr', users: 1620 },
|
|
1247
|
-
{ month: 'May', users: 1890 },
|
|
1248
|
-
]}
|
|
1249
|
-
indexKey="month"
|
|
1250
|
-
config={{ users: { label: 'Users', color: 'var(--chart-2)' } }}
|
|
1251
|
-
series={[{ key: 'users', label: 'Users' }]}
|
|
1252
|
-
showLegend={false}
|
|
1253
|
-
/>
|
|
1254
|
-
</ChartCard>
|
|
1255
|
-
|
|
1256
|
-
{/* Donut */}
|
|
1257
|
-
<ChartCard title="Donut Chart" description="Part-to-whole">
|
|
1258
|
-
<DonutBreakdownChart
|
|
1259
|
-
data={[
|
|
1260
|
-
{ name: 'Active', value: 68 },
|
|
1261
|
-
{ name: 'Idle', value: 22 },
|
|
1262
|
-
{ name: 'Offline', value: 10 },
|
|
1263
|
-
]}
|
|
1264
|
-
nameKey="name"
|
|
1265
|
-
valueKey="value"
|
|
1266
|
-
config={{
|
|
1267
|
-
Active: { label: 'Active', color: 'var(--chart-2)' },
|
|
1268
|
-
Idle: { label: 'Idle', color: 'var(--chart-3)' },
|
|
1269
|
-
Offline: { label: 'Offline', color: 'var(--chart-5)' },
|
|
1270
|
-
}}
|
|
1271
|
-
centerValue="68%"
|
|
1272
|
-
centerLabel="Active"
|
|
1273
|
-
showLegend={false}
|
|
1274
|
-
/>
|
|
1275
|
-
</ChartCard>
|
|
1276
|
-
|
|
1277
|
-
{/* Radar */}
|
|
1278
|
-
<ChartCard title="Radar Chart" description="Multi-dimensional">
|
|
1279
|
-
<RadarMetricChart
|
|
1280
|
-
data={radarData}
|
|
1281
|
-
labelKey="skill"
|
|
1282
|
-
series={[{ key: 'score', label: 'Score' }]}
|
|
1283
|
-
filled
|
|
1284
|
-
showLegend={false}
|
|
1285
|
-
/>
|
|
1286
|
-
</ChartCard>
|
|
1287
|
-
|
|
1288
|
-
{/* Pie */}
|
|
1289
|
-
<ChartCard title="Pie Chart" description="Proportional slices">
|
|
1290
|
-
<PieMetricChart
|
|
1291
|
-
data={pieData}
|
|
1292
|
-
nameKey="category"
|
|
1293
|
-
valueKey="spend"
|
|
1294
|
-
showLabels
|
|
1295
|
-
showLegend={false}
|
|
1296
|
-
/>
|
|
1297
|
-
</ChartCard>
|
|
1298
|
-
|
|
1299
|
-
{/* Radial Bar */}
|
|
1300
|
-
<ChartCard title="Radial Bar" description="Progress rings">
|
|
1301
|
-
<RadialBarMetricChart
|
|
1302
|
-
data={radialData}
|
|
1303
|
-
dataKey="value"
|
|
1304
|
-
nameKey="name"
|
|
1305
|
-
innerRadius="20%"
|
|
1306
|
-
outerRadius="90%"
|
|
1307
|
-
valueFormatter={v => `${v}%`}
|
|
1308
|
-
/>
|
|
1309
|
-
</ChartCard>
|
|
1310
|
-
</div>
|
|
1311
|
-
|
|
1312
|
-
{/* Gauge row */}
|
|
1313
|
-
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
1314
|
-
{[
|
|
1315
|
-
{ label: 'CPU', value: 34 },
|
|
1316
|
-
{ label: 'Memory', value: 71 },
|
|
1317
|
-
{ label: 'Disk', value: 58 },
|
|
1318
|
-
].map(m => (
|
|
1319
|
-
<ChartCard key={m.label} title={`Gauge — ${m.label}`} description="Semicircle gauge">
|
|
1320
|
-
<div className="flex justify-center py-2">
|
|
1321
|
-
<GaugeChart value={m.value} label={m.label} thresholds={gaugeThresholds} />
|
|
1322
|
-
</div>
|
|
1323
|
-
</ChartCard>
|
|
1324
|
-
))}
|
|
1325
|
-
</div>
|
|
1326
|
-
</div>
|
|
1327
|
-
),
|
|
1328
|
-
};
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import {
|
|
3
|
+
ChartContainer,
|
|
4
|
+
ChartTooltip,
|
|
5
|
+
ChartTooltipContent,
|
|
6
|
+
ChartLegend,
|
|
7
|
+
ChartLegendContent,
|
|
8
|
+
ChartCard,
|
|
9
|
+
DashboardBarChart,
|
|
10
|
+
DashboardLineChart,
|
|
11
|
+
HorizontalBarChart,
|
|
12
|
+
InteractiveTimeSeriesChart,
|
|
13
|
+
ComboMetricChart,
|
|
14
|
+
DonutBreakdownChart,
|
|
15
|
+
SparklineChart,
|
|
16
|
+
RadarMetricChart,
|
|
17
|
+
PieMetricChart,
|
|
18
|
+
RadialBarMetricChart,
|
|
19
|
+
GaugeChart,
|
|
20
|
+
type ChartConfig,
|
|
21
|
+
type GaugeChartThreshold,
|
|
22
|
+
} from './chart';
|
|
23
|
+
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, LineChart, Line } from 'recharts';
|
|
24
|
+
import { Card, CardHeader, CardTitle, CardContent } from '../card';
|
|
25
|
+
import React from 'react';
|
|
26
|
+
import { TrendingUp, TrendingDown, Minus } from 'lucide-react';
|
|
27
|
+
|
|
28
|
+
const meta: Meta<typeof DashboardBarChart> = {
|
|
29
|
+
title: 'UI/Chart',
|
|
30
|
+
component: DashboardBarChart,
|
|
31
|
+
render: args => <DashboardBarChart {...args} />,
|
|
32
|
+
parameters: {
|
|
33
|
+
layout: 'fullscreen',
|
|
34
|
+
},
|
|
35
|
+
decorators: [
|
|
36
|
+
Story => (
|
|
37
|
+
<div className="w-full min-w-0 p-8">
|
|
38
|
+
<Story />
|
|
39
|
+
</div>
|
|
40
|
+
),
|
|
41
|
+
],
|
|
42
|
+
argTypes: {
|
|
43
|
+
barSize: {
|
|
44
|
+
control: 'select',
|
|
45
|
+
options: ['sm', 'md', 'lg', 'xl'],
|
|
46
|
+
description: 'Controls only the bar thickness.',
|
|
47
|
+
},
|
|
48
|
+
stacked: { control: 'boolean' },
|
|
49
|
+
showGrid: { control: 'boolean' },
|
|
50
|
+
showLegend: { control: 'boolean' },
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default meta;
|
|
55
|
+
type Story = StoryObj<typeof DashboardBarChart>;
|
|
56
|
+
|
|
57
|
+
// ─── Shared data ──────────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
const data = [
|
|
60
|
+
{ month: 'Jan', revenue: 4000, expenses: 2400 },
|
|
61
|
+
{ month: 'Feb', revenue: 3000, expenses: 1398 },
|
|
62
|
+
{ month: 'Mar', revenue: 6000, expenses: 3200 },
|
|
63
|
+
{ month: 'Apr', revenue: 2780, expenses: 3908 },
|
|
64
|
+
{ month: 'May', revenue: 1890, expenses: 4800 },
|
|
65
|
+
{ month: 'Jun', revenue: 2390, expenses: 3800 },
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
const chartConfig: ChartConfig = {
|
|
69
|
+
revenue: { label: 'Revenue', color: 'var(--chart-1)' },
|
|
70
|
+
expenses: { label: 'Expenses', color: 'var(--chart-5)' },
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const richChartConfig: ChartConfig = {
|
|
74
|
+
revenue: { label: 'Revenue', color: 'var(--chart-1)' },
|
|
75
|
+
pipeline: { label: 'Pipeline', color: 'var(--chart-4)' },
|
|
76
|
+
conversion: { label: 'Conversion', color: 'var(--chart-2)' },
|
|
77
|
+
churn: { label: 'Churn', color: 'var(--chart-5)' },
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const richData = [
|
|
81
|
+
{ date: 'Apr 01', revenue: 4200, pipeline: 2600, conversion: 32, churn: 8 },
|
|
82
|
+
{ date: 'Apr 08', revenue: 5200, pipeline: 3200, conversion: 38, churn: 7 },
|
|
83
|
+
{ date: 'Apr 15', revenue: 6100, pipeline: 3900, conversion: 42, churn: 6 },
|
|
84
|
+
{ date: 'Apr 22', revenue: 5600, pipeline: 4300, conversion: 41, churn: 9 },
|
|
85
|
+
{ date: 'Apr 29', revenue: 7200, pipeline: 4700, conversion: 48, churn: 5 },
|
|
86
|
+
{ date: 'May 06', revenue: 7900, pipeline: 5300, conversion: 52, churn: 4 },
|
|
87
|
+
{ date: 'May 13', revenue: 8400, pipeline: 5800, conversion: 55, churn: 3 },
|
|
88
|
+
{ date: 'May 20', revenue: 9100, pipeline: 6200, conversion: 58, churn: 4 },
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
const breakdownConfig: ChartConfig = {
|
|
92
|
+
enterprise: { label: 'Enterprise', color: 'var(--chart-1)' },
|
|
93
|
+
midmarket: { label: 'Mid-market', color: 'var(--chart-4)' },
|
|
94
|
+
startup: { label: 'Startup', color: 'var(--chart-2)' },
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const breakdownData = [
|
|
98
|
+
{ name: 'enterprise', value: 52 },
|
|
99
|
+
{ name: 'midmarket', value: 31 },
|
|
100
|
+
{ name: 'startup', value: 17 },
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
// ─── Primitive stories ────────────────────────────────────────────────────────
|
|
104
|
+
|
|
105
|
+
export const BarChartExample: Story = {
|
|
106
|
+
name: 'Primitive / Bar Chart',
|
|
107
|
+
render: () => (
|
|
108
|
+
<Card className="w-full max-w-4xl">
|
|
109
|
+
<CardHeader>
|
|
110
|
+
<CardTitle>Monthly Performance</CardTitle>
|
|
111
|
+
</CardHeader>
|
|
112
|
+
<CardContent>
|
|
113
|
+
<ChartContainer config={chartConfig} className="h-[300px] w-full">
|
|
114
|
+
<BarChart data={data}>
|
|
115
|
+
<CartesianGrid vertical={false} strokeDasharray="3 3" />
|
|
116
|
+
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
|
117
|
+
<ChartTooltip content={<ChartTooltipContent />} />
|
|
118
|
+
<ChartLegend content={<ChartLegendContent />} />
|
|
119
|
+
<Bar dataKey="revenue" fill="var(--color-revenue)" radius={[4, 4, 0, 0]} />
|
|
120
|
+
<Bar dataKey="expenses" fill="var(--color-expenses)" radius={[4, 4, 0, 0]} />
|
|
121
|
+
</BarChart>
|
|
122
|
+
</ChartContainer>
|
|
123
|
+
</CardContent>
|
|
124
|
+
</Card>
|
|
125
|
+
),
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const LineChartExample: Story = {
|
|
129
|
+
name: 'Primitive / Line Chart',
|
|
130
|
+
render: () => (
|
|
131
|
+
<Card className="w-full max-w-4xl">
|
|
132
|
+
<CardHeader>
|
|
133
|
+
<CardTitle>Revenue Trends</CardTitle>
|
|
134
|
+
</CardHeader>
|
|
135
|
+
<CardContent>
|
|
136
|
+
<ChartContainer config={chartConfig} className="h-[300px] w-full">
|
|
137
|
+
<LineChart data={data}>
|
|
138
|
+
<CartesianGrid vertical={false} strokeDasharray="3 3" />
|
|
139
|
+
<XAxis dataKey="month" tickLine={false} axisLine={false} />
|
|
140
|
+
<ChartTooltip content={<ChartTooltipContent />} />
|
|
141
|
+
<Line
|
|
142
|
+
type="monotone"
|
|
143
|
+
dataKey="revenue"
|
|
144
|
+
stroke="var(--color-revenue)"
|
|
145
|
+
strokeWidth={3}
|
|
146
|
+
dot={{ r: 4, fill: 'var(--color-revenue)', strokeWidth: 0 }}
|
|
147
|
+
activeDot={{ r: 6, strokeWidth: 0 }}
|
|
148
|
+
/>
|
|
149
|
+
</LineChart>
|
|
150
|
+
</ChartContainer>
|
|
151
|
+
</CardContent>
|
|
152
|
+
</Card>
|
|
153
|
+
),
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// ─── Dashboard chart stories ──────────────────────────────────────────────────
|
|
157
|
+
|
|
158
|
+
export const DashboardBarChartExample: Story = {
|
|
159
|
+
name: 'Bar Chart',
|
|
160
|
+
args: {
|
|
161
|
+
data: richData,
|
|
162
|
+
indexKey: 'date',
|
|
163
|
+
config: richChartConfig,
|
|
164
|
+
colors: {
|
|
165
|
+
revenue: 'var(--chart-1)',
|
|
166
|
+
pipeline: 'var(--chart-4)',
|
|
167
|
+
},
|
|
168
|
+
barSize: 'lg',
|
|
169
|
+
series: [
|
|
170
|
+
{ key: 'revenue', stackId: 'money' },
|
|
171
|
+
{ key: 'pipeline', stackId: 'money' },
|
|
172
|
+
],
|
|
173
|
+
stacked: true,
|
|
174
|
+
},
|
|
175
|
+
render: args => (
|
|
176
|
+
<ChartCard title="Revenue by Week" description="Stacked dashboard-ready comparison">
|
|
177
|
+
<DashboardBarChart {...args} />
|
|
178
|
+
</ChartCard>
|
|
179
|
+
),
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export const DashboardLineChartExample: Story = {
|
|
183
|
+
name: 'Line Chart',
|
|
184
|
+
render: () => (
|
|
185
|
+
<ChartCard title="Growth Trend" description="Multi-series line chart with smooth curves">
|
|
186
|
+
<DashboardLineChart
|
|
187
|
+
data={richData}
|
|
188
|
+
indexKey="date"
|
|
189
|
+
config={richChartConfig}
|
|
190
|
+
colors={{
|
|
191
|
+
revenue: 'var(--chart-1)',
|
|
192
|
+
pipeline: 'var(--chart-4)',
|
|
193
|
+
conversion: 'var(--chart-2)',
|
|
194
|
+
}}
|
|
195
|
+
series={[
|
|
196
|
+
{ key: 'revenue', label: 'Revenue' },
|
|
197
|
+
{ key: 'pipeline', label: 'Pipeline' },
|
|
198
|
+
{ key: 'conversion', label: 'Conversion' },
|
|
199
|
+
]}
|
|
200
|
+
showDots
|
|
201
|
+
curveType="monotone"
|
|
202
|
+
strokeWidth={2.5}
|
|
203
|
+
/>
|
|
204
|
+
</ChartCard>
|
|
205
|
+
),
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export const HorizontalBarChartExample: Story = {
|
|
209
|
+
name: 'Horizontal Bar Chart',
|
|
210
|
+
render: () => (
|
|
211
|
+
<ChartCard title="Top Segments" description="Ranking chart for dashboard comparisons">
|
|
212
|
+
<HorizontalBarChart
|
|
213
|
+
data={[
|
|
214
|
+
{ segment: 'Enterprise', revenue: 7600 },
|
|
215
|
+
{ segment: 'Mid-market', revenue: 5400 },
|
|
216
|
+
{ segment: 'Startup', revenue: 3100 },
|
|
217
|
+
{ segment: 'Partners', revenue: 2200 },
|
|
218
|
+
]}
|
|
219
|
+
indexKey="segment"
|
|
220
|
+
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
|
|
221
|
+
colors={{ revenue: 'var(--chart-1)' }}
|
|
222
|
+
barSize="xl"
|
|
223
|
+
categoryWidth={110}
|
|
224
|
+
showLegend={false}
|
|
225
|
+
/>
|
|
226
|
+
</ChartCard>
|
|
227
|
+
),
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
export const InteractiveTimeSeriesExample: Story = {
|
|
231
|
+
name: 'Interactive Time Series',
|
|
232
|
+
render: () => (
|
|
233
|
+
<ChartCard
|
|
234
|
+
title="Executive Trend"
|
|
235
|
+
description="Switch metric and period without leaving the card"
|
|
236
|
+
>
|
|
237
|
+
<InteractiveTimeSeriesChart
|
|
238
|
+
data={richData}
|
|
239
|
+
indexKey="date"
|
|
240
|
+
config={richChartConfig}
|
|
241
|
+
colors={['var(--chart-1)', 'var(--chart-4)', 'var(--chart-2)']}
|
|
242
|
+
series={[
|
|
243
|
+
{ key: 'revenue', label: 'Revenue' },
|
|
244
|
+
{ key: 'pipeline', label: 'Pipeline' },
|
|
245
|
+
{ key: 'conversion', label: 'Conversion' },
|
|
246
|
+
]}
|
|
247
|
+
gradientFill
|
|
248
|
+
/>
|
|
249
|
+
</ChartCard>
|
|
250
|
+
),
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
export const GradientAreaChartExample: Story = {
|
|
254
|
+
name: 'Gradient Area Chart',
|
|
255
|
+
render: () => (
|
|
256
|
+
<ChartCard
|
|
257
|
+
title="Revenue Over Time"
|
|
258
|
+
description="Area chart with gradient fill for a modern look"
|
|
259
|
+
>
|
|
260
|
+
<InteractiveTimeSeriesChart
|
|
261
|
+
data={richData}
|
|
262
|
+
indexKey="date"
|
|
263
|
+
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
|
|
264
|
+
colors={['var(--chart-1)']}
|
|
265
|
+
series={[{ key: 'revenue', label: 'Revenue' }]}
|
|
266
|
+
gradientFill
|
|
267
|
+
showDots
|
|
268
|
+
periods={[
|
|
269
|
+
{ value: '7d', label: '7 days' },
|
|
270
|
+
{ value: '30d', label: '30 days' },
|
|
271
|
+
]}
|
|
272
|
+
/>
|
|
273
|
+
</ChartCard>
|
|
274
|
+
),
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
export const ComboMetricChartExample: Story = {
|
|
278
|
+
name: 'Combo Metric Chart',
|
|
279
|
+
render: () => (
|
|
280
|
+
<ChartCard title="Pipeline Health" description="Bars for volume with a line for rate">
|
|
281
|
+
<ComboMetricChart
|
|
282
|
+
data={richData}
|
|
283
|
+
indexKey="date"
|
|
284
|
+
config={richChartConfig}
|
|
285
|
+
colors={{
|
|
286
|
+
pipeline: 'var(--chart-4)',
|
|
287
|
+
conversion: 'var(--chart-2)',
|
|
288
|
+
}}
|
|
289
|
+
barSize="lg"
|
|
290
|
+
series={[
|
|
291
|
+
{ key: 'pipeline', type: 'bar' },
|
|
292
|
+
{ key: 'conversion', type: 'line' },
|
|
293
|
+
]}
|
|
294
|
+
/>
|
|
295
|
+
</ChartCard>
|
|
296
|
+
),
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
export const ComboWithGradientAreaExample: Story = {
|
|
300
|
+
name: 'Combo Chart with Gradient Area',
|
|
301
|
+
render: () => (
|
|
302
|
+
<ChartCard
|
|
303
|
+
title="Revenue & Pipeline"
|
|
304
|
+
description="Gradient area for revenue, line for conversion rate"
|
|
305
|
+
>
|
|
306
|
+
<ComboMetricChart
|
|
307
|
+
data={richData}
|
|
308
|
+
indexKey="date"
|
|
309
|
+
config={richChartConfig}
|
|
310
|
+
colors={{
|
|
311
|
+
revenue: 'var(--chart-1)',
|
|
312
|
+
conversion: 'var(--chart-2)',
|
|
313
|
+
}}
|
|
314
|
+
series={[
|
|
315
|
+
{ key: 'revenue', type: 'area' },
|
|
316
|
+
{ key: 'conversion', type: 'line' },
|
|
317
|
+
]}
|
|
318
|
+
gradientFill
|
|
319
|
+
curveType="monotone"
|
|
320
|
+
/>
|
|
321
|
+
</ChartCard>
|
|
322
|
+
),
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
export const DonutBreakdownExample: Story = {
|
|
326
|
+
name: 'Donut Chart',
|
|
327
|
+
render: () => (
|
|
328
|
+
<ChartCard title="Customer Mix" description="Interactive segment breakdown">
|
|
329
|
+
<DonutBreakdownChart
|
|
330
|
+
data={breakdownData}
|
|
331
|
+
config={breakdownConfig}
|
|
332
|
+
colors={['var(--chart-1)', 'var(--chart-4)', 'var(--chart-2)']}
|
|
333
|
+
centerValue="100%"
|
|
334
|
+
centerLabel="Accounts"
|
|
335
|
+
/>
|
|
336
|
+
</ChartCard>
|
|
337
|
+
),
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
// ─── Sparkline stories ────────────────────────────────────────────────────────
|
|
341
|
+
|
|
342
|
+
const sparkData = [
|
|
343
|
+
{ v: 12 },
|
|
344
|
+
{ v: 18 },
|
|
345
|
+
{ v: 14 },
|
|
346
|
+
{ v: 22 },
|
|
347
|
+
{ v: 19 },
|
|
348
|
+
{ v: 28 },
|
|
349
|
+
{ v: 24 },
|
|
350
|
+
{ v: 31 },
|
|
351
|
+
{ v: 27 },
|
|
352
|
+
{ v: 35 },
|
|
353
|
+
];
|
|
354
|
+
|
|
355
|
+
const sparkDataDown = [
|
|
356
|
+
{ v: 35 },
|
|
357
|
+
{ v: 30 },
|
|
358
|
+
{ v: 28 },
|
|
359
|
+
{ v: 22 },
|
|
360
|
+
{ v: 25 },
|
|
361
|
+
{ v: 18 },
|
|
362
|
+
{ v: 20 },
|
|
363
|
+
{ v: 14 },
|
|
364
|
+
{ v: 12 },
|
|
365
|
+
{ v: 8 },
|
|
366
|
+
];
|
|
367
|
+
|
|
368
|
+
export const SparklineExample: Story = {
|
|
369
|
+
name: 'Sparkline Chart',
|
|
370
|
+
render: () => (
|
|
371
|
+
<div className="space-y-6 max-w-2xl">
|
|
372
|
+
<p className="text-sm text-muted-foreground">
|
|
373
|
+
Sparklines are minimal inline charts designed for stat cards and table cells.
|
|
374
|
+
</p>
|
|
375
|
+
|
|
376
|
+
{/* Stat cards with sparklines */}
|
|
377
|
+
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
|
378
|
+
<Card className="p-4">
|
|
379
|
+
<div className="flex items-start justify-between mb-3">
|
|
380
|
+
<div>
|
|
381
|
+
<p className="text-xs text-muted-foreground font-medium uppercase tracking-wide">
|
|
382
|
+
Revenue
|
|
383
|
+
</p>
|
|
384
|
+
<p className="text-2xl font-bold mt-0.5">$35.2K</p>
|
|
385
|
+
</div>
|
|
386
|
+
<span className="inline-flex items-center gap-1 text-xs font-medium text-emerald-600 bg-emerald-50 dark:bg-emerald-950 dark:text-emerald-400 px-2 py-0.5 rounded-full">
|
|
387
|
+
<TrendingUp className="size-3" />
|
|
388
|
+
+12%
|
|
389
|
+
</span>
|
|
390
|
+
</div>
|
|
391
|
+
<SparklineChart
|
|
392
|
+
data={sparkData}
|
|
393
|
+
dataKey="v"
|
|
394
|
+
color="var(--chart-2)"
|
|
395
|
+
filled
|
|
396
|
+
showEndDot
|
|
397
|
+
className="h-12"
|
|
398
|
+
/>
|
|
399
|
+
</Card>
|
|
400
|
+
|
|
401
|
+
<Card className="p-4">
|
|
402
|
+
<div className="flex items-start justify-between mb-3">
|
|
403
|
+
<div>
|
|
404
|
+
<p className="text-xs text-muted-foreground font-medium uppercase tracking-wide">
|
|
405
|
+
Churn
|
|
406
|
+
</p>
|
|
407
|
+
<p className="text-2xl font-bold mt-0.5">8.4%</p>
|
|
408
|
+
</div>
|
|
409
|
+
<span className="inline-flex items-center gap-1 text-xs font-medium text-red-600 bg-red-50 dark:bg-red-950 dark:text-red-400 px-2 py-0.5 rounded-full">
|
|
410
|
+
<TrendingDown className="size-3" />
|
|
411
|
+
-3%
|
|
412
|
+
</span>
|
|
413
|
+
</div>
|
|
414
|
+
<SparklineChart
|
|
415
|
+
data={sparkDataDown}
|
|
416
|
+
dataKey="v"
|
|
417
|
+
color="var(--chart-5)"
|
|
418
|
+
filled
|
|
419
|
+
showEndDot
|
|
420
|
+
className="h-12"
|
|
421
|
+
/>
|
|
422
|
+
</Card>
|
|
423
|
+
|
|
424
|
+
<Card className="p-4">
|
|
425
|
+
<div className="flex items-start justify-between mb-3">
|
|
426
|
+
<div>
|
|
427
|
+
<p className="text-xs text-muted-foreground font-medium uppercase tracking-wide">
|
|
428
|
+
Pipeline
|
|
429
|
+
</p>
|
|
430
|
+
<p className="text-2xl font-bold mt-0.5">$128K</p>
|
|
431
|
+
</div>
|
|
432
|
+
<span className="inline-flex items-center gap-1 text-xs font-medium text-muted-foreground bg-muted px-2 py-0.5 rounded-full">
|
|
433
|
+
<Minus className="size-3" />
|
|
434
|
+
0%
|
|
435
|
+
</span>
|
|
436
|
+
</div>
|
|
437
|
+
<SparklineChart
|
|
438
|
+
data={[
|
|
439
|
+
{ v: 20 },
|
|
440
|
+
{ v: 22 },
|
|
441
|
+
{ v: 19 },
|
|
442
|
+
{ v: 23 },
|
|
443
|
+
{ v: 21 },
|
|
444
|
+
{ v: 24 },
|
|
445
|
+
{ v: 22 },
|
|
446
|
+
{ v: 25 },
|
|
447
|
+
{ v: 23 },
|
|
448
|
+
{ v: 24 },
|
|
449
|
+
]}
|
|
450
|
+
dataKey="v"
|
|
451
|
+
color="var(--chart-4)"
|
|
452
|
+
filled
|
|
453
|
+
showEndDot
|
|
454
|
+
className="h-12"
|
|
455
|
+
/>
|
|
456
|
+
</Card>
|
|
457
|
+
</div>
|
|
458
|
+
|
|
459
|
+
{/* Sparkline variants */}
|
|
460
|
+
<ChartCard title="Sparkline Variants" description="Line-only vs filled area">
|
|
461
|
+
<div className="space-y-4 py-2">
|
|
462
|
+
<div className="flex items-center gap-4">
|
|
463
|
+
<span className="text-xs text-muted-foreground w-24 shrink-0">Filled (default)</span>
|
|
464
|
+
<SparklineChart
|
|
465
|
+
data={sparkData}
|
|
466
|
+
dataKey="v"
|
|
467
|
+
color="var(--chart-1)"
|
|
468
|
+
filled
|
|
469
|
+
className="h-10 flex-1"
|
|
470
|
+
/>
|
|
471
|
+
</div>
|
|
472
|
+
<div className="flex items-center gap-4">
|
|
473
|
+
<span className="text-xs text-muted-foreground w-24 shrink-0">Line only</span>
|
|
474
|
+
<SparklineChart
|
|
475
|
+
data={sparkData}
|
|
476
|
+
dataKey="v"
|
|
477
|
+
color="var(--chart-3)"
|
|
478
|
+
filled={false}
|
|
479
|
+
showEndDot={false}
|
|
480
|
+
className="h-10 flex-1"
|
|
481
|
+
/>
|
|
482
|
+
</div>
|
|
483
|
+
<div className="flex items-center gap-4">
|
|
484
|
+
<span className="text-xs text-muted-foreground w-24 shrink-0">Step curve</span>
|
|
485
|
+
<SparklineChart
|
|
486
|
+
data={sparkData}
|
|
487
|
+
dataKey="v"
|
|
488
|
+
color="var(--chart-6)"
|
|
489
|
+
filled
|
|
490
|
+
curveType="step"
|
|
491
|
+
className="h-10 flex-1"
|
|
492
|
+
/>
|
|
493
|
+
</div>
|
|
494
|
+
</div>
|
|
495
|
+
</ChartCard>
|
|
496
|
+
</div>
|
|
497
|
+
),
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// ─── Dashboard layout story ───────────────────────────────────────────────────
|
|
501
|
+
|
|
502
|
+
export const DashboardLayoutExample: Story = {
|
|
503
|
+
name: 'Dashboard Layout',
|
|
504
|
+
render: () => {
|
|
505
|
+
const kpiData = [
|
|
506
|
+
{
|
|
507
|
+
label: 'Total Revenue',
|
|
508
|
+
value: '$128.4K',
|
|
509
|
+
trend: '+18%',
|
|
510
|
+
up: true,
|
|
511
|
+
sparkData: sparkData,
|
|
512
|
+
color: 'var(--chart-1)',
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
label: 'Active Pipeline',
|
|
516
|
+
value: '$62.1K',
|
|
517
|
+
trend: '+9%',
|
|
518
|
+
up: true,
|
|
519
|
+
sparkData: sparkData.map(d => ({ v: d.v * 0.7 })),
|
|
520
|
+
color: 'var(--chart-4)',
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
label: 'Conversion Rate',
|
|
524
|
+
value: '58%',
|
|
525
|
+
trend: '+4%',
|
|
526
|
+
up: true,
|
|
527
|
+
sparkData: sparkData.map(d => ({ v: d.v * 0.5 })),
|
|
528
|
+
color: 'var(--chart-2)',
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
label: 'Churn Rate',
|
|
532
|
+
value: '3.2%',
|
|
533
|
+
trend: '-1%',
|
|
534
|
+
up: false,
|
|
535
|
+
sparkData: sparkDataDown,
|
|
536
|
+
color: 'var(--chart-5)',
|
|
537
|
+
},
|
|
538
|
+
];
|
|
539
|
+
|
|
540
|
+
return (
|
|
541
|
+
<div className="space-y-6">
|
|
542
|
+
{/* KPI row */}
|
|
543
|
+
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
|
544
|
+
{kpiData.map(kpi => (
|
|
545
|
+
<Card key={kpi.label} className="p-4">
|
|
546
|
+
<div className="flex items-start justify-between mb-3">
|
|
547
|
+
<div>
|
|
548
|
+
<p className="text-xs text-muted-foreground font-medium">{kpi.label}</p>
|
|
549
|
+
<p className="text-xl font-bold mt-0.5">{kpi.value}</p>
|
|
550
|
+
</div>
|
|
551
|
+
<span
|
|
552
|
+
className={`inline-flex items-center gap-1 text-xs font-medium px-2 py-0.5 rounded-full ${
|
|
553
|
+
kpi.up
|
|
554
|
+
? 'text-emerald-600 bg-emerald-50 dark:bg-emerald-950 dark:text-emerald-400'
|
|
555
|
+
: 'text-red-600 bg-red-50 dark:bg-red-950 dark:text-red-400'
|
|
556
|
+
}`}
|
|
557
|
+
>
|
|
558
|
+
{kpi.up ? <TrendingUp className="size-3" /> : <TrendingDown className="size-3" />}
|
|
559
|
+
{kpi.trend}
|
|
560
|
+
</span>
|
|
561
|
+
</div>
|
|
562
|
+
<SparklineChart
|
|
563
|
+
data={kpi.sparkData}
|
|
564
|
+
dataKey="v"
|
|
565
|
+
color={kpi.color}
|
|
566
|
+
filled
|
|
567
|
+
showEndDot
|
|
568
|
+
className="h-10"
|
|
569
|
+
/>
|
|
570
|
+
</Card>
|
|
571
|
+
))}
|
|
572
|
+
</div>
|
|
573
|
+
|
|
574
|
+
{/* Main charts row */}
|
|
575
|
+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
|
|
576
|
+
<div className="lg:col-span-2">
|
|
577
|
+
<ChartCard title="Revenue & Pipeline" description="Weekly performance overview">
|
|
578
|
+
<InteractiveTimeSeriesChart
|
|
579
|
+
data={richData}
|
|
580
|
+
indexKey="date"
|
|
581
|
+
config={richChartConfig}
|
|
582
|
+
colors={['var(--chart-1)', 'var(--chart-4)', 'var(--chart-2)']}
|
|
583
|
+
series={[
|
|
584
|
+
{ key: 'revenue', label: 'Revenue' },
|
|
585
|
+
{ key: 'pipeline', label: 'Pipeline' },
|
|
586
|
+
{ key: 'conversion', label: 'Conversion' },
|
|
587
|
+
]}
|
|
588
|
+
gradientFill
|
|
589
|
+
periods={[
|
|
590
|
+
{ value: '7d', label: '7 days' },
|
|
591
|
+
{ value: '30d', label: '30 days' },
|
|
592
|
+
]}
|
|
593
|
+
/>
|
|
594
|
+
</ChartCard>
|
|
595
|
+
</div>
|
|
596
|
+
|
|
597
|
+
<ChartCard title="Customer Mix" description="Segment breakdown">
|
|
598
|
+
<DonutBreakdownChart
|
|
599
|
+
data={breakdownData}
|
|
600
|
+
config={breakdownConfig}
|
|
601
|
+
colors={['var(--chart-1)', 'var(--chart-4)', 'var(--chart-2)']}
|
|
602
|
+
centerValue="100%"
|
|
603
|
+
centerLabel="Accounts"
|
|
604
|
+
/>
|
|
605
|
+
</ChartCard>
|
|
606
|
+
</div>
|
|
607
|
+
|
|
608
|
+
{/* Bottom row */}
|
|
609
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
610
|
+
<ChartCard title="Top Segments" description="Revenue by customer segment">
|
|
611
|
+
<HorizontalBarChart
|
|
612
|
+
data={[
|
|
613
|
+
{ segment: 'Enterprise', revenue: 7600 },
|
|
614
|
+
{ segment: 'Mid-market', revenue: 5400 },
|
|
615
|
+
{ segment: 'Startup', revenue: 3100 },
|
|
616
|
+
{ segment: 'Partners', revenue: 2200 },
|
|
617
|
+
]}
|
|
618
|
+
indexKey="segment"
|
|
619
|
+
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
|
|
620
|
+
colors={{ revenue: 'var(--chart-1)' }}
|
|
621
|
+
barSize="xl"
|
|
622
|
+
categoryWidth={110}
|
|
623
|
+
showLegend={false}
|
|
624
|
+
/>
|
|
625
|
+
</ChartCard>
|
|
626
|
+
|
|
627
|
+
<ChartCard title="Pipeline Health" description="Volume vs conversion rate">
|
|
628
|
+
<ComboMetricChart
|
|
629
|
+
data={richData}
|
|
630
|
+
indexKey="date"
|
|
631
|
+
config={richChartConfig}
|
|
632
|
+
colors={{
|
|
633
|
+
pipeline: 'var(--chart-4)',
|
|
634
|
+
conversion: 'var(--chart-2)',
|
|
635
|
+
}}
|
|
636
|
+
barSize="lg"
|
|
637
|
+
series={[
|
|
638
|
+
{ key: 'pipeline', type: 'bar' },
|
|
639
|
+
{ key: 'conversion', type: 'line' },
|
|
640
|
+
]}
|
|
641
|
+
/>
|
|
642
|
+
</ChartCard>
|
|
643
|
+
</div>
|
|
644
|
+
</div>
|
|
645
|
+
);
|
|
646
|
+
},
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
// ─── State stories ────────────────────────────────────────────────────────────
|
|
650
|
+
|
|
651
|
+
export const EmptyStateExample: Story = {
|
|
652
|
+
name: 'State / Empty',
|
|
653
|
+
render: () => (
|
|
654
|
+
<ChartCard
|
|
655
|
+
title="Revenue by Week"
|
|
656
|
+
description="The empty state is rendered by the chart wrapper"
|
|
657
|
+
>
|
|
658
|
+
<DashboardBarChart
|
|
659
|
+
data={[]}
|
|
660
|
+
indexKey="date"
|
|
661
|
+
config={richChartConfig}
|
|
662
|
+
emptyDescription="No revenue events were found for the selected period."
|
|
663
|
+
/>
|
|
664
|
+
</ChartCard>
|
|
665
|
+
),
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
export const ConnectionErrorExample: Story = {
|
|
669
|
+
name: 'State / Connection Error',
|
|
670
|
+
render: () => (
|
|
671
|
+
<ChartCard title="Pipeline Health" description="Connection errors stay inside the chart panel">
|
|
672
|
+
<ComboMetricChart
|
|
673
|
+
data={richData}
|
|
674
|
+
indexKey="date"
|
|
675
|
+
config={richChartConfig}
|
|
676
|
+
error="Unable to connect to the analytics service."
|
|
677
|
+
onRetry={() => undefined}
|
|
678
|
+
/>
|
|
679
|
+
</ChartCard>
|
|
680
|
+
),
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
export const LoadingStateExample: Story = {
|
|
684
|
+
name: 'State / Loading',
|
|
685
|
+
render: () => (
|
|
686
|
+
<ChartCard title="Revenue by Week" description="Loading skeleton while data is fetched">
|
|
687
|
+
<DashboardBarChart data={[]} indexKey="date" config={richChartConfig} isLoading />
|
|
688
|
+
</ChartCard>
|
|
689
|
+
),
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
// ─── Variant stories ──────────────────────────────────────────────────────────
|
|
693
|
+
|
|
694
|
+
export const BarSizeVariantsExample: Story = {
|
|
695
|
+
name: 'Variants / Bar Sizes',
|
|
696
|
+
render: () => (
|
|
697
|
+
<div className="space-y-6">
|
|
698
|
+
<ChartCard title="Thin Bars" description='barSize="sm"'>
|
|
699
|
+
<DashboardBarChart
|
|
700
|
+
data={richData}
|
|
701
|
+
indexKey="date"
|
|
702
|
+
config={richChartConfig}
|
|
703
|
+
series={[{ key: 'revenue' }]}
|
|
704
|
+
barSize="sm"
|
|
705
|
+
showLegend={false}
|
|
706
|
+
/>
|
|
707
|
+
</ChartCard>
|
|
708
|
+
<ChartCard title="Wide Bars" description='barSize="xl"'>
|
|
709
|
+
<DashboardBarChart
|
|
710
|
+
data={richData}
|
|
711
|
+
indexKey="date"
|
|
712
|
+
config={richChartConfig}
|
|
713
|
+
series={[{ key: 'revenue' }]}
|
|
714
|
+
barSize="xl"
|
|
715
|
+
showLegend={false}
|
|
716
|
+
/>
|
|
717
|
+
</ChartCard>
|
|
718
|
+
</div>
|
|
719
|
+
),
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
export const CurveTypeVariantsExample: Story = {
|
|
723
|
+
name: 'Variants / Curve Types',
|
|
724
|
+
render: () => (
|
|
725
|
+
<div className="space-y-6">
|
|
726
|
+
{(['monotone', 'linear', 'step', 'natural', 'basis'] as const).map(curve => (
|
|
727
|
+
<ChartCard
|
|
728
|
+
key={curve}
|
|
729
|
+
title={`curveType="${curve}"`}
|
|
730
|
+
description="Line chart curve interpolation"
|
|
731
|
+
>
|
|
732
|
+
<DashboardLineChart
|
|
733
|
+
data={richData}
|
|
734
|
+
indexKey="date"
|
|
735
|
+
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
|
|
736
|
+
series={[{ key: 'revenue' }]}
|
|
737
|
+
curveType={curve}
|
|
738
|
+
showLegend={false}
|
|
739
|
+
showDots={curve === 'linear'}
|
|
740
|
+
/>
|
|
741
|
+
</ChartCard>
|
|
742
|
+
))}
|
|
743
|
+
</div>
|
|
744
|
+
),
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
export const ColorPaletteExample: Story = {
|
|
748
|
+
name: 'Variants / Color Palette',
|
|
749
|
+
render: () => {
|
|
750
|
+
const paletteConfig: ChartConfig = {
|
|
751
|
+
chart1: { label: 'chart-1 (indigo)', color: 'var(--chart-1)' },
|
|
752
|
+
chart2: { label: 'chart-2 (emerald)', color: 'var(--chart-2)' },
|
|
753
|
+
chart3: { label: 'chart-3 (amber)', color: 'var(--chart-3)' },
|
|
754
|
+
chart4: { label: 'chart-4 (blue)', color: 'var(--chart-4)' },
|
|
755
|
+
chart5: { label: 'chart-5 (red)', color: 'var(--chart-5)' },
|
|
756
|
+
chart6: { label: 'chart-6 (purple)', color: 'var(--chart-6)' },
|
|
757
|
+
chart7: { label: 'chart-7 (teal)', color: 'var(--chart-7)' },
|
|
758
|
+
chart8: { label: 'chart-8 (rose)', color: 'var(--chart-8)' },
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
const paletteData = [
|
|
762
|
+
{
|
|
763
|
+
name: 'A',
|
|
764
|
+
chart1: 80,
|
|
765
|
+
chart2: 70,
|
|
766
|
+
chart3: 60,
|
|
767
|
+
chart4: 75,
|
|
768
|
+
chart5: 55,
|
|
769
|
+
chart6: 65,
|
|
770
|
+
chart7: 72,
|
|
771
|
+
chart8: 68,
|
|
772
|
+
},
|
|
773
|
+
];
|
|
774
|
+
|
|
775
|
+
return (
|
|
776
|
+
<ChartCard
|
|
777
|
+
title="Chart Color Palette"
|
|
778
|
+
description="All 8 chart tokens — vibrant, accessible, harmonious"
|
|
779
|
+
>
|
|
780
|
+
<DashboardBarChart
|
|
781
|
+
data={paletteData}
|
|
782
|
+
indexKey="name"
|
|
783
|
+
config={paletteConfig}
|
|
784
|
+
barSize="xl"
|
|
785
|
+
showGrid={false}
|
|
786
|
+
/>
|
|
787
|
+
</ChartCard>
|
|
788
|
+
);
|
|
789
|
+
},
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
// ─── Radar Chart Stories ───────────────────────────────────────────────────────
|
|
793
|
+
|
|
794
|
+
const radarData = [
|
|
795
|
+
{ skill: 'Performance', score: 88 },
|
|
796
|
+
{ skill: 'Reliability', score: 72 },
|
|
797
|
+
{ skill: 'Security', score: 95 },
|
|
798
|
+
{ skill: 'Scalability', score: 65 },
|
|
799
|
+
{ skill: 'Usability', score: 80 },
|
|
800
|
+
{ skill: 'Maintainability', score: 58 },
|
|
801
|
+
];
|
|
802
|
+
|
|
803
|
+
const radarMultiData = [
|
|
804
|
+
{ skill: 'Performance', teamA: 88, teamB: 62 },
|
|
805
|
+
{ skill: 'Reliability', teamA: 72, teamB: 85 },
|
|
806
|
+
{ skill: 'Security', teamA: 95, teamB: 70 },
|
|
807
|
+
{ skill: 'Scalability', teamA: 65, teamB: 90 },
|
|
808
|
+
{ skill: 'Usability', teamA: 80, teamB: 55 },
|
|
809
|
+
{ skill: 'Maintainability', teamA: 58, teamB: 78 },
|
|
810
|
+
];
|
|
811
|
+
|
|
812
|
+
export const RadarChartFilled: Story = {
|
|
813
|
+
name: 'Radar Chart / Filled',
|
|
814
|
+
render: () => (
|
|
815
|
+
<ChartCard title="System Health Score" description="Filled radar — single series">
|
|
816
|
+
<RadarMetricChart
|
|
817
|
+
data={radarData}
|
|
818
|
+
labelKey="skill"
|
|
819
|
+
series={[{ key: 'score', label: 'Score' }]}
|
|
820
|
+
filled
|
|
821
|
+
showLegend={false}
|
|
822
|
+
/>
|
|
823
|
+
</ChartCard>
|
|
824
|
+
),
|
|
825
|
+
};
|
|
826
|
+
|
|
827
|
+
export const RadarChartOutline: Story = {
|
|
828
|
+
name: 'Radar Chart / Outline',
|
|
829
|
+
render: () => (
|
|
830
|
+
<ChartCard title="System Health Score" description="Outline only — no fill">
|
|
831
|
+
<RadarMetricChart
|
|
832
|
+
data={radarData}
|
|
833
|
+
labelKey="skill"
|
|
834
|
+
series={[{ key: 'score', label: 'Score' }]}
|
|
835
|
+
filled={false}
|
|
836
|
+
showDots
|
|
837
|
+
showLegend={false}
|
|
838
|
+
/>
|
|
839
|
+
</ChartCard>
|
|
840
|
+
),
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
export const RadarChartMultiSeries: Story = {
|
|
844
|
+
name: 'Radar Chart / Multi-Series',
|
|
845
|
+
render: () => (
|
|
846
|
+
<ChartCard title="Team Comparison" description="Two teams across 6 dimensions">
|
|
847
|
+
<RadarMetricChart
|
|
848
|
+
data={radarMultiData}
|
|
849
|
+
labelKey="skill"
|
|
850
|
+
series={[
|
|
851
|
+
{ key: 'teamA', label: 'Team Alpha' },
|
|
852
|
+
{ key: 'teamB', label: 'Team Beta' },
|
|
853
|
+
]}
|
|
854
|
+
filled
|
|
855
|
+
fillOpacity={0.2}
|
|
856
|
+
showDots
|
|
857
|
+
/>
|
|
858
|
+
</ChartCard>
|
|
859
|
+
),
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
export const RadarChartVariants: Story = {
|
|
863
|
+
name: 'Radar Chart / All Variants',
|
|
864
|
+
render: () => (
|
|
865
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
866
|
+
<ChartCard title="Filled" description="Default filled area">
|
|
867
|
+
<RadarMetricChart
|
|
868
|
+
data={radarData}
|
|
869
|
+
labelKey="skill"
|
|
870
|
+
series={[{ key: 'score', label: 'Score' }]}
|
|
871
|
+
filled
|
|
872
|
+
showLegend={false}
|
|
873
|
+
/>
|
|
874
|
+
</ChartCard>
|
|
875
|
+
<ChartCard title="Outline + Dots" description="No fill, with dots">
|
|
876
|
+
<RadarMetricChart
|
|
877
|
+
data={radarData}
|
|
878
|
+
labelKey="skill"
|
|
879
|
+
series={[{ key: 'score', label: 'Score' }]}
|
|
880
|
+
filled={false}
|
|
881
|
+
showDots
|
|
882
|
+
showLegend={false}
|
|
883
|
+
/>
|
|
884
|
+
</ChartCard>
|
|
885
|
+
<ChartCard title="Multi-Series" description="Comparison overlay">
|
|
886
|
+
<RadarMetricChart
|
|
887
|
+
data={radarMultiData}
|
|
888
|
+
labelKey="skill"
|
|
889
|
+
series={[
|
|
890
|
+
{ key: 'teamA', label: 'Team A' },
|
|
891
|
+
{ key: 'teamB', label: 'Team B' },
|
|
892
|
+
]}
|
|
893
|
+
filled
|
|
894
|
+
fillOpacity={0.18}
|
|
895
|
+
/>
|
|
896
|
+
</ChartCard>
|
|
897
|
+
</div>
|
|
898
|
+
),
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
// ─── Pie Chart Stories ────────────────────────────────────────────────────────
|
|
902
|
+
|
|
903
|
+
const pieData = [
|
|
904
|
+
{ category: 'Infrastructure', spend: 42000 },
|
|
905
|
+
{ category: 'Engineering', spend: 31000 },
|
|
906
|
+
{ category: 'Marketing', spend: 18500 },
|
|
907
|
+
{ category: 'Operations', spend: 12000 },
|
|
908
|
+
{ category: 'Other', spend: 6500 },
|
|
909
|
+
];
|
|
910
|
+
|
|
911
|
+
export const PieChartSimple: Story = {
|
|
912
|
+
name: 'Pie Chart / Simple',
|
|
913
|
+
render: () => (
|
|
914
|
+
<ChartCard title="Budget Breakdown" description="Simple pie — no labels">
|
|
915
|
+
<PieMetricChart
|
|
916
|
+
data={pieData}
|
|
917
|
+
nameKey="category"
|
|
918
|
+
valueKey="spend"
|
|
919
|
+
valueFormatter={v => `$${(v as number).toLocaleString()}`}
|
|
920
|
+
/>
|
|
921
|
+
</ChartCard>
|
|
922
|
+
),
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
export const PieChartWithLabels: Story = {
|
|
926
|
+
name: 'Pie Chart / With Labels',
|
|
927
|
+
render: () => (
|
|
928
|
+
<ChartCard title="Budget Breakdown" description="Pie with percentage labels">
|
|
929
|
+
<PieMetricChart
|
|
930
|
+
data={pieData}
|
|
931
|
+
nameKey="category"
|
|
932
|
+
valueKey="spend"
|
|
933
|
+
showLabels
|
|
934
|
+
valueFormatter={v => `$${(v as number).toLocaleString()}`}
|
|
935
|
+
/>
|
|
936
|
+
</ChartCard>
|
|
937
|
+
),
|
|
938
|
+
};
|
|
939
|
+
|
|
940
|
+
export const PieChartExploded: Story = {
|
|
941
|
+
name: 'Pie Chart / Exploded Slice',
|
|
942
|
+
render: () => (
|
|
943
|
+
<ChartCard title="Budget Breakdown" description="Largest slice highlighted with drop shadow">
|
|
944
|
+
<PieMetricChart
|
|
945
|
+
data={pieData}
|
|
946
|
+
nameKey="category"
|
|
947
|
+
valueKey="spend"
|
|
948
|
+
showLabels
|
|
949
|
+
explodeIndex={0}
|
|
950
|
+
valueFormatter={v => `$${(v as number).toLocaleString()}`}
|
|
951
|
+
/>
|
|
952
|
+
</ChartCard>
|
|
953
|
+
),
|
|
954
|
+
};
|
|
955
|
+
|
|
956
|
+
export const PieChartDonutVariant: Story = {
|
|
957
|
+
name: 'Pie Chart / Donut Variant',
|
|
958
|
+
render: () => (
|
|
959
|
+
<ChartCard title="Budget Breakdown" description="Pie with inner radius (donut style)">
|
|
960
|
+
<PieMetricChart
|
|
961
|
+
data={pieData}
|
|
962
|
+
nameKey="category"
|
|
963
|
+
valueKey="spend"
|
|
964
|
+
innerRadius="45%"
|
|
965
|
+
showLabels
|
|
966
|
+
valueFormatter={v => `$${(v as number).toLocaleString()}`}
|
|
967
|
+
/>
|
|
968
|
+
</ChartCard>
|
|
969
|
+
),
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
export const PieChartVariants: Story = {
|
|
973
|
+
name: 'Pie Chart / All Variants',
|
|
974
|
+
render: () => (
|
|
975
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
976
|
+
<ChartCard title="Simple" description="No labels">
|
|
977
|
+
<PieMetricChart data={pieData} nameKey="category" valueKey="spend" />
|
|
978
|
+
</ChartCard>
|
|
979
|
+
<ChartCard title="With Labels" description="Percentage labels">
|
|
980
|
+
<PieMetricChart data={pieData} nameKey="category" valueKey="spend" showLabels />
|
|
981
|
+
</ChartCard>
|
|
982
|
+
<ChartCard title="Exploded" description="First slice highlighted">
|
|
983
|
+
<PieMetricChart
|
|
984
|
+
data={pieData}
|
|
985
|
+
nameKey="category"
|
|
986
|
+
valueKey="spend"
|
|
987
|
+
showLabels
|
|
988
|
+
explodeIndex={0}
|
|
989
|
+
/>
|
|
990
|
+
</ChartCard>
|
|
991
|
+
<ChartCard title="Donut" description="Inner radius 45%">
|
|
992
|
+
<PieMetricChart
|
|
993
|
+
data={pieData}
|
|
994
|
+
nameKey="category"
|
|
995
|
+
valueKey="spend"
|
|
996
|
+
innerRadius="45%"
|
|
997
|
+
showLabels
|
|
998
|
+
/>
|
|
999
|
+
</ChartCard>
|
|
1000
|
+
</div>
|
|
1001
|
+
),
|
|
1002
|
+
};
|
|
1003
|
+
|
|
1004
|
+
// ─── Radial Bar Chart Stories ─────────────────────────────────────────────────
|
|
1005
|
+
|
|
1006
|
+
const radialData = [
|
|
1007
|
+
{ name: 'Infrastructure', value: 78 },
|
|
1008
|
+
{ name: 'Engineering', value: 62 },
|
|
1009
|
+
{ name: 'Marketing', value: 45 },
|
|
1010
|
+
{ name: 'Operations', value: 91 },
|
|
1011
|
+
];
|
|
1012
|
+
|
|
1013
|
+
export const RadialBarChartSingle: Story = {
|
|
1014
|
+
name: 'Radial Bar / Single Bar',
|
|
1015
|
+
render: () => (
|
|
1016
|
+
<ChartCard title="Deployment Success Rate" description="Single radial bar — full circle">
|
|
1017
|
+
<RadialBarMetricChart
|
|
1018
|
+
data={[{ name: 'Success Rate', value: 87 }]}
|
|
1019
|
+
dataKey="value"
|
|
1020
|
+
nameKey="name"
|
|
1021
|
+
showLegend={false}
|
|
1022
|
+
innerRadius="60%"
|
|
1023
|
+
outerRadius="90%"
|
|
1024
|
+
valueFormatter={v => `${v}%`}
|
|
1025
|
+
/>
|
|
1026
|
+
</ChartCard>
|
|
1027
|
+
),
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
export const RadialBarChartMulti: Story = {
|
|
1031
|
+
name: 'Radial Bar / Multi-Bar',
|
|
1032
|
+
render: () => (
|
|
1033
|
+
<ChartCard title="Department KPIs" description="Multiple radial bars with background track">
|
|
1034
|
+
<RadialBarMetricChart
|
|
1035
|
+
data={radialData}
|
|
1036
|
+
dataKey="value"
|
|
1037
|
+
nameKey="name"
|
|
1038
|
+
innerRadius="20%"
|
|
1039
|
+
outerRadius="90%"
|
|
1040
|
+
valueFormatter={v => `${v}%`}
|
|
1041
|
+
/>
|
|
1042
|
+
</ChartCard>
|
|
1043
|
+
),
|
|
1044
|
+
};
|
|
1045
|
+
|
|
1046
|
+
export const RadialBarChartSemiCircle: Story = {
|
|
1047
|
+
name: 'Radial Bar / Semi-Circle',
|
|
1048
|
+
render: () => (
|
|
1049
|
+
<ChartCard
|
|
1050
|
+
title="Department KPIs"
|
|
1051
|
+
description="Semi-circle layout (startAngle=180, endAngle=0)"
|
|
1052
|
+
>
|
|
1053
|
+
<RadialBarMetricChart
|
|
1054
|
+
data={radialData}
|
|
1055
|
+
dataKey="value"
|
|
1056
|
+
nameKey="name"
|
|
1057
|
+
innerRadius="30%"
|
|
1058
|
+
outerRadius="90%"
|
|
1059
|
+
startAngle={180}
|
|
1060
|
+
endAngle={0}
|
|
1061
|
+
valueFormatter={v => `${v}%`}
|
|
1062
|
+
/>
|
|
1063
|
+
</ChartCard>
|
|
1064
|
+
),
|
|
1065
|
+
};
|
|
1066
|
+
|
|
1067
|
+
export const RadialBarChartVariants: Story = {
|
|
1068
|
+
name: 'Radial Bar / All Variants',
|
|
1069
|
+
render: () => (
|
|
1070
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
1071
|
+
<ChartCard title="Single Bar" description="Full circle">
|
|
1072
|
+
<RadialBarMetricChart
|
|
1073
|
+
data={[{ name: 'Success', value: 87 }]}
|
|
1074
|
+
dataKey="value"
|
|
1075
|
+
nameKey="name"
|
|
1076
|
+
showLegend={false}
|
|
1077
|
+
innerRadius="60%"
|
|
1078
|
+
outerRadius="90%"
|
|
1079
|
+
valueFormatter={v => `${v}%`}
|
|
1080
|
+
/>
|
|
1081
|
+
</ChartCard>
|
|
1082
|
+
<ChartCard title="Multi-Bar" description="Stacked radial bars">
|
|
1083
|
+
<RadialBarMetricChart
|
|
1084
|
+
data={radialData}
|
|
1085
|
+
dataKey="value"
|
|
1086
|
+
nameKey="name"
|
|
1087
|
+
innerRadius="20%"
|
|
1088
|
+
outerRadius="90%"
|
|
1089
|
+
valueFormatter={v => `${v}%`}
|
|
1090
|
+
/>
|
|
1091
|
+
</ChartCard>
|
|
1092
|
+
<ChartCard title="Semi-Circle" description="180° arc layout">
|
|
1093
|
+
<RadialBarMetricChart
|
|
1094
|
+
data={radialData}
|
|
1095
|
+
dataKey="value"
|
|
1096
|
+
nameKey="name"
|
|
1097
|
+
innerRadius="30%"
|
|
1098
|
+
outerRadius="90%"
|
|
1099
|
+
startAngle={180}
|
|
1100
|
+
endAngle={0}
|
|
1101
|
+
valueFormatter={v => `${v}%`}
|
|
1102
|
+
/>
|
|
1103
|
+
</ChartCard>
|
|
1104
|
+
</div>
|
|
1105
|
+
),
|
|
1106
|
+
};
|
|
1107
|
+
|
|
1108
|
+
// ─── Gauge Chart Stories ──────────────────────────────────────────────────────
|
|
1109
|
+
|
|
1110
|
+
const gaugeThresholds: GaugeChartThreshold[] = [
|
|
1111
|
+
{ value: 33, color: 'var(--chart-5)', label: 'Critical' },
|
|
1112
|
+
{ value: 66, color: 'var(--chart-3)', label: 'Warning' },
|
|
1113
|
+
{ value: 100, color: 'var(--chart-2)', label: 'Healthy' },
|
|
1114
|
+
];
|
|
1115
|
+
|
|
1116
|
+
export const GaugeChartSimple: Story = {
|
|
1117
|
+
name: 'Gauge Chart / Simple',
|
|
1118
|
+
render: () => (
|
|
1119
|
+
<ChartCard
|
|
1120
|
+
title="CPU Usage"
|
|
1121
|
+
description="Simple gauge — single color"
|
|
1122
|
+
className="max-w-sm mx-auto"
|
|
1123
|
+
>
|
|
1124
|
+
<div className="flex justify-center py-4">
|
|
1125
|
+
<GaugeChart value={67} label="CPU Usage" />
|
|
1126
|
+
</div>
|
|
1127
|
+
</ChartCard>
|
|
1128
|
+
),
|
|
1129
|
+
};
|
|
1130
|
+
|
|
1131
|
+
export const GaugeChartWithThresholds: Story = {
|
|
1132
|
+
name: 'Gauge Chart / With Thresholds',
|
|
1133
|
+
render: () => (
|
|
1134
|
+
<ChartCard
|
|
1135
|
+
title="System Health"
|
|
1136
|
+
description="Color zones: critical / warning / healthy"
|
|
1137
|
+
className="max-w-sm mx-auto"
|
|
1138
|
+
>
|
|
1139
|
+
<div className="flex justify-center py-4">
|
|
1140
|
+
<GaugeChart value={72} label="Overall Health" thresholds={gaugeThresholds} />
|
|
1141
|
+
</div>
|
|
1142
|
+
</ChartCard>
|
|
1143
|
+
),
|
|
1144
|
+
};
|
|
1145
|
+
|
|
1146
|
+
export const GaugeChartNoNeedle: Story = {
|
|
1147
|
+
name: 'Gauge Chart / No Needle',
|
|
1148
|
+
render: () => (
|
|
1149
|
+
<ChartCard
|
|
1150
|
+
title="Memory Usage"
|
|
1151
|
+
description="Arc only — no needle indicator"
|
|
1152
|
+
className="max-w-sm mx-auto"
|
|
1153
|
+
>
|
|
1154
|
+
<div className="flex justify-center py-4">
|
|
1155
|
+
<GaugeChart value={45} label="Memory" showNeedle={false} thresholds={gaugeThresholds} />
|
|
1156
|
+
</div>
|
|
1157
|
+
</ChartCard>
|
|
1158
|
+
),
|
|
1159
|
+
};
|
|
1160
|
+
|
|
1161
|
+
export const GaugeChartVariants: Story = {
|
|
1162
|
+
name: 'Gauge Chart / All Variants',
|
|
1163
|
+
render: () => (
|
|
1164
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
1165
|
+
<ChartCard title="Low (22%)" description="Critical zone">
|
|
1166
|
+
<div className="flex justify-center py-2">
|
|
1167
|
+
<GaugeChart value={22} label="CPU" thresholds={gaugeThresholds} />
|
|
1168
|
+
</div>
|
|
1169
|
+
</ChartCard>
|
|
1170
|
+
<ChartCard title="Medium (55%)" description="Warning zone">
|
|
1171
|
+
<div className="flex justify-center py-2">
|
|
1172
|
+
<GaugeChart value={55} label="Memory" thresholds={gaugeThresholds} />
|
|
1173
|
+
</div>
|
|
1174
|
+
</ChartCard>
|
|
1175
|
+
<ChartCard title="High (88%)" description="Healthy zone">
|
|
1176
|
+
<div className="flex justify-center py-2">
|
|
1177
|
+
<GaugeChart value={88} label="Disk I/O" thresholds={gaugeThresholds} />
|
|
1178
|
+
</div>
|
|
1179
|
+
</ChartCard>
|
|
1180
|
+
</div>
|
|
1181
|
+
),
|
|
1182
|
+
};
|
|
1183
|
+
|
|
1184
|
+
export const GaugeChartDashboard: Story = {
|
|
1185
|
+
name: 'Gauge Chart / Infrastructure Dashboard',
|
|
1186
|
+
render: () => {
|
|
1187
|
+
const metrics = [
|
|
1188
|
+
{ label: 'CPU', value: 34, unit: '%' },
|
|
1189
|
+
{ label: 'Memory', value: 71, unit: '%' },
|
|
1190
|
+
{ label: 'Disk', value: 58, unit: '%' },
|
|
1191
|
+
{ label: 'Network', value: 22, unit: '%' },
|
|
1192
|
+
];
|
|
1193
|
+
|
|
1194
|
+
return (
|
|
1195
|
+
<div className="space-y-4">
|
|
1196
|
+
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
1197
|
+
{metrics.map(m => (
|
|
1198
|
+
<ChartCard key={m.label} title={m.label} description={`Current ${m.label} utilization`}>
|
|
1199
|
+
<div className="flex justify-center py-2">
|
|
1200
|
+
<GaugeChart
|
|
1201
|
+
value={m.value}
|
|
1202
|
+
label={m.label}
|
|
1203
|
+
thresholds={gaugeThresholds}
|
|
1204
|
+
valueFormatter={v => `${v}${m.unit}`}
|
|
1205
|
+
/>
|
|
1206
|
+
</div>
|
|
1207
|
+
</ChartCard>
|
|
1208
|
+
))}
|
|
1209
|
+
</div>
|
|
1210
|
+
</div>
|
|
1211
|
+
);
|
|
1212
|
+
},
|
|
1213
|
+
};
|
|
1214
|
+
|
|
1215
|
+
// ─── Complete Chart Library Overview ─────────────────────────────────────────
|
|
1216
|
+
|
|
1217
|
+
export const CompleteLibraryOverview: Story = {
|
|
1218
|
+
name: 'Complete Library / All Chart Types',
|
|
1219
|
+
render: () => (
|
|
1220
|
+
<div className="space-y-6">
|
|
1221
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
1222
|
+
{/* Bar */}
|
|
1223
|
+
<ChartCard title="Bar Chart" description="Categorical comparison">
|
|
1224
|
+
<DashboardBarChart
|
|
1225
|
+
data={[
|
|
1226
|
+
{ month: 'Jan', revenue: 42000 },
|
|
1227
|
+
{ month: 'Feb', revenue: 38000 },
|
|
1228
|
+
{ month: 'Mar', revenue: 51000 },
|
|
1229
|
+
{ month: 'Apr', revenue: 47000 },
|
|
1230
|
+
{ month: 'May', revenue: 55000 },
|
|
1231
|
+
]}
|
|
1232
|
+
indexKey="month"
|
|
1233
|
+
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
|
|
1234
|
+
series={[{ key: 'revenue', label: 'Revenue' }]}
|
|
1235
|
+
showLegend={false}
|
|
1236
|
+
/>
|
|
1237
|
+
</ChartCard>
|
|
1238
|
+
|
|
1239
|
+
{/* Line */}
|
|
1240
|
+
<ChartCard title="Line Chart" description="Trend over time">
|
|
1241
|
+
<DashboardLineChart
|
|
1242
|
+
data={[
|
|
1243
|
+
{ month: 'Jan', users: 1200 },
|
|
1244
|
+
{ month: 'Feb', users: 1450 },
|
|
1245
|
+
{ month: 'Mar', users: 1380 },
|
|
1246
|
+
{ month: 'Apr', users: 1620 },
|
|
1247
|
+
{ month: 'May', users: 1890 },
|
|
1248
|
+
]}
|
|
1249
|
+
indexKey="month"
|
|
1250
|
+
config={{ users: { label: 'Users', color: 'var(--chart-2)' } }}
|
|
1251
|
+
series={[{ key: 'users', label: 'Users' }]}
|
|
1252
|
+
showLegend={false}
|
|
1253
|
+
/>
|
|
1254
|
+
</ChartCard>
|
|
1255
|
+
|
|
1256
|
+
{/* Donut */}
|
|
1257
|
+
<ChartCard title="Donut Chart" description="Part-to-whole">
|
|
1258
|
+
<DonutBreakdownChart
|
|
1259
|
+
data={[
|
|
1260
|
+
{ name: 'Active', value: 68 },
|
|
1261
|
+
{ name: 'Idle', value: 22 },
|
|
1262
|
+
{ name: 'Offline', value: 10 },
|
|
1263
|
+
]}
|
|
1264
|
+
nameKey="name"
|
|
1265
|
+
valueKey="value"
|
|
1266
|
+
config={{
|
|
1267
|
+
Active: { label: 'Active', color: 'var(--chart-2)' },
|
|
1268
|
+
Idle: { label: 'Idle', color: 'var(--chart-3)' },
|
|
1269
|
+
Offline: { label: 'Offline', color: 'var(--chart-5)' },
|
|
1270
|
+
}}
|
|
1271
|
+
centerValue="68%"
|
|
1272
|
+
centerLabel="Active"
|
|
1273
|
+
showLegend={false}
|
|
1274
|
+
/>
|
|
1275
|
+
</ChartCard>
|
|
1276
|
+
|
|
1277
|
+
{/* Radar */}
|
|
1278
|
+
<ChartCard title="Radar Chart" description="Multi-dimensional">
|
|
1279
|
+
<RadarMetricChart
|
|
1280
|
+
data={radarData}
|
|
1281
|
+
labelKey="skill"
|
|
1282
|
+
series={[{ key: 'score', label: 'Score' }]}
|
|
1283
|
+
filled
|
|
1284
|
+
showLegend={false}
|
|
1285
|
+
/>
|
|
1286
|
+
</ChartCard>
|
|
1287
|
+
|
|
1288
|
+
{/* Pie */}
|
|
1289
|
+
<ChartCard title="Pie Chart" description="Proportional slices">
|
|
1290
|
+
<PieMetricChart
|
|
1291
|
+
data={pieData}
|
|
1292
|
+
nameKey="category"
|
|
1293
|
+
valueKey="spend"
|
|
1294
|
+
showLabels
|
|
1295
|
+
showLegend={false}
|
|
1296
|
+
/>
|
|
1297
|
+
</ChartCard>
|
|
1298
|
+
|
|
1299
|
+
{/* Radial Bar */}
|
|
1300
|
+
<ChartCard title="Radial Bar" description="Progress rings">
|
|
1301
|
+
<RadialBarMetricChart
|
|
1302
|
+
data={radialData}
|
|
1303
|
+
dataKey="value"
|
|
1304
|
+
nameKey="name"
|
|
1305
|
+
innerRadius="20%"
|
|
1306
|
+
outerRadius="90%"
|
|
1307
|
+
valueFormatter={v => `${v}%`}
|
|
1308
|
+
/>
|
|
1309
|
+
</ChartCard>
|
|
1310
|
+
</div>
|
|
1311
|
+
|
|
1312
|
+
{/* Gauge row */}
|
|
1313
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
1314
|
+
{[
|
|
1315
|
+
{ label: 'CPU', value: 34 },
|
|
1316
|
+
{ label: 'Memory', value: 71 },
|
|
1317
|
+
{ label: 'Disk', value: 58 },
|
|
1318
|
+
].map(m => (
|
|
1319
|
+
<ChartCard key={m.label} title={`Gauge — ${m.label}`} description="Semicircle gauge">
|
|
1320
|
+
<div className="flex justify-center py-2">
|
|
1321
|
+
<GaugeChart value={m.value} label={m.label} thresholds={gaugeThresholds} />
|
|
1322
|
+
</div>
|
|
1323
|
+
</ChartCard>
|
|
1324
|
+
))}
|
|
1325
|
+
</div>
|
|
1326
|
+
</div>
|
|
1327
|
+
),
|
|
1328
|
+
};
|