@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,262 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaServiceGraph, defaultServices, defaultConnections } from './index'
3
+ import type { ServiceNode, ServiceConnection, ServiceHealth, ServiceType } from './index'
4
+ import * as React from 'react'
5
+
6
+ const degradedServices: ServiceNode[] = [
7
+ { id: 'gateway', name: 'API Gateway', type: 'gateway', health: 'healthy', requestsPerSec: 1200, errorRate: 0.002 },
8
+ { id: 'auth', name: 'Auth Service', type: 'api', health: 'healthy', requestsPerSec: 400 },
9
+ { id: 'users', name: 'User Service', type: 'api', health: 'degraded', requestsPerSec: 280, errorRate: 0.08 },
10
+ { id: 'orders', name: 'Order Service', type: 'api', health: 'unhealthy', requestsPerSec: 50, errorRate: 0.25 },
11
+ { id: 'postgres', name: 'PostgreSQL', type: 'database', health: 'degraded' },
12
+ { id: 'redis', name: 'Redis', type: 'cache', health: 'healthy' },
13
+ ]
14
+
15
+ const degradedConnections: ServiceConnection[] = [
16
+ { source: 'gateway', target: 'auth', requestsPerSec: 400 },
17
+ { source: 'gateway', target: 'users', requestsPerSec: 280, errorRate: 0.05 },
18
+ { source: 'gateway', target: 'orders', requestsPerSec: 50, errorRate: 0.15 },
19
+ { source: 'auth', target: 'redis', requestsPerSec: 800 },
20
+ { source: 'users', target: 'postgres', requestsPerSec: 150, errorRate: 0.03 },
21
+ { source: 'orders', target: 'postgres', requestsPerSec: 30, errorRate: 0.1 },
22
+ ]
23
+
24
+ const simpleServices: ServiceNode[] = [
25
+ { id: 'frontend', name: 'Frontend', type: 'gateway', health: 'healthy' },
26
+ { id: 'backend', name: 'Backend API', type: 'api', health: 'healthy' },
27
+ { id: 'database', name: 'Database', type: 'database', health: 'healthy' },
28
+ ]
29
+
30
+ const simpleConnections: ServiceConnection[] = [
31
+ { source: 'frontend', target: 'backend' },
32
+ { source: 'backend', target: 'database' },
33
+ ]
34
+
35
+ const complexServices: ServiceNode[] = [
36
+ { id: 'gateway', name: 'Gateway', type: 'gateway', health: 'healthy', namespace: 'ingress', version: 'v2.0', replicas: 3, requestsPerSec: 5000, latencyP50: 12, latencyP99: 45 },
37
+ { id: 'auth', name: 'Auth', type: 'api', health: 'healthy', namespace: 'auth', replicas: 2, requestsPerSec: 1200 },
38
+ { id: 'users', name: 'Users', type: 'api', health: 'healthy', namespace: 'users', replicas: 3, requestsPerSec: 800 },
39
+ { id: 'orders', name: 'Orders', type: 'api', health: 'healthy', namespace: 'orders', replicas: 4, requestsPerSec: 600 },
40
+ { id: 'inventory', name: 'Inventory', type: 'api', health: 'healthy', namespace: 'inventory', replicas: 2, requestsPerSec: 400 },
41
+ { id: 'payments', name: 'Payments', type: 'api', health: 'healthy', namespace: 'payments', replicas: 2, requestsPerSec: 300 },
42
+ { id: 'notifications', name: 'Notifications', type: 'api', health: 'healthy', namespace: 'notifications', replicas: 1, requestsPerSec: 150 },
43
+ { id: 'postgres', name: 'PostgreSQL', type: 'database', health: 'healthy' },
44
+ { id: 'redis', name: 'Redis', type: 'cache', health: 'healthy' },
45
+ { id: 'rabbitmq', name: 'RabbitMQ', type: 'queue', health: 'healthy' },
46
+ { id: 'stripe', name: 'Stripe', type: 'external', health: 'healthy' },
47
+ { id: 'sendgrid', name: 'SendGrid', type: 'external', health: 'healthy' },
48
+ ]
49
+
50
+ const complexConnections: ServiceConnection[] = [
51
+ { source: 'gateway', target: 'auth', requestsPerSec: 1200 },
52
+ { source: 'gateway', target: 'users', requestsPerSec: 800 },
53
+ { source: 'gateway', target: 'orders', requestsPerSec: 600 },
54
+ { source: 'gateway', target: 'inventory', requestsPerSec: 400 },
55
+ { source: 'auth', target: 'postgres', requestsPerSec: 500 },
56
+ { source: 'auth', target: 'redis', requestsPerSec: 2000 },
57
+ { source: 'users', target: 'postgres', requestsPerSec: 350 },
58
+ { source: 'orders', target: 'postgres', requestsPerSec: 280 },
59
+ { source: 'orders', target: 'payments', requestsPerSec: 200 },
60
+ { source: 'orders', target: 'inventory', requestsPerSec: 400 },
61
+ { source: 'orders', target: 'rabbitmq', requestsPerSec: 150 },
62
+ { source: 'inventory', target: 'postgres', requestsPerSec: 180 },
63
+ { source: 'payments', target: 'stripe', requestsPerSec: 100 },
64
+ { source: 'payments', target: 'postgres', requestsPerSec: 150 },
65
+ { source: 'notifications', target: 'sendgrid', requestsPerSec: 50 },
66
+ { source: 'rabbitmq', target: 'notifications', requestsPerSec: 150 },
67
+ ]
68
+
69
+ const meta: Meta<typeof WakaServiceGraph> = {
70
+ title: 'Components/DevOps/WakaServiceGraph',
71
+ component: WakaServiceGraph,
72
+ parameters: {
73
+ layout: 'centered',
74
+ docs: {
75
+ description: {
76
+ component: 'A service mesh graph visualization with health indicators, connection metrics, zoom controls, and service type legend.',
77
+ },
78
+ },
79
+ },
80
+ tags: ['autodocs'],
81
+ argTypes: {
82
+ showMetrics: {
83
+ control: 'boolean',
84
+ description: 'Show metrics on service nodes',
85
+ },
86
+ },
87
+ }
88
+
89
+ export default meta
90
+ type Story = StoryObj<typeof WakaServiceGraph>
91
+
92
+ export const Default: Story = {
93
+ args: {
94
+ services: defaultServices,
95
+ connections: defaultConnections,
96
+ },
97
+ render: (args) => (
98
+ <div className="w-[700px] h-[500px]">
99
+ <WakaServiceGraph
100
+ {...args}
101
+ onServiceClick={(service) => console.log('Service click:', service)}
102
+ onConnectionClick={(connection) => console.log('Connection click:', connection)}
103
+ onRefresh={() => console.log('Refresh')}
104
+ />
105
+ </div>
106
+ ),
107
+ }
108
+
109
+ export const DegradedServices: Story = {
110
+ render: () => (
111
+ <div className="w-[700px] h-[500px]">
112
+ <p className="text-sm text-muted-foreground mb-4">
113
+ Service mesh with degraded and unhealthy services
114
+ </p>
115
+ <WakaServiceGraph
116
+ services={degradedServices}
117
+ connections={degradedConnections}
118
+ onServiceClick={(service) => console.log('Service click:', service)}
119
+ />
120
+ </div>
121
+ ),
122
+ }
123
+
124
+ export const SimpleGraph: Story = {
125
+ render: () => (
126
+ <div className="w-[600px] h-[400px]">
127
+ <p className="text-sm text-muted-foreground mb-4">
128
+ Simple 3-service architecture
129
+ </p>
130
+ <WakaServiceGraph
131
+ services={simpleServices}
132
+ connections={simpleConnections}
133
+ />
134
+ </div>
135
+ ),
136
+ }
137
+
138
+ export const ComplexMicroservices: Story = {
139
+ render: () => (
140
+ <div className="w-[800px] h-[600px]">
141
+ <p className="text-sm text-muted-foreground mb-4">
142
+ Complex microservices architecture
143
+ </p>
144
+ <WakaServiceGraph
145
+ services={complexServices}
146
+ connections={complexConnections}
147
+ onServiceClick={(service) => console.log('Service click:', service)}
148
+ onConnectionClick={(connection) => console.log('Connection click:', connection)}
149
+ onRefresh={() => console.log('Refresh')}
150
+ />
151
+ </div>
152
+ ),
153
+ }
154
+
155
+ export const NoMetrics: Story = {
156
+ render: () => (
157
+ <div className="w-[700px] h-[500px]">
158
+ <WakaServiceGraph
159
+ services={defaultServices}
160
+ connections={defaultConnections}
161
+ showMetrics={false}
162
+ />
163
+ </div>
164
+ ),
165
+ }
166
+
167
+ export const WithSelection: Story = {
168
+ render: () => {
169
+ const [selectedService, setSelectedService] = React.useState<string | undefined>('gateway')
170
+
171
+ return (
172
+ <div className="w-[700px] h-[500px]">
173
+ <p className="text-sm text-muted-foreground mb-4">
174
+ Selected: {selectedService || 'None'}
175
+ </p>
176
+ <WakaServiceGraph
177
+ services={defaultServices}
178
+ connections={defaultConnections}
179
+ selectedService={selectedService}
180
+ onServiceClick={(service) => setSelectedService(service.id)}
181
+ />
182
+ </div>
183
+ )
184
+ },
185
+ }
186
+
187
+ export const AllServiceTypes: Story = {
188
+ render: () => {
189
+ const typeServices: ServiceNode[] = [
190
+ { id: 'gateway', name: 'Gateway', type: 'gateway', health: 'healthy' },
191
+ { id: 'api', name: 'API Service', type: 'api', health: 'healthy' },
192
+ { id: 'database', name: 'Database', type: 'database', health: 'healthy' },
193
+ { id: 'cache', name: 'Cache', type: 'cache', health: 'healthy' },
194
+ { id: 'queue', name: 'Queue', type: 'queue', health: 'healthy' },
195
+ { id: 'external', name: 'External', type: 'external', health: 'healthy' },
196
+ ]
197
+
198
+ const typeConnections: ServiceConnection[] = [
199
+ { source: 'gateway', target: 'api' },
200
+ { source: 'api', target: 'database' },
201
+ { source: 'api', target: 'cache' },
202
+ { source: 'api', target: 'queue' },
203
+ { source: 'api', target: 'external' },
204
+ ]
205
+
206
+ return (
207
+ <div className="w-[700px] h-[500px]">
208
+ <p className="text-sm text-muted-foreground mb-4">
209
+ All service types demonstrated
210
+ </p>
211
+ <WakaServiceGraph
212
+ services={typeServices}
213
+ connections={typeConnections}
214
+ />
215
+ </div>
216
+ )
217
+ },
218
+ }
219
+
220
+ export const Empty: Story = {
221
+ render: () => (
222
+ <div className="w-[600px] h-[400px]">
223
+ <WakaServiceGraph
224
+ services={[]}
225
+ connections={[]}
226
+ />
227
+ </div>
228
+ ),
229
+ }
230
+
231
+ export const ObservabilityDashboard: Story = {
232
+ render: () => (
233
+ <div className="p-6 rounded-xl border bg-card">
234
+ <div className="flex items-center justify-between mb-6">
235
+ <div>
236
+ <h2 className="text-xl font-bold">Service Mesh Topology</h2>
237
+ <p className="text-sm text-muted-foreground">Production Environment</p>
238
+ </div>
239
+ <div className="flex items-center gap-4">
240
+ <div className="text-sm">
241
+ <span className="text-muted-foreground">Total RPS: </span>
242
+ <span className="font-medium">5,280</span>
243
+ </div>
244
+ <div className="text-sm">
245
+ <span className="text-muted-foreground">Error Rate: </span>
246
+ <span className="font-medium text-green-500">0.12%</span>
247
+ </div>
248
+ </div>
249
+ </div>
250
+
251
+ <div className="w-[750px]">
252
+ <WakaServiceGraph
253
+ services={defaultServices}
254
+ connections={defaultConnections}
255
+ onServiceClick={(service) => console.log('Service click:', service)}
256
+ onConnectionClick={(connection) => console.log('Connection click:', connection)}
257
+ onRefresh={() => console.log('Refresh')}
258
+ />
259
+ </div>
260
+ </div>
261
+ ),
262
+ }
@@ -0,0 +1,321 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaSkeletonWave, WakaSkeletonText, WakaSkeletonAvatar, WakaSkeletonCard, WakaSkeletonList, WakaSkeletonGrid } from './index'
3
+ import * as React from 'react'
4
+
5
+ const meta: Meta<typeof WakaSkeletonWave> = {
6
+ title: 'Components/Effects/WakaSkeletonWave',
7
+ component: WakaSkeletonWave,
8
+ parameters: {
9
+ layout: 'centered',
10
+ docs: {
11
+ description: {
12
+ component: 'A loading skeleton component with wave animation and various presets for common UI patterns.',
13
+ },
14
+ },
15
+ },
16
+ tags: ['autodocs'],
17
+ argTypes: {
18
+ preset: {
19
+ control: 'select',
20
+ options: ['text', 'avatar', 'card', 'list', 'thumbnail', 'button'],
21
+ description: 'Preset shape configuration',
22
+ },
23
+ rounded: {
24
+ control: 'select',
25
+ options: ['none', 'sm', 'md', 'lg', 'xl', 'full'],
26
+ description: 'Border radius',
27
+ },
28
+ speed: {
29
+ control: { type: 'range', min: 0.5, max: 3, step: 0.1 },
30
+ description: 'Animation speed in seconds',
31
+ },
32
+ animated: {
33
+ control: 'boolean',
34
+ description: 'Enable wave animation',
35
+ },
36
+ width: {
37
+ control: 'text',
38
+ description: 'Width (CSS value or number for px)',
39
+ },
40
+ height: {
41
+ control: 'text',
42
+ description: 'Height (CSS value or number for px)',
43
+ },
44
+ },
45
+ }
46
+
47
+ export default meta
48
+ type Story = StoryObj<typeof WakaSkeletonWave>
49
+
50
+ export const Default: Story = {
51
+ args: {
52
+ width: '100%',
53
+ height: 20,
54
+ },
55
+ render: (args) => (
56
+ <div className="space-y-4 w-[300px]">
57
+ <WakaSkeletonWave {...args} />
58
+ <WakaSkeletonWave {...args} width="80%" />
59
+ <WakaSkeletonWave {...args} width="60%" />
60
+ </div>
61
+ ),
62
+ }
63
+
64
+ export const Presets: Story = {
65
+ render: () => (
66
+ <div className="space-y-6">
67
+ <div className="flex items-center gap-4">
68
+ <span className="w-20 text-sm text-muted-foreground">Text:</span>
69
+ <WakaSkeletonWave preset="text" className="w-[200px]" />
70
+ </div>
71
+ <div className="flex items-center gap-4">
72
+ <span className="w-20 text-sm text-muted-foreground">Avatar:</span>
73
+ <WakaSkeletonWave preset="avatar" />
74
+ </div>
75
+ <div className="flex items-center gap-4">
76
+ <span className="w-20 text-sm text-muted-foreground">Button:</span>
77
+ <WakaSkeletonWave preset="button" />
78
+ </div>
79
+ <div className="flex items-center gap-4">
80
+ <span className="w-20 text-sm text-muted-foreground">Thumbnail:</span>
81
+ <WakaSkeletonWave preset="thumbnail" />
82
+ </div>
83
+ </div>
84
+ ),
85
+ }
86
+
87
+ export const TextLines: Story = {
88
+ render: () => (
89
+ <div className="w-[400px]">
90
+ <WakaSkeletonText lines={4} />
91
+ </div>
92
+ ),
93
+ }
94
+
95
+ export const AvatarSizes: Story = {
96
+ render: () => (
97
+ <div className="flex items-center gap-4">
98
+ <div className="text-center">
99
+ <WakaSkeletonAvatar size="sm" />
100
+ <p className="text-xs text-muted-foreground mt-2">sm</p>
101
+ </div>
102
+ <div className="text-center">
103
+ <WakaSkeletonAvatar size="md" />
104
+ <p className="text-xs text-muted-foreground mt-2">md</p>
105
+ </div>
106
+ <div className="text-center">
107
+ <WakaSkeletonAvatar size="lg" />
108
+ <p className="text-xs text-muted-foreground mt-2">lg</p>
109
+ </div>
110
+ <div className="text-center">
111
+ <WakaSkeletonAvatar size="xl" />
112
+ <p className="text-xs text-muted-foreground mt-2">xl</p>
113
+ </div>
114
+ </div>
115
+ ),
116
+ }
117
+
118
+ export const CardSkeleton: Story = {
119
+ render: () => (
120
+ <div className="w-[350px]">
121
+ <WakaSkeletonCard />
122
+ </div>
123
+ ),
124
+ }
125
+
126
+ export const CardVariations: Story = {
127
+ render: () => (
128
+ <div className="flex gap-6">
129
+ <div className="w-[280px]">
130
+ <p className="text-sm text-muted-foreground mb-2">With image</p>
131
+ <WakaSkeletonCard showImage showHeader />
132
+ </div>
133
+ <div className="w-[280px]">
134
+ <p className="text-sm text-muted-foreground mb-2">Without image</p>
135
+ <WakaSkeletonCard showImage={false} showHeader contentLines={4} />
136
+ </div>
137
+ <div className="w-[280px]">
138
+ <p className="text-sm text-muted-foreground mb-2">Minimal</p>
139
+ <WakaSkeletonCard showImage={false} showHeader={false} contentLines={3} />
140
+ </div>
141
+ </div>
142
+ ),
143
+ }
144
+
145
+ export const ListSkeleton: Story = {
146
+ render: () => (
147
+ <div className="w-[400px] border rounded-lg p-4">
148
+ <WakaSkeletonList items={5} />
149
+ </div>
150
+ ),
151
+ }
152
+
153
+ export const ListVariations: Story = {
154
+ render: () => (
155
+ <div className="flex gap-6">
156
+ <div className="w-[300px] border rounded-lg p-4">
157
+ <p className="text-sm text-muted-foreground mb-4">With actions</p>
158
+ <WakaSkeletonList items={3} showAction />
159
+ </div>
160
+ <div className="w-[300px] border rounded-lg p-4">
161
+ <p className="text-sm text-muted-foreground mb-4">Without avatar</p>
162
+ <WakaSkeletonList items={3} showAvatar={false} />
163
+ </div>
164
+ </div>
165
+ ),
166
+ }
167
+
168
+ export const GridSkeleton: Story = {
169
+ render: () => (
170
+ <div className="w-[500px]">
171
+ <WakaSkeletonGrid items={6} columns={3} />
172
+ </div>
173
+ ),
174
+ }
175
+
176
+ export const GridAspectRatios: Story = {
177
+ render: () => (
178
+ <div className="space-y-8">
179
+ <div>
180
+ <p className="text-sm text-muted-foreground mb-2">Square (1:1)</p>
181
+ <WakaSkeletonGrid items={4} columns={4} aspectRatio={1} className="w-[400px]" />
182
+ </div>
183
+ <div>
184
+ <p className="text-sm text-muted-foreground mb-2">Landscape (16:9)</p>
185
+ <WakaSkeletonGrid items={3} columns={3} aspectRatio={16 / 9} className="w-[500px]" />
186
+ </div>
187
+ <div>
188
+ <p className="text-sm text-muted-foreground mb-2">Portrait (3:4)</p>
189
+ <WakaSkeletonGrid items={4} columns={4} aspectRatio={3 / 4} className="w-[400px]" />
190
+ </div>
191
+ </div>
192
+ ),
193
+ }
194
+
195
+ export const AnimationSpeeds: Story = {
196
+ render: () => (
197
+ <div className="space-y-6 w-[300px]">
198
+ <div>
199
+ <p className="text-sm text-muted-foreground mb-2">Slow (2.5s)</p>
200
+ <WakaSkeletonWave width="100%" height={20} speed={2.5} />
201
+ </div>
202
+ <div>
203
+ <p className="text-sm text-muted-foreground mb-2">Normal (1.5s)</p>
204
+ <WakaSkeletonWave width="100%" height={20} speed={1.5} />
205
+ </div>
206
+ <div>
207
+ <p className="text-sm text-muted-foreground mb-2">Fast (0.8s)</p>
208
+ <WakaSkeletonWave width="100%" height={20} speed={0.8} />
209
+ </div>
210
+ <div>
211
+ <p className="text-sm text-muted-foreground mb-2">No animation</p>
212
+ <WakaSkeletonWave width="100%" height={20} animated={false} />
213
+ </div>
214
+ </div>
215
+ ),
216
+ }
217
+
218
+ export const RoundedVariants: Story = {
219
+ render: () => (
220
+ <div className="flex gap-4">
221
+ {(['none', 'sm', 'md', 'lg', 'xl', 'full'] as const).map((r) => (
222
+ <div key={r} className="text-center">
223
+ <WakaSkeletonWave width={80} height={80} rounded={r} />
224
+ <p className="text-xs text-muted-foreground mt-2">{r}</p>
225
+ </div>
226
+ ))}
227
+ </div>
228
+ ),
229
+ }
230
+
231
+ export const CustomColors: Story = {
232
+ render: () => (
233
+ <div className="space-y-6 w-[300px]">
234
+ <div>
235
+ <p className="text-sm text-muted-foreground mb-2">Default</p>
236
+ <WakaSkeletonWave width="100%" height={20} />
237
+ </div>
238
+ <div>
239
+ <p className="text-sm text-muted-foreground mb-2">Blue theme</p>
240
+ <WakaSkeletonWave
241
+ width="100%"
242
+ height={20}
243
+ baseColor="hsl(210 100% 95%)"
244
+ highlightColor="hsl(210 100% 80%)"
245
+ />
246
+ </div>
247
+ <div>
248
+ <p className="text-sm text-muted-foreground mb-2">Purple theme</p>
249
+ <WakaSkeletonWave
250
+ width="100%"
251
+ height={20}
252
+ baseColor="hsl(270 80% 95%)"
253
+ highlightColor="hsl(270 80% 75%)"
254
+ />
255
+ </div>
256
+ </div>
257
+ ),
258
+ }
259
+
260
+ export const ProfilePageSkeleton: Story = {
261
+ render: () => (
262
+ <div className="w-[400px] border rounded-lg p-6 space-y-6">
263
+ <div className="flex items-center gap-4">
264
+ <WakaSkeletonAvatar size="xl" />
265
+ <div className="flex-1 space-y-2">
266
+ <WakaSkeletonWave width="60%" height={24} />
267
+ <WakaSkeletonWave width="40%" height={16} />
268
+ </div>
269
+ </div>
270
+ <WakaSkeletonText lines={3} />
271
+ <div className="flex gap-4">
272
+ <WakaSkeletonWave width={100} height={36} rounded="md" />
273
+ <WakaSkeletonWave width={100} height={36} rounded="md" />
274
+ </div>
275
+ </div>
276
+ ),
277
+ }
278
+
279
+ export const CommentsSkeleton: Story = {
280
+ render: () => (
281
+ <div className="w-[500px] space-y-4">
282
+ {[1, 2, 3].map((i) => (
283
+ <div key={i} className="flex gap-3">
284
+ <WakaSkeletonAvatar size="md" />
285
+ <div className="flex-1 space-y-2">
286
+ <div className="flex items-center gap-2">
287
+ <WakaSkeletonWave width={120} height={14} />
288
+ <WakaSkeletonWave width={60} height={12} />
289
+ </div>
290
+ <WakaSkeletonText lines={2} randomWidths />
291
+ </div>
292
+ </div>
293
+ ))}
294
+ </div>
295
+ ),
296
+ }
297
+
298
+ export const TableSkeleton: Story = {
299
+ render: () => (
300
+ <div className="w-[600px] border rounded-lg overflow-hidden">
301
+ {/* Header */}
302
+ <div className="grid grid-cols-4 gap-4 p-4 bg-muted/50 border-b">
303
+ {[1, 2, 3, 4].map((i) => (
304
+ <WakaSkeletonWave key={i} width="80%" height={16} />
305
+ ))}
306
+ </div>
307
+ {/* Rows */}
308
+ {[1, 2, 3, 4, 5].map((row) => (
309
+ <div key={row} className="grid grid-cols-4 gap-4 p-4 border-b last:border-0">
310
+ {[1, 2, 3, 4].map((col) => (
311
+ <WakaSkeletonWave
312
+ key={col}
313
+ width={`${60 + Math.random() * 30}%`}
314
+ height={14}
315
+ />
316
+ ))}
317
+ </div>
318
+ ))}
319
+ </div>
320
+ ),
321
+ }