@wakastellar/ui 2.3.4 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/dist/blocks/dashboard/index.d.ts +4 -1
  2. package/dist/blocks/empty-states/index.d.ts +4 -1
  3. package/dist/blocks/error-pages/index.d.ts +4 -1
  4. package/dist/blocks/index.d.ts +1 -1
  5. package/dist/blocks/landing/index.d.ts +4 -1
  6. package/dist/blocks/pricing/index.d.ts +5 -1
  7. package/dist/blocks/sidebar/index.d.ts +5 -1
  8. package/dist/index.cjs.js +130 -130
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.es.js +7905 -7856
  11. package/dist/stories/Button.d.ts +14 -0
  12. package/dist/stories/Button.stories.d.ts +8 -0
  13. package/dist/stories/Header.d.ts +11 -0
  14. package/dist/stories/Header.stories.d.ts +6 -0
  15. package/dist/stories/Page.d.ts +2 -0
  16. package/dist/stories/Page.stories.d.ts +6 -0
  17. package/dist/types/index.d.ts +1 -0
  18. package/dist/types/link.d.ts +23 -0
  19. package/package.json +11 -3
  20. package/src/blocks/activity-timeline/ActivityTimeline.stories.tsx +460 -0
  21. package/src/blocks/apm-overview/APMOverview.stories.tsx +435 -0
  22. package/src/blocks/auth-2fa/Auth2FA.stories.tsx +308 -0
  23. package/src/blocks/calendar-view/CalendarView.stories.tsx +398 -0
  24. package/src/blocks/chat/Chat.stories.tsx +466 -0
  25. package/src/blocks/chat-interface/ChatInterface.stories.tsx +412 -0
  26. package/src/blocks/checkout-flow/CheckoutFlow.stories.tsx +408 -0
  27. package/src/blocks/cicd-builder/CICDBuilder.stories.tsx +499 -0
  28. package/src/blocks/cloud-cost-dashboard/CloudCostDashboard.stories.tsx +356 -0
  29. package/src/blocks/container-orchestrator/ContainerOrchestrator.stories.tsx +461 -0
  30. package/src/blocks/dashboard/Dashboard.stories.tsx +559 -0
  31. package/src/blocks/dashboard/index.tsx +68 -27
  32. package/src/blocks/dashboard-kpi/DashboardKPI.stories.tsx +422 -0
  33. package/src/blocks/database-admin/DatabaseAdmin.stories.tsx +393 -0
  34. package/src/blocks/deployment-dashboard/DeploymentDashboard.stories.tsx +457 -0
  35. package/src/blocks/empty-states/EmptyStates.stories.tsx +467 -0
  36. package/src/blocks/empty-states/index.tsx +26 -8
  37. package/src/blocks/error-pages/ErrorPages.stories.tsx +401 -0
  38. package/src/blocks/error-pages/index.tsx +26 -8
  39. package/src/blocks/faq/FAQ.stories.tsx +416 -0
  40. package/src/blocks/file-manager/FileManager.stories.tsx +413 -0
  41. package/src/blocks/footer/Footer.stories.tsx +328 -0
  42. package/src/blocks/gitops-sync-status/GitOpsSyncStatus.stories.tsx +529 -0
  43. package/src/blocks/header/WakaHeader.stories.tsx +455 -0
  44. package/src/blocks/headtab/Headtab.stories.tsx +369 -0
  45. package/src/blocks/i18n-editor/I18nEditor.stories.tsx +451 -0
  46. package/src/blocks/incident-manager/IncidentManager.stories.tsx +464 -0
  47. package/src/blocks/index.ts +1 -1
  48. package/src/blocks/infrastructure-map/InfrastructureMap.stories.tsx +533 -0
  49. package/src/blocks/kanban-board/KanbanBoard.stories.tsx +494 -0
  50. package/src/blocks/landing/WakaLanding.stories.tsx +449 -0
  51. package/src/blocks/landing/index.tsx +125 -66
  52. package/src/blocks/language-selector/LanguageSelector.stories.tsx +345 -0
  53. package/src/blocks/layout/Layout.stories.tsx +373 -0
  54. package/src/blocks/login/Login.stories.tsx +443 -0
  55. package/src/blocks/on-call-schedule/OnCallSchedule.stories.tsx +381 -0
  56. package/src/blocks/player-profile/PlayerProfile.stories.tsx +316 -0
  57. package/src/blocks/pricing/WakaPricing.stories.tsx +530 -0
  58. package/src/blocks/pricing/index.tsx +38 -4
  59. package/src/blocks/profile/Profile.stories.tsx +371 -0
  60. package/src/blocks/release-notes/ReleaseNotes.stories.tsx +431 -0
  61. package/src/blocks/settings/Settings.stories.tsx +520 -0
  62. package/src/blocks/sidebar/WakaSidebar.stories.tsx +513 -0
  63. package/src/blocks/sidebar/index.tsx +49 -20
  64. package/src/blocks/theme-creator-block/ThemeCreatorBlock.stories.tsx +370 -0
  65. package/src/blocks/user-management/UserManagement.stories.tsx +411 -0
  66. package/src/blocks/wizard/Wizard.stories.tsx +683 -0
  67. package/src/components/accordion/Accordion.stories.tsx +93 -0
  68. package/src/components/alert/Alert.stories.tsx +95 -0
  69. package/src/components/alert-dialog/AlertDialog.stories.tsx +126 -0
  70. package/src/components/aspect-ratio/AspectRatio.stories.tsx +118 -0
  71. package/src/components/avatar/Avatar.stories.tsx +104 -0
  72. package/src/components/button/Button.stories.tsx +12 -1
  73. package/src/components/calendar/Calendar.stories.tsx +102 -0
  74. package/src/components/card/Card.stories.tsx +125 -0
  75. package/src/components/checkbox/Checkbox.stories.tsx +100 -0
  76. package/src/components/code/Code.stories.tsx +402 -0
  77. package/src/components/collapsible/Collapsible.stories.tsx +123 -0
  78. package/src/components/command/Command.stories.tsx +207 -0
  79. package/src/components/context-menu/ContextMenu.stories.tsx +220 -0
  80. package/src/components/dialog/Dialog.stories.tsx +157 -0
  81. package/src/components/dropdown-menu/DropdownMenu.stories.tsx +225 -0
  82. package/src/components/form/Form.stories.tsx +413 -0
  83. package/src/components/hover-card/HoverCard.stories.tsx +148 -0
  84. package/src/components/input-otp/InputOTP.stories.tsx +255 -0
  85. package/src/components/label/Label.stories.tsx +68 -0
  86. package/src/components/menubar/Menubar.stories.tsx +278 -0
  87. package/src/components/navigation-menu/NavigationMenu.stories.tsx +202 -0
  88. package/src/components/popover/Popover.stories.tsx +199 -0
  89. package/src/components/progress/Progress.stories.tsx +104 -0
  90. package/src/components/radio-group/RadioGroup.stories.tsx +138 -0
  91. package/src/components/scroll-area/ScrollArea.stories.tsx +153 -0
  92. package/src/components/select/Select.stories.tsx +146 -0
  93. package/src/components/separator/Separator.stories.tsx +117 -0
  94. package/src/components/sheet/Sheet.stories.tsx +195 -0
  95. package/src/components/skeleton/Skeleton.stories.tsx +114 -0
  96. package/src/components/slider/Slider.stories.tsx +157 -0
  97. package/src/components/switch/Switch.stories.tsx +114 -0
  98. package/src/components/table/Table.stories.tsx +153 -0
  99. package/src/components/tabs/Tabs.stories.tsx +155 -0
  100. package/src/components/textarea/Textarea.stories.tsx +116 -0
  101. package/src/components/toast/Toast.stories.tsx +160 -0
  102. package/src/components/toggle/Toggle.stories.tsx +125 -0
  103. package/src/components/tooltip/Tooltip.stories.tsx +133 -0
  104. package/src/components/typography/Typography.stories.tsx +207 -0
  105. package/src/components/waka-3d-pie-chart/Waka3DPieChart.stories.tsx +308 -0
  106. package/src/components/waka-achievement-unlock/WakaAchievementUnlock.stories.tsx +353 -0
  107. package/src/components/waka-artifact-list/WakaArtifactList.stories.tsx +258 -0
  108. package/src/components/waka-autocomplete/WakaAutocomplete.stories.tsx +224 -0
  109. package/src/components/waka-badge-showcase/WakaBadgeShowcase.stories.tsx +269 -0
  110. package/src/components/waka-barcode/WakaBarcode.stories.tsx +227 -0
  111. package/src/components/waka-bottom-sheet/WakaBottomSheet.stories.tsx +408 -0
  112. package/src/components/waka-breadcrumb/WakaBreadcrumb.stories.tsx +237 -0
  113. package/src/components/waka-build-matrix/WakaBuildMatrix.stories.tsx +328 -0
  114. package/src/components/waka-carousel/WakaCarousel.stories.tsx +296 -0
  115. package/src/components/waka-charts/WakaCharts.stories.tsx +519 -0
  116. package/src/components/waka-color-picker/WakaColorPicker.stories.tsx +200 -0
  117. package/src/components/waka-combobox/WakaCombobox.stories.tsx +250 -0
  118. package/src/components/waka-container-list/WakaContainerList.stories.tsx +315 -0
  119. package/src/components/waka-contribution-graph/WakaContributionGraph.stories.tsx +354 -0
  120. package/src/components/waka-cost-breakdown/WakaCostBreakdown.stories.tsx +348 -0
  121. package/src/components/waka-daily-reward/WakaDailyReward.stories.tsx +365 -0
  122. package/src/components/waka-database-card/WakaDatabaseCard.stories.tsx +306 -0
  123. package/src/components/waka-date-range-picker/WakaDateRangePicker.stories.tsx +339 -0
  124. package/src/components/waka-datetime-picker/WakaDateTimePicker.stories.tsx +317 -0
  125. package/src/components/waka-deployment-lane/WakaDeploymentLane.stories.tsx +292 -0
  126. package/src/components/waka-dock/WakaDock.stories.tsx +332 -0
  127. package/src/components/waka-drawer/WakaDrawer.stories.tsx +437 -0
  128. package/src/components/waka-env-var-editor/WakaEnvVarEditor.stories.tsx +263 -0
  129. package/src/components/waka-error-shake/WakaErrorShake.stories.tsx +410 -0
  130. package/src/components/waka-file-upload/WakaFileUpload.stories.tsx +239 -0
  131. package/src/components/waka-flow-diagram/WakaFlowDiagram.stories.tsx +365 -0
  132. package/src/components/waka-funnel-chart/WakaFunnelChart.stories.tsx +281 -0
  133. package/src/components/waka-glow-card/WakaGlowCard.stories.tsx +274 -0
  134. package/src/components/waka-haptic-button/WakaHapticButton.stories.tsx +349 -0
  135. package/src/components/waka-health-pulse/WakaHealthPulse.stories.tsx +293 -0
  136. package/src/components/waka-heatmap/WakaHeatmap.stories.tsx +376 -0
  137. package/src/components/waka-image/WakaImage.stories.tsx +255 -0
  138. package/src/components/waka-incident-timeline/WakaIncidentTimeline.stories.tsx +300 -0
  139. package/src/components/waka-kanban/WakaKanban.stories.tsx +399 -0
  140. package/src/components/waka-kubernetes-overview/WakaKubernetesOverview.stories.tsx +281 -0
  141. package/src/components/waka-leaderboard/WakaLeaderboard.stories.tsx +300 -0
  142. package/src/components/waka-level-progress/WakaLevelProgress.stories.tsx +313 -0
  143. package/src/components/waka-loading-orbit/WakaLoadingOrbit.stories.tsx +413 -0
  144. package/src/components/waka-log-viewer/WakaLogViewer.stories.tsx +312 -0
  145. package/src/components/waka-loot-box/WakaLootBox.stories.tsx +374 -0
  146. package/src/components/waka-metric-sparkline/WakaMetricSparkline.stories.tsx +312 -0
  147. package/src/components/waka-migration-list/WakaMigrationList.stories.tsx +289 -0
  148. package/src/components/waka-modal/WakaModal.stories.tsx +434 -0
  149. package/src/components/waka-morph-button/WakaMorphButton.stories.tsx +405 -0
  150. package/src/components/waka-network-topology/WakaNetworkTopology.stories.tsx +364 -0
  151. package/src/components/waka-notifications/WakaNotifications.stories.tsx +290 -0
  152. package/src/components/waka-number-input/WakaNumberInput.stories.tsx +282 -0
  153. package/src/components/waka-pagination/WakaPagination.stories.tsx +328 -0
  154. package/src/components/waka-password-strength/WakaPasswordStrength.stories.tsx +318 -0
  155. package/src/components/waka-pipeline-view/WakaPipelineView.stories.tsx +386 -0
  156. package/src/components/waka-player-card/WakaPlayerCard.stories.tsx +333 -0
  157. package/src/components/waka-pod-card/WakaPodCard.stories.tsx +435 -0
  158. package/src/components/waka-qrcode/WakaQRCode.stories.tsx +232 -0
  159. package/src/components/waka-query-explain/WakaQueryExplain.stories.tsx +407 -0
  160. package/src/components/waka-quest-card/WakaQuestCard.stories.tsx +394 -0
  161. package/src/components/waka-quota-bar/WakaQuotaBar.stories.tsx +435 -0
  162. package/src/components/waka-radar-score/WakaRadarScore.stories.tsx +372 -0
  163. package/src/components/waka-resource-gauge/WakaResourceGauge.stories.tsx +366 -0
  164. package/src/components/waka-rich-text-editor/WakaRichTextEditor.stories.tsx +238 -0
  165. package/src/components/waka-sankey-diagram/WakaSankeyDiagram.stories.tsx +389 -0
  166. package/src/components/waka-scratch-card/WakaScratchCard.stories.tsx +388 -0
  167. package/src/components/waka-secret-card/WakaSecretCard.stories.tsx +314 -0
  168. package/src/components/waka-segmented-control/WakaSegmentedControl.stories.tsx +309 -0
  169. package/src/components/waka-server-rack/WakaServerRack.stories.tsx +382 -0
  170. package/src/components/waka-service-graph/WakaServiceGraph.stories.tsx +262 -0
  171. package/src/components/waka-skeleton-wave/WakaSkeletonWave.stories.tsx +321 -0
  172. package/src/components/waka-skill-tree/WakaSkillTree.stories.tsx +308 -0
  173. package/src/components/waka-spin-wheel/WakaSpinWheel.stories.tsx +368 -0
  174. package/src/components/waka-spinner/WakaSpinner.stories.tsx +156 -0
  175. package/src/components/waka-stat/WakaStat.stories.tsx +334 -0
  176. package/src/components/waka-status-matrix/WakaStatusMatrix.stories.tsx +331 -0
  177. package/src/components/waka-stepper/WakaStepper.stories.tsx +468 -0
  178. package/src/components/waka-streak-counter/WakaStreakCounter.stories.tsx +235 -0
  179. package/src/components/waka-success-explosion/WakaSuccessExplosion.stories.tsx +389 -0
  180. package/src/components/waka-tabs-morph/WakaTabsMorph.stories.tsx +471 -0
  181. package/src/components/waka-terminal-output/WakaTerminalOutput.stories.tsx +351 -0
  182. package/src/components/waka-test-report/WakaTestReport.stories.tsx +322 -0
  183. package/src/components/waka-tilt-card/WakaTiltCard.stories.tsx +300 -0
  184. package/src/components/waka-time-picker/WakaTimePicker.stories.tsx +227 -0
  185. package/src/components/waka-timeline/WakaTimeline.stories.tsx +383 -0
  186. package/src/components/waka-tournament-bracket/WakaTournamentBracket.stories.tsx +375 -0
  187. package/src/components/waka-trace-viewer/WakaTraceViewer.stories.tsx +445 -0
  188. package/src/components/waka-tree/WakaTree.stories.tsx +359 -0
  189. package/src/components/waka-treemap-chart/WakaTreemapChart.stories.tsx +378 -0
  190. package/src/components/waka-typewriter/WakaTypewriter.stories.tsx +366 -0
  191. package/src/components/waka-versus-card/WakaVersusCard.stories.tsx +530 -0
  192. package/src/components/waka-video/WakaVideo.stories.tsx +203 -0
  193. package/src/components/waka-virtual-list/WakaVirtualList.stories.tsx +273 -0
  194. package/src/components/waka-xp-bar/WakaXPBar.stories.tsx +305 -0
@@ -0,0 +1,364 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaNetworkTopology } from './index'
3
+ import type { NetworkNode, NetworkEdge } from './index'
4
+ import * as React from 'react'
5
+
6
+ const simpleTopologyNodes: NetworkNode[] = [
7
+ { id: 'lb', label: 'Load Balancer', type: 'loadbalancer', status: 'healthy', x: 400, y: 100 },
8
+ { id: 'web1', label: 'Web Server 1', type: 'server', status: 'healthy', x: 200, y: 250, metrics: { cpu: 45, memory: 62, connections: 1240 } },
9
+ { id: 'web2', label: 'Web Server 2', type: 'server', status: 'healthy', x: 400, y: 250, metrics: { cpu: 52, memory: 58, connections: 1180 } },
10
+ { id: 'web3', label: 'Web Server 3', type: 'server', status: 'warning', x: 600, y: 250, metrics: { cpu: 78, memory: 85, connections: 1450 } },
11
+ { id: 'db', label: 'Database', type: 'database', status: 'healthy', x: 400, y: 400, metrics: { cpu: 35, memory: 72, connections: 450 } },
12
+ ]
13
+
14
+ const simpleTopologyEdges: NetworkEdge[] = [
15
+ { source: 'lb', target: 'web1', latency: 2, traffic: 'medium', status: 'active' },
16
+ { source: 'lb', target: 'web2', latency: 3, traffic: 'high', status: 'active' },
17
+ { source: 'lb', target: 'web3', latency: 5, traffic: 'medium', status: 'degraded' },
18
+ { source: 'web1', target: 'db', latency: 8, traffic: 'medium', status: 'active' },
19
+ { source: 'web2', target: 'db', latency: 7, traffic: 'high', status: 'active' },
20
+ { source: 'web3', target: 'db', latency: 12, traffic: 'low', status: 'active' },
21
+ ]
22
+
23
+ const complexTopologyNodes: NetworkNode[] = [
24
+ // Edge layer
25
+ { id: 'fw1', label: 'Firewall', type: 'firewall', status: 'healthy', x: 400, y: 50 },
26
+
27
+ // Load balancers
28
+ { id: 'lb1', label: 'LB Primary', type: 'loadbalancer', status: 'healthy', x: 250, y: 150 },
29
+ { id: 'lb2', label: 'LB Secondary', type: 'loadbalancer', status: 'healthy', x: 550, y: 150 },
30
+
31
+ // Application servers
32
+ { id: 'app1', label: 'App Server 1', type: 'server', status: 'healthy', x: 150, y: 280, metrics: { cpu: 42, memory: 58 } },
33
+ { id: 'app2', label: 'App Server 2', type: 'server', status: 'healthy', x: 350, y: 280, metrics: { cpu: 38, memory: 52 } },
34
+ { id: 'app3', label: 'App Server 3', type: 'server', status: 'warning', x: 550, y: 280, metrics: { cpu: 85, memory: 78 } },
35
+ { id: 'app4', label: 'App Server 4', type: 'server', status: 'error', x: 750, y: 280, metrics: { cpu: 95, memory: 92 } },
36
+
37
+ // Cache layer
38
+ { id: 'cache1', label: 'Redis Primary', type: 'database', status: 'healthy', x: 250, y: 400, metrics: { memory: 45 } },
39
+ { id: 'cache2', label: 'Redis Replica', type: 'database', status: 'healthy', x: 550, y: 400, metrics: { memory: 42 } },
40
+
41
+ // Database cluster
42
+ { id: 'db-primary', label: 'DB Primary', type: 'database', status: 'healthy', x: 300, y: 520, metrics: { cpu: 55, memory: 68 } },
43
+ { id: 'db-replica1', label: 'DB Replica 1', type: 'database', status: 'healthy', x: 500, y: 520, metrics: { cpu: 32, memory: 54 } },
44
+ { id: 'db-replica2', label: 'DB Replica 2', type: 'database', status: 'offline', x: 700, y: 520 },
45
+ ]
46
+
47
+ const complexTopologyEdges: NetworkEdge[] = [
48
+ // Firewall to LBs
49
+ { source: 'fw1', target: 'lb1', latency: 1, traffic: 'high', status: 'active' },
50
+ { source: 'fw1', target: 'lb2', latency: 1, traffic: 'medium', status: 'active' },
51
+
52
+ // LBs to App servers
53
+ { source: 'lb1', target: 'app1', latency: 2, traffic: 'high', status: 'active' },
54
+ { source: 'lb1', target: 'app2', latency: 2, traffic: 'medium', status: 'active' },
55
+ { source: 'lb2', target: 'app3', latency: 3, traffic: 'medium', status: 'degraded' },
56
+ { source: 'lb2', target: 'app4', latency: 8, traffic: 'low', status: 'down' },
57
+
58
+ // App servers to cache
59
+ { source: 'app1', target: 'cache1', latency: 1, traffic: 'high', status: 'active' },
60
+ { source: 'app2', target: 'cache1', latency: 1, traffic: 'medium', status: 'active' },
61
+ { source: 'app3', target: 'cache2', latency: 2, traffic: 'medium', status: 'active' },
62
+ { source: 'app4', target: 'cache2', latency: 5, traffic: 'low', status: 'degraded' },
63
+
64
+ // Cache to cache (replication)
65
+ { source: 'cache1', target: 'cache2', latency: 1, traffic: 'low', status: 'active' },
66
+
67
+ // Cache to DB
68
+ { source: 'cache1', target: 'db-primary', latency: 3, traffic: 'medium', status: 'active' },
69
+ { source: 'cache2', target: 'db-primary', latency: 4, traffic: 'low', status: 'active' },
70
+
71
+ // DB replication
72
+ { source: 'db-primary', target: 'db-replica1', latency: 5, traffic: 'medium', status: 'active' },
73
+ { source: 'db-primary', target: 'db-replica2', latency: 0, traffic: 'low', status: 'down' },
74
+ ]
75
+
76
+ const cloudTopologyNodes: NetworkNode[] = [
77
+ { id: 'internet', label: 'Internet', type: 'cloud', status: 'healthy', x: 400, y: 50 },
78
+ { id: 'cdn', label: 'CDN Edge', type: 'router', status: 'healthy', x: 200, y: 150 },
79
+ { id: 'waf', label: 'WAF', type: 'firewall', status: 'healthy', x: 400, y: 150 },
80
+ { id: 'api-gw', label: 'API Gateway', type: 'router', status: 'healthy', x: 600, y: 150 },
81
+ { id: 'k8s', label: 'K8s Cluster', type: 'cloud', status: 'healthy', x: 400, y: 280 },
82
+ { id: 'rds', label: 'RDS', type: 'database', status: 'healthy', x: 250, y: 400 },
83
+ { id: 'elasticache', label: 'ElastiCache', type: 'database', status: 'healthy', x: 550, y: 400 },
84
+ ]
85
+
86
+ const cloudTopologyEdges: NetworkEdge[] = [
87
+ { source: 'internet', target: 'cdn', traffic: 'high', status: 'active' },
88
+ { source: 'internet', target: 'waf', traffic: 'high', status: 'active' },
89
+ { source: 'internet', target: 'api-gw', traffic: 'medium', status: 'active' },
90
+ { source: 'cdn', target: 'k8s', latency: 5, traffic: 'high', status: 'active' },
91
+ { source: 'waf', target: 'k8s', latency: 3, traffic: 'high', status: 'active' },
92
+ { source: 'api-gw', target: 'k8s', latency: 2, traffic: 'medium', status: 'active' },
93
+ { source: 'k8s', target: 'rds', latency: 4, traffic: 'medium', status: 'active' },
94
+ { source: 'k8s', target: 'elasticache', latency: 1, traffic: 'high', status: 'active' },
95
+ ]
96
+
97
+ const meta: Meta<typeof WakaNetworkTopology> = {
98
+ title: 'Components/Charts/WakaNetworkTopology',
99
+ component: WakaNetworkTopology,
100
+ parameters: {
101
+ layout: 'centered',
102
+ docs: {
103
+ description: {
104
+ component: 'A network topology visualization for displaying infrastructure, showing nodes with status indicators, connections with latency/traffic metrics, and interactive features like zoom, pan, and selection.',
105
+ },
106
+ },
107
+ },
108
+ tags: ['autodocs'],
109
+ argTypes: {
110
+ showLatency: {
111
+ control: 'boolean',
112
+ description: 'Show latency labels on edges',
113
+ },
114
+ showTraffic: {
115
+ control: 'boolean',
116
+ description: 'Show traffic intensity on edges',
117
+ },
118
+ animated: {
119
+ control: 'boolean',
120
+ description: 'Enable animations',
121
+ },
122
+ },
123
+ }
124
+
125
+ export default meta
126
+ type Story = StoryObj<typeof WakaNetworkTopology>
127
+
128
+ export const Default: Story = {
129
+ args: {
130
+ nodes: simpleTopologyNodes,
131
+ edges: simpleTopologyEdges,
132
+ },
133
+ render: (args) => (
134
+ <div className="w-[800px] h-[500px]">
135
+ <WakaNetworkTopology {...args} />
136
+ </div>
137
+ ),
138
+ }
139
+
140
+ export const ComplexInfrastructure: Story = {
141
+ render: () => (
142
+ <div className="w-[900px] h-[650px]">
143
+ <WakaNetworkTopology
144
+ nodes={complexTopologyNodes}
145
+ edges={complexTopologyEdges}
146
+ />
147
+ </div>
148
+ ),
149
+ }
150
+
151
+ export const CloudArchitecture: Story = {
152
+ render: () => (
153
+ <div className="w-[800px] h-[500px]">
154
+ <WakaNetworkTopology
155
+ nodes={cloudTopologyNodes}
156
+ edges={cloudTopologyEdges}
157
+ />
158
+ </div>
159
+ ),
160
+ }
161
+
162
+ export const NoLatency: Story = {
163
+ render: () => (
164
+ <div className="w-[800px] h-[500px]">
165
+ <WakaNetworkTopology
166
+ nodes={simpleTopologyNodes}
167
+ edges={simpleTopologyEdges}
168
+ showLatency={false}
169
+ />
170
+ </div>
171
+ ),
172
+ }
173
+
174
+ export const NoTraffic: Story = {
175
+ render: () => (
176
+ <div className="w-[800px] h-[500px]">
177
+ <WakaNetworkTopology
178
+ nodes={simpleTopologyNodes}
179
+ edges={simpleTopologyEdges}
180
+ showTraffic={false}
181
+ />
182
+ </div>
183
+ ),
184
+ }
185
+
186
+ export const NoAnimation: Story = {
187
+ render: () => (
188
+ <div className="w-[800px] h-[500px]">
189
+ <WakaNetworkTopology
190
+ nodes={simpleTopologyNodes}
191
+ edges={simpleTopologyEdges}
192
+ animated={false}
193
+ />
194
+ </div>
195
+ ),
196
+ }
197
+
198
+ export const Interactive: Story = {
199
+ render: () => {
200
+ const [selectedNode, setSelectedNode] = React.useState<string | undefined>()
201
+ const [selectedEdge, setSelectedEdge] = React.useState<{ source: string; target: string } | null>(null)
202
+
203
+ const selectedNodeData = simpleTopologyNodes.find((n) => n.id === selectedNode)
204
+ const selectedEdgeData = selectedEdge
205
+ ? simpleTopologyEdges.find((e) => e.source === selectedEdge.source && e.target === selectedEdge.target)
206
+ : null
207
+
208
+ return (
209
+ <div className="space-y-4">
210
+ <div className="w-[800px] h-[450px]">
211
+ <WakaNetworkTopology
212
+ nodes={simpleTopologyNodes}
213
+ edges={simpleTopologyEdges}
214
+ selectedNode={selectedNode}
215
+ onNodeClick={(nodeId) => {
216
+ setSelectedNode(selectedNode === nodeId ? undefined : nodeId)
217
+ setSelectedEdge(null)
218
+ }}
219
+ onEdgeClick={(source, target) => {
220
+ setSelectedEdge({ source, target })
221
+ setSelectedNode(undefined)
222
+ }}
223
+ />
224
+ </div>
225
+ {(selectedNodeData || selectedEdgeData) && (
226
+ <div className="p-4 border rounded-lg bg-muted/50">
227
+ {selectedNodeData && (
228
+ <div>
229
+ <h4 className="font-semibold">{selectedNodeData.label}</h4>
230
+ <p className="text-sm text-muted-foreground">
231
+ Type: {selectedNodeData.type} | Status: {selectedNodeData.status}
232
+ </p>
233
+ {selectedNodeData.metrics && (
234
+ <div className="mt-2 grid grid-cols-3 gap-4 text-sm">
235
+ {selectedNodeData.metrics.cpu !== undefined && (
236
+ <div>
237
+ <span className="text-muted-foreground">CPU:</span> {selectedNodeData.metrics.cpu}%
238
+ </div>
239
+ )}
240
+ {selectedNodeData.metrics.memory !== undefined && (
241
+ <div>
242
+ <span className="text-muted-foreground">Memory:</span> {selectedNodeData.metrics.memory}%
243
+ </div>
244
+ )}
245
+ {selectedNodeData.metrics.connections !== undefined && (
246
+ <div>
247
+ <span className="text-muted-foreground">Connections:</span> {selectedNodeData.metrics.connections}
248
+ </div>
249
+ )}
250
+ </div>
251
+ )}
252
+ </div>
253
+ )}
254
+ {selectedEdgeData && (
255
+ <div>
256
+ <h4 className="font-semibold">
257
+ {selectedEdge?.source} → {selectedEdge?.target}
258
+ </h4>
259
+ <div className="mt-2 grid grid-cols-3 gap-4 text-sm">
260
+ <div>
261
+ <span className="text-muted-foreground">Latency:</span> {selectedEdgeData.latency}ms
262
+ </div>
263
+ <div>
264
+ <span className="text-muted-foreground">Traffic:</span> {selectedEdgeData.traffic}
265
+ </div>
266
+ <div>
267
+ <span className="text-muted-foreground">Status:</span> {selectedEdgeData.status}
268
+ </div>
269
+ </div>
270
+ </div>
271
+ )}
272
+ </div>
273
+ )}
274
+ </div>
275
+ )
276
+ },
277
+ }
278
+
279
+ export const InfrastructureDashboard: Story = {
280
+ render: () => (
281
+ <div className="w-[950px] p-6 border rounded-lg">
282
+ <div className="flex justify-between items-start mb-4">
283
+ <div>
284
+ <h3 className="text-xl font-semibold">Production Infrastructure</h3>
285
+ <p className="text-sm text-muted-foreground">Real-time topology overview</p>
286
+ </div>
287
+ <div className="flex items-center gap-4 text-sm">
288
+ <div className="flex items-center gap-1.5">
289
+ <div className="w-2 h-2 rounded-full bg-green-500" />
290
+ <span>Healthy: 8</span>
291
+ </div>
292
+ <div className="flex items-center gap-1.5">
293
+ <div className="w-2 h-2 rounded-full bg-yellow-500" />
294
+ <span>Warning: 2</span>
295
+ </div>
296
+ <div className="flex items-center gap-1.5">
297
+ <div className="w-2 h-2 rounded-full bg-red-500" />
298
+ <span>Error: 1</span>
299
+ </div>
300
+ <div className="flex items-center gap-1.5">
301
+ <div className="w-2 h-2 rounded-full bg-gray-500" />
302
+ <span>Offline: 1</span>
303
+ </div>
304
+ </div>
305
+ </div>
306
+ <div className="h-[550px]">
307
+ <WakaNetworkTopology
308
+ nodes={complexTopologyNodes}
309
+ edges={complexTopologyEdges}
310
+ />
311
+ </div>
312
+ </div>
313
+ ),
314
+ }
315
+
316
+ export const NodeTypes: Story = {
317
+ render: () => {
318
+ const typeShowcaseNodes: NetworkNode[] = [
319
+ { id: 'server', label: 'Server', type: 'server', status: 'healthy', x: 100, y: 100 },
320
+ { id: 'database', label: 'Database', type: 'database', status: 'healthy', x: 250, y: 100 },
321
+ { id: 'loadbalancer', label: 'Load Balancer', type: 'loadbalancer', status: 'healthy', x: 400, y: 100 },
322
+ { id: 'firewall', label: 'Firewall', type: 'firewall', status: 'healthy', x: 550, y: 100 },
323
+ { id: 'cloud', label: 'Cloud', type: 'cloud', status: 'healthy', x: 175, y: 250 },
324
+ { id: 'client', label: 'Client', type: 'client', status: 'healthy', x: 325, y: 250 },
325
+ { id: 'router', label: 'Router', type: 'router', status: 'healthy', x: 475, y: 250 },
326
+ ]
327
+
328
+ return (
329
+ <div className="space-y-4">
330
+ <p className="text-sm text-muted-foreground">Available node types:</p>
331
+ <div className="w-[700px] h-[350px]">
332
+ <WakaNetworkTopology
333
+ nodes={typeShowcaseNodes}
334
+ edges={[]}
335
+ animated={false}
336
+ />
337
+ </div>
338
+ </div>
339
+ )
340
+ },
341
+ }
342
+
343
+ export const StatusShowcase: Story = {
344
+ render: () => {
345
+ const statusNodes: NetworkNode[] = [
346
+ { id: 'healthy', label: 'Healthy', type: 'server', status: 'healthy', x: 150, y: 150 },
347
+ { id: 'warning', label: 'Warning', type: 'server', status: 'warning', x: 350, y: 150 },
348
+ { id: 'error', label: 'Error', type: 'server', status: 'error', x: 550, y: 150 },
349
+ { id: 'offline', label: 'Offline', type: 'server', status: 'offline', x: 350, y: 300 },
350
+ ]
351
+
352
+ return (
353
+ <div className="space-y-4">
354
+ <p className="text-sm text-muted-foreground">Node status indicators:</p>
355
+ <div className="w-[700px] h-[400px]">
356
+ <WakaNetworkTopology
357
+ nodes={statusNodes}
358
+ edges={[]}
359
+ />
360
+ </div>
361
+ </div>
362
+ )
363
+ },
364
+ }
@@ -0,0 +1,290 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaNotifications, useNotifications } from './index'
3
+ import type { Notification } from './index'
4
+ import * as React from 'react'
5
+ import { CheckCircle, AlertTriangle, XCircle, Info, MessageSquare, UserPlus, ShoppingCart, CreditCard } from 'lucide-react'
6
+
7
+ const meta: Meta<typeof WakaNotifications> = {
8
+ title: 'Components/Display/WakaNotifications',
9
+ component: WakaNotifications,
10
+ parameters: {
11
+ layout: 'centered',
12
+ docs: {
13
+ description: {
14
+ component: 'A notification center component with popover, tabs, and action buttons for managing notifications.',
15
+ },
16
+ },
17
+ },
18
+ tags: ['autodocs'],
19
+ argTypes: {
20
+ showBadge: {
21
+ control: 'boolean',
22
+ description: 'Show unread count badge',
23
+ },
24
+ showTabs: {
25
+ control: 'boolean',
26
+ description: 'Show All/Unread tabs',
27
+ },
28
+ maxHeight: {
29
+ control: 'text',
30
+ description: 'Maximum height of notification list',
31
+ },
32
+ },
33
+ }
34
+
35
+ export default meta
36
+ type Story = StoryObj<typeof WakaNotifications>
37
+
38
+ const sampleNotifications: Notification[] = [
39
+ {
40
+ id: '1',
41
+ title: 'New comment on your post',
42
+ message: 'John Doe commented on your recent post about React patterns.',
43
+ type: 'info',
44
+ read: false,
45
+ timestamp: new Date(Date.now() - 5 * 60 * 1000), // 5 mins ago
46
+ icon: <MessageSquare className="h-5 w-5" />,
47
+ action: {
48
+ label: 'View comment',
49
+ onClick: () => console.log('View comment clicked'),
50
+ },
51
+ },
52
+ {
53
+ id: '2',
54
+ title: 'Payment successful',
55
+ message: 'Your payment of $99.00 has been processed successfully.',
56
+ type: 'success',
57
+ read: false,
58
+ timestamp: new Date(Date.now() - 30 * 60 * 1000), // 30 mins ago
59
+ icon: <CreditCard className="h-5 w-5" />,
60
+ },
61
+ {
62
+ id: '3',
63
+ title: 'New follower',
64
+ message: 'Sarah Miller started following you.',
65
+ type: 'info',
66
+ read: true,
67
+ timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000), // 2 hours ago
68
+ icon: <UserPlus className="h-5 w-5" />,
69
+ },
70
+ {
71
+ id: '4',
72
+ title: 'Low storage warning',
73
+ message: 'You are running low on storage space. Consider upgrading your plan.',
74
+ type: 'warning',
75
+ read: false,
76
+ timestamp: new Date(Date.now() - 5 * 60 * 60 * 1000), // 5 hours ago
77
+ icon: <AlertTriangle className="h-5 w-5" />,
78
+ action: {
79
+ label: 'Upgrade now',
80
+ onClick: () => console.log('Upgrade clicked'),
81
+ },
82
+ },
83
+ {
84
+ id: '5',
85
+ title: 'Build failed',
86
+ message: 'Your latest deployment to production failed. Check the logs for details.',
87
+ type: 'error',
88
+ read: true,
89
+ timestamp: new Date(Date.now() - 24 * 60 * 60 * 1000), // 1 day ago
90
+ icon: <XCircle className="h-5 w-5" />,
91
+ },
92
+ {
93
+ id: '6',
94
+ title: 'Order shipped',
95
+ message: 'Your order #12345 has been shipped and is on its way.',
96
+ type: 'success',
97
+ read: true,
98
+ timestamp: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000), // 2 days ago
99
+ icon: <ShoppingCart className="h-5 w-5" />,
100
+ },
101
+ ]
102
+
103
+ export const Default: Story = {
104
+ args: {},
105
+ render: (args) => {
106
+ const {
107
+ notifications,
108
+ markAsRead,
109
+ markAllAsRead,
110
+ deleteNotification,
111
+ deleteAllNotifications,
112
+ } = useNotifications(sampleNotifications)
113
+
114
+ return (
115
+ <div className="p-8">
116
+ <WakaNotifications
117
+ notifications={notifications}
118
+ onMarkAsRead={markAsRead}
119
+ onMarkAllAsRead={markAllAsRead}
120
+ onDelete={deleteNotification}
121
+ onDeleteAll={deleteAllNotifications}
122
+ onSettingsClick={() => console.log('Settings clicked')}
123
+ />
124
+ </div>
125
+ )
126
+ },
127
+ }
128
+
129
+ export const Empty: Story = {
130
+ render: () => (
131
+ <div className="p-8">
132
+ <WakaNotifications
133
+ notifications={[]}
134
+ emptyMessage="No notifications yet"
135
+ />
136
+ </div>
137
+ ),
138
+ }
139
+
140
+ export const WithoutTabs: Story = {
141
+ render: () => {
142
+ const {
143
+ notifications,
144
+ markAsRead,
145
+ deleteNotification,
146
+ } = useNotifications(sampleNotifications)
147
+
148
+ return (
149
+ <div className="p-8">
150
+ <WakaNotifications
151
+ notifications={notifications}
152
+ onMarkAsRead={markAsRead}
153
+ onDelete={deleteNotification}
154
+ showTabs={false}
155
+ />
156
+ </div>
157
+ )
158
+ },
159
+ }
160
+
161
+ export const WithoutBadge: Story = {
162
+ render: () => {
163
+ const { notifications } = useNotifications(sampleNotifications)
164
+
165
+ return (
166
+ <div className="p-8">
167
+ <WakaNotifications
168
+ notifications={notifications}
169
+ showBadge={false}
170
+ />
171
+ </div>
172
+ )
173
+ },
174
+ }
175
+
176
+ export const Interactive: Story = {
177
+ render: () => {
178
+ const {
179
+ notifications,
180
+ addNotification,
181
+ markAsRead,
182
+ markAllAsRead,
183
+ deleteNotification,
184
+ deleteAllNotifications,
185
+ unreadCount,
186
+ } = useNotifications([])
187
+
188
+ const addRandomNotification = () => {
189
+ const types: Notification['type'][] = ['info', 'success', 'warning', 'error']
190
+ const randomType = types[Math.floor(Math.random() * types.length)]
191
+ const icons = {
192
+ info: <Info className="h-5 w-5" />,
193
+ success: <CheckCircle className="h-5 w-5" />,
194
+ warning: <AlertTriangle className="h-5 w-5" />,
195
+ error: <XCircle className="h-5 w-5" />,
196
+ }
197
+
198
+ addNotification({
199
+ title: `New ${randomType} notification`,
200
+ message: `This is a sample ${randomType} notification message.`,
201
+ type: randomType,
202
+ icon: icons[randomType],
203
+ })
204
+ }
205
+
206
+ return (
207
+ <div className="flex flex-col items-center gap-4 p-8">
208
+ <div className="flex items-center gap-4">
209
+ <WakaNotifications
210
+ notifications={notifications}
211
+ onMarkAsRead={markAsRead}
212
+ onMarkAllAsRead={markAllAsRead}
213
+ onDelete={deleteNotification}
214
+ onDeleteAll={deleteAllNotifications}
215
+ />
216
+ <span className="text-sm text-muted-foreground">
217
+ {unreadCount} unread
218
+ </span>
219
+ </div>
220
+ <button
221
+ onClick={addRandomNotification}
222
+ className="px-4 py-2 bg-primary text-primary-foreground rounded-md text-sm"
223
+ >
224
+ Add Random Notification
225
+ </button>
226
+ </div>
227
+ )
228
+ },
229
+ }
230
+
231
+ export const ManyNotifications: Story = {
232
+ render: () => {
233
+ const manyNotifications: Notification[] = Array.from({ length: 20 }, (_, i) => ({
234
+ id: `notif-${i}`,
235
+ title: `Notification ${i + 1}`,
236
+ message: `This is notification number ${i + 1} with some sample content.`,
237
+ type: (['info', 'success', 'warning', 'error'] as const)[i % 4],
238
+ read: i > 5,
239
+ timestamp: new Date(Date.now() - i * 30 * 60 * 1000),
240
+ }))
241
+
242
+ const {
243
+ notifications,
244
+ markAsRead,
245
+ markAllAsRead,
246
+ deleteNotification,
247
+ } = useNotifications(manyNotifications)
248
+
249
+ return (
250
+ <div className="p-8">
251
+ <WakaNotifications
252
+ notifications={notifications}
253
+ onMarkAsRead={markAsRead}
254
+ onMarkAllAsRead={markAllAsRead}
255
+ onDelete={deleteNotification}
256
+ maxHeight="350px"
257
+ />
258
+ </div>
259
+ )
260
+ },
261
+ }
262
+
263
+ export const HeaderIntegration: Story = {
264
+ render: () => {
265
+ const { notifications, markAsRead, markAllAsRead, deleteNotification } = useNotifications(sampleNotifications)
266
+
267
+ return (
268
+ <div className="w-[600px] border rounded-lg">
269
+ <header className="flex items-center justify-between px-4 py-3 border-b">
270
+ <div className="font-semibold">My Application</div>
271
+ <div className="flex items-center gap-2">
272
+ <WakaNotifications
273
+ notifications={notifications}
274
+ onMarkAsRead={markAsRead}
275
+ onMarkAllAsRead={markAllAsRead}
276
+ onDelete={deleteNotification}
277
+ onSettingsClick={() => console.log('Settings')}
278
+ />
279
+ <div className="h-8 w-8 rounded-full bg-muted flex items-center justify-center text-sm">
280
+ JD
281
+ </div>
282
+ </div>
283
+ </header>
284
+ <div className="p-8 text-center text-muted-foreground">
285
+ Main content area
286
+ </div>
287
+ </div>
288
+ )
289
+ },
290
+ }