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