@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,312 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaMetricSparkline, useSparklineData } from './index'
3
+ import * as React from 'react'
4
+
5
+ const sampleData = [45, 52, 38, 65, 72, 58, 80, 75, 90, 85, 95, 88]
6
+ const trendingUpData = [20, 25, 30, 28, 35, 40, 38, 45, 50, 55, 60, 65]
7
+ const trendingDownData = [80, 75, 78, 70, 65, 68, 60, 55, 50, 45, 40, 35]
8
+ const volatileData = [50, 80, 30, 90, 40, 85, 25, 95, 35, 70, 45, 80]
9
+
10
+ const meta: Meta<typeof WakaMetricSparkline> = {
11
+ title: 'Components/Charts/WakaMetricSparkline',
12
+ component: WakaMetricSparkline,
13
+ parameters: {
14
+ layout: 'centered',
15
+ docs: {
16
+ description: {
17
+ component: 'A compact inline sparkline chart for displaying metric trends with support for line, bar, and area variants.',
18
+ },
19
+ },
20
+ },
21
+ tags: ['autodocs'],
22
+ argTypes: {
23
+ variant: {
24
+ control: 'select',
25
+ options: ['line', 'bar', 'area'],
26
+ description: 'Chart variant',
27
+ },
28
+ width: {
29
+ control: { type: 'range', min: 50, max: 200, step: 10 },
30
+ description: 'Width in pixels',
31
+ },
32
+ height: {
33
+ control: { type: 'range', min: 16, max: 48, step: 4 },
34
+ description: 'Height in pixels',
35
+ },
36
+ showValue: {
37
+ control: 'boolean',
38
+ description: 'Show current value',
39
+ },
40
+ showTrend: {
41
+ control: 'boolean',
42
+ description: 'Show trend indicator',
43
+ },
44
+ showMinMax: {
45
+ control: 'boolean',
46
+ description: 'Show min/max markers',
47
+ },
48
+ animated: {
49
+ control: 'boolean',
50
+ description: 'Enable animations',
51
+ },
52
+ },
53
+ }
54
+
55
+ export default meta
56
+ type Story = StoryObj<typeof WakaMetricSparkline>
57
+
58
+ export const Default: Story = {
59
+ args: {
60
+ data: sampleData,
61
+ },
62
+ render: (args) => <WakaMetricSparkline {...args} />,
63
+ }
64
+
65
+ export const Variants: Story = {
66
+ render: () => (
67
+ <div className="space-y-4">
68
+ <div className="flex items-center gap-4">
69
+ <span className="w-20 text-sm text-muted-foreground">Line:</span>
70
+ <WakaMetricSparkline data={sampleData} variant="line" />
71
+ </div>
72
+ <div className="flex items-center gap-4">
73
+ <span className="w-20 text-sm text-muted-foreground">Area:</span>
74
+ <WakaMetricSparkline data={sampleData} variant="area" />
75
+ </div>
76
+ <div className="flex items-center gap-4">
77
+ <span className="w-20 text-sm text-muted-foreground">Bar:</span>
78
+ <WakaMetricSparkline data={sampleData} variant="bar" />
79
+ </div>
80
+ </div>
81
+ ),
82
+ }
83
+
84
+ export const TrendIndicators: Story = {
85
+ render: () => (
86
+ <div className="space-y-4">
87
+ <div className="flex items-center gap-4">
88
+ <span className="w-32 text-sm text-muted-foreground">Trending Up:</span>
89
+ <WakaMetricSparkline data={trendingUpData} />
90
+ </div>
91
+ <div className="flex items-center gap-4">
92
+ <span className="w-32 text-sm text-muted-foreground">Trending Down:</span>
93
+ <WakaMetricSparkline data={trendingDownData} />
94
+ </div>
95
+ <div className="flex items-center gap-4">
96
+ <span className="w-32 text-sm text-muted-foreground">Volatile:</span>
97
+ <WakaMetricSparkline data={volatileData} />
98
+ </div>
99
+ </div>
100
+ ),
101
+ }
102
+
103
+ export const Sizes: Story = {
104
+ render: () => (
105
+ <div className="space-y-4">
106
+ <div className="flex items-center gap-4">
107
+ <span className="w-24 text-sm text-muted-foreground">Small:</span>
108
+ <WakaMetricSparkline data={sampleData} width={60} height={16} />
109
+ </div>
110
+ <div className="flex items-center gap-4">
111
+ <span className="w-24 text-sm text-muted-foreground">Medium:</span>
112
+ <WakaMetricSparkline data={sampleData} width={80} height={24} />
113
+ </div>
114
+ <div className="flex items-center gap-4">
115
+ <span className="w-24 text-sm text-muted-foreground">Large:</span>
116
+ <WakaMetricSparkline data={sampleData} width={120} height={32} />
117
+ </div>
118
+ <div className="flex items-center gap-4">
119
+ <span className="w-24 text-sm text-muted-foreground">Extra Large:</span>
120
+ <WakaMetricSparkline data={sampleData} width={160} height={40} />
121
+ </div>
122
+ </div>
123
+ ),
124
+ }
125
+
126
+ export const WithMinMax: Story = {
127
+ render: () => (
128
+ <div className="space-y-4">
129
+ <WakaMetricSparkline data={sampleData} showMinMax variant="line" width={120} height={32} />
130
+ <WakaMetricSparkline data={sampleData} showMinMax variant="area" width={120} height={32} />
131
+ <WakaMetricSparkline data={sampleData} showMinMax variant="bar" width={120} height={32} />
132
+ </div>
133
+ ),
134
+ }
135
+
136
+ export const CustomColors: Story = {
137
+ render: () => (
138
+ <div className="space-y-4">
139
+ <WakaMetricSparkline data={trendingUpData} color="#8b5cf6" />
140
+ <WakaMetricSparkline data={sampleData} color="#f59e0b" />
141
+ <WakaMetricSparkline data={trendingDownData} color="#06b6d4" />
142
+ </div>
143
+ ),
144
+ }
145
+
146
+ export const NoValue: Story = {
147
+ render: () => <WakaMetricSparkline data={sampleData} showValue={false} />,
148
+ }
149
+
150
+ export const NoTrend: Story = {
151
+ render: () => <WakaMetricSparkline data={trendingUpData} showTrend={false} />,
152
+ }
153
+
154
+ export const CustomFormatter: Story = {
155
+ render: () => (
156
+ <WakaMetricSparkline
157
+ data={sampleData}
158
+ value={95}
159
+ formatValue={(v) => `${v}%`}
160
+ />
161
+ ),
162
+ }
163
+
164
+ export const CurrencyFormat: Story = {
165
+ render: () => (
166
+ <WakaMetricSparkline
167
+ data={[1200, 1350, 1180, 1450, 1520, 1380, 1600, 1550, 1720, 1650]}
168
+ value={1650}
169
+ formatValue={(v) => `$${v.toLocaleString()}`}
170
+ />
171
+ ),
172
+ }
173
+
174
+ export const WithHook: Story = {
175
+ render: () => {
176
+ const { data, addPoint, reset, currentValue, previousValue } = useSparklineData({
177
+ initialData: [50, 55, 48, 60, 58],
178
+ maxPoints: 12,
179
+ })
180
+
181
+ const handleAdd = () => {
182
+ const newValue = Math.floor(Math.random() * 50) + 50
183
+ addPoint(newValue)
184
+ }
185
+
186
+ return (
187
+ <div className="space-y-4">
188
+ <div className="flex gap-2">
189
+ <button
190
+ onClick={handleAdd}
191
+ className="px-3 py-1 text-sm border rounded hover:bg-muted"
192
+ >
193
+ Add Random Point
194
+ </button>
195
+ <button
196
+ onClick={reset}
197
+ className="px-3 py-1 text-sm border rounded hover:bg-muted"
198
+ >
199
+ Reset
200
+ </button>
201
+ </div>
202
+ <WakaMetricSparkline
203
+ data={data}
204
+ value={currentValue}
205
+ previousValue={previousValue}
206
+ width={150}
207
+ height={32}
208
+ />
209
+ </div>
210
+ )
211
+ },
212
+ }
213
+
214
+ export const MetricsTable: Story = {
215
+ render: () => (
216
+ <div className="w-[500px] border rounded-lg overflow-hidden">
217
+ <table className="w-full text-sm">
218
+ <thead className="bg-muted">
219
+ <tr>
220
+ <th className="px-4 py-2 text-left font-medium">Metric</th>
221
+ <th className="px-4 py-2 text-right font-medium">Trend</th>
222
+ </tr>
223
+ </thead>
224
+ <tbody className="divide-y">
225
+ <tr>
226
+ <td className="px-4 py-3">Page Views</td>
227
+ <td className="px-4 py-3 text-right">
228
+ <WakaMetricSparkline
229
+ data={[1200, 1350, 1180, 1450, 1520, 1380, 1600]}
230
+ value={1600}
231
+ formatValue={(v) => `${(v / 1000).toFixed(1)}K`}
232
+ />
233
+ </td>
234
+ </tr>
235
+ <tr>
236
+ <td className="px-4 py-3">Conversion Rate</td>
237
+ <td className="px-4 py-3 text-right">
238
+ <WakaMetricSparkline
239
+ data={[2.1, 2.3, 2.0, 2.5, 2.8, 2.6, 3.1]}
240
+ value={3.1}
241
+ formatValue={(v) => `${v.toFixed(1)}%`}
242
+ />
243
+ </td>
244
+ </tr>
245
+ <tr>
246
+ <td className="px-4 py-3">Bounce Rate</td>
247
+ <td className="px-4 py-3 text-right">
248
+ <WakaMetricSparkline
249
+ data={[45, 42, 48, 40, 38, 41, 35]}
250
+ value={35}
251
+ formatValue={(v) => `${v}%`}
252
+ />
253
+ </td>
254
+ </tr>
255
+ <tr>
256
+ <td className="px-4 py-3">Avg Session</td>
257
+ <td className="px-4 py-3 text-right">
258
+ <WakaMetricSparkline
259
+ data={[180, 195, 170, 210, 225, 200, 240]}
260
+ value={240}
261
+ formatValue={(v) => `${Math.floor(v / 60)}:${(v % 60).toString().padStart(2, '0')}`}
262
+ />
263
+ </td>
264
+ </tr>
265
+ </tbody>
266
+ </table>
267
+ </div>
268
+ ),
269
+ }
270
+
271
+ export const KPICards: Story = {
272
+ render: () => (
273
+ <div className="flex gap-4">
274
+ <div className="p-4 border rounded-lg w-[180px]">
275
+ <p className="text-sm text-muted-foreground mb-1">Revenue</p>
276
+ <WakaMetricSparkline
277
+ data={[12000, 13500, 11800, 14500, 15200, 13800, 16000]}
278
+ value={16000}
279
+ formatValue={(v) => `$${(v / 1000).toFixed(0)}K`}
280
+ variant="area"
281
+ width={140}
282
+ height={28}
283
+ />
284
+ </div>
285
+ <div className="p-4 border rounded-lg w-[180px]">
286
+ <p className="text-sm text-muted-foreground mb-1">Users</p>
287
+ <WakaMetricSparkline
288
+ data={[850, 920, 880, 1050, 1120, 980, 1200]}
289
+ value={1200}
290
+ formatValue={(v) => v.toLocaleString()}
291
+ variant="line"
292
+ width={140}
293
+ height={28}
294
+ />
295
+ </div>
296
+ <div className="p-4 border rounded-lg w-[180px]">
297
+ <p className="text-sm text-muted-foreground mb-1">Orders</p>
298
+ <WakaMetricSparkline
299
+ data={[120, 145, 130, 165, 180, 155, 195]}
300
+ value={195}
301
+ variant="bar"
302
+ width={140}
303
+ height={28}
304
+ />
305
+ </div>
306
+ </div>
307
+ ),
308
+ }
309
+
310
+ export const NoAnimation: Story = {
311
+ render: () => <WakaMetricSparkline data={sampleData} animated={false} />,
312
+ }
@@ -0,0 +1,289 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaMigrationList, defaultMigrations } from './index'
3
+ import type { Migration, MigrationStatus } from './index'
4
+ import * as React from 'react'
5
+
6
+ const allAppliedMigrations: Migration[] = [
7
+ {
8
+ id: '1',
9
+ version: '20240101_001',
10
+ name: 'create_users_table',
11
+ status: 'applied',
12
+ appliedAt: new Date(Date.now() - 30 * 24 * 3600000),
13
+ duration: 125,
14
+ author: 'john.doe',
15
+ },
16
+ {
17
+ id: '2',
18
+ version: '20240115_001',
19
+ name: 'add_users_email_index',
20
+ status: 'applied',
21
+ appliedAt: new Date(Date.now() - 20 * 24 * 3600000),
22
+ duration: 45,
23
+ author: 'jane.smith',
24
+ },
25
+ {
26
+ id: '3',
27
+ version: '20240201_001',
28
+ name: 'create_posts_table',
29
+ status: 'applied',
30
+ appliedAt: new Date(Date.now() - 10 * 24 * 3600000),
31
+ duration: 230,
32
+ author: 'john.doe',
33
+ },
34
+ ]
35
+
36
+ const pendingMigrations: Migration[] = [
37
+ {
38
+ id: '1',
39
+ version: '20240301_001',
40
+ name: 'add_analytics_tracking',
41
+ description: 'Add analytics tracking columns to users',
42
+ status: 'pending',
43
+ author: 'data-team',
44
+ upScript: `ALTER TABLE users ADD COLUMN last_seen_at TIMESTAMP;
45
+ ALTER TABLE users ADD COLUMN session_count INTEGER DEFAULT 0;`,
46
+ downScript: `ALTER TABLE users DROP COLUMN session_count;
47
+ ALTER TABLE users DROP COLUMN last_seen_at;`,
48
+ },
49
+ {
50
+ id: '2',
51
+ version: '20240305_001',
52
+ name: 'create_notifications_table',
53
+ description: 'Create notifications table for in-app notifications',
54
+ status: 'pending',
55
+ author: 'jane.smith',
56
+ upScript: `CREATE TABLE notifications (
57
+ id SERIAL PRIMARY KEY,
58
+ user_id INTEGER REFERENCES users(id),
59
+ type VARCHAR(50) NOT NULL,
60
+ title VARCHAR(255),
61
+ body TEXT,
62
+ read_at TIMESTAMP,
63
+ created_at TIMESTAMP DEFAULT NOW()
64
+ );
65
+ CREATE INDEX idx_notifications_user ON notifications(user_id);`,
66
+ downScript: `DROP INDEX idx_notifications_user;
67
+ DROP TABLE notifications;`,
68
+ },
69
+ ]
70
+
71
+ const runningMigration: Migration[] = [
72
+ {
73
+ id: '1',
74
+ version: '20240220_001',
75
+ name: 'add_large_data_migration',
76
+ description: 'Migrating 10M rows - this may take a while',
77
+ status: 'running',
78
+ author: 'dba-team',
79
+ },
80
+ ]
81
+
82
+ const meta: Meta<typeof WakaMigrationList> = {
83
+ title: 'Components/DevOps/WakaMigrationList',
84
+ component: WakaMigrationList,
85
+ parameters: {
86
+ layout: 'centered',
87
+ docs: {
88
+ description: {
89
+ component: 'A database migration list with status filters, apply/rollback actions, script previews, and error display.',
90
+ },
91
+ },
92
+ },
93
+ tags: ['autodocs'],
94
+ argTypes: {
95
+ showScripts: {
96
+ control: 'boolean',
97
+ description: 'Show migration scripts',
98
+ },
99
+ },
100
+ }
101
+
102
+ export default meta
103
+ type Story = StoryObj<typeof WakaMigrationList>
104
+
105
+ export const Default: Story = {
106
+ args: {
107
+ migrations: defaultMigrations,
108
+ currentVersion: '20240125_001',
109
+ },
110
+ render: (args) => (
111
+ <div className="w-[800px] h-[600px]">
112
+ <WakaMigrationList
113
+ {...args}
114
+ onApply={(m) => console.log('Apply:', m.version)}
115
+ onRollback={(m) => console.log('Rollback:', m.version)}
116
+ onViewDetails={(m) => console.log('View:', m.version)}
117
+ />
118
+ </div>
119
+ ),
120
+ }
121
+
122
+ export const WithScripts: Story = {
123
+ render: () => (
124
+ <div className="w-[800px] h-[700px]">
125
+ <p className="text-sm text-muted-foreground mb-4">
126
+ Click the chevron to expand and view migration scripts
127
+ </p>
128
+ <WakaMigrationList
129
+ migrations={defaultMigrations}
130
+ currentVersion="20240125_001"
131
+ showScripts
132
+ onApply={(m) => console.log('Apply:', m.version)}
133
+ onRollback={(m) => console.log('Rollback:', m.version)}
134
+ />
135
+ </div>
136
+ ),
137
+ }
138
+
139
+ export const AllApplied: Story = {
140
+ render: () => (
141
+ <div className="w-[800px] h-[500px]">
142
+ <WakaMigrationList
143
+ migrations={allAppliedMigrations}
144
+ currentVersion="20240201_001"
145
+ title="All Migrations Applied"
146
+ onRollback={(m) => console.log('Rollback:', m.version)}
147
+ />
148
+ </div>
149
+ ),
150
+ }
151
+
152
+ export const PendingOnly: Story = {
153
+ render: () => (
154
+ <div className="w-[800px] h-[500px]">
155
+ <WakaMigrationList
156
+ migrations={pendingMigrations}
157
+ showScripts
158
+ title="Pending Migrations"
159
+ onApply={(m) => console.log('Apply:', m.version)}
160
+ />
161
+ </div>
162
+ ),
163
+ }
164
+
165
+ export const WithRunning: Story = {
166
+ render: () => (
167
+ <div className="w-[800px] h-[400px]">
168
+ <WakaMigrationList
169
+ migrations={[...runningMigration, ...allAppliedMigrations]}
170
+ currentVersion="20240201_001"
171
+ title="Migration In Progress"
172
+ />
173
+ </div>
174
+ ),
175
+ }
176
+
177
+ export const Interactive: Story = {
178
+ render: () => {
179
+ const [migrations, setMigrations] = React.useState<Migration[]>(defaultMigrations)
180
+ const [currentVersion, setCurrentVersion] = React.useState('20240125_001')
181
+
182
+ const handleApply = (migration: Migration) => {
183
+ setMigrations((prev) =>
184
+ prev.map((m) =>
185
+ m.id === migration.id
186
+ ? { ...m, status: 'running' as MigrationStatus }
187
+ : m
188
+ )
189
+ )
190
+
191
+ setTimeout(() => {
192
+ setMigrations((prev) =>
193
+ prev.map((m) =>
194
+ m.id === migration.id
195
+ ? {
196
+ ...m,
197
+ status: 'applied' as MigrationStatus,
198
+ appliedAt: new Date(),
199
+ duration: Math.floor(Math.random() * 500) + 50,
200
+ }
201
+ : m
202
+ )
203
+ )
204
+ setCurrentVersion(migration.version)
205
+ }, 2000)
206
+ }
207
+
208
+ const handleRollback = (migration: Migration) => {
209
+ setMigrations((prev) =>
210
+ prev.map((m) =>
211
+ m.id === migration.id
212
+ ? {
213
+ ...m,
214
+ status: 'rolled_back' as MigrationStatus,
215
+ rolledBackAt: new Date(),
216
+ }
217
+ : m
218
+ )
219
+ )
220
+
221
+ const appliedMigrations = migrations
222
+ .filter((m) => m.status === 'applied' && m.version < migration.version)
223
+ .sort((a, b) => b.version.localeCompare(a.version))
224
+
225
+ if (appliedMigrations.length > 0) {
226
+ setCurrentVersion(appliedMigrations[0].version)
227
+ }
228
+ }
229
+
230
+ return (
231
+ <div className="w-[800px] h-[600px]">
232
+ <p className="text-sm text-muted-foreground mb-4">
233
+ Interactive demo - try applying and rolling back migrations
234
+ </p>
235
+ <WakaMigrationList
236
+ migrations={migrations}
237
+ currentVersion={currentVersion}
238
+ showScripts
239
+ onApply={handleApply}
240
+ onRollback={handleRollback}
241
+ onViewDetails={(m) => alert(`Migration: ${m.name}\n\n${m.description || 'No description'}`)}
242
+ />
243
+ </div>
244
+ )
245
+ },
246
+ }
247
+
248
+ export const Empty: Story = {
249
+ render: () => (
250
+ <div className="w-[800px] h-[400px]">
251
+ <WakaMigrationList
252
+ migrations={[]}
253
+ title="No Migrations"
254
+ />
255
+ </div>
256
+ ),
257
+ }
258
+
259
+ export const DatabaseMigrationPanel: Story = {
260
+ render: () => (
261
+ <div className="p-6 rounded-xl border bg-card">
262
+ <div className="flex items-center justify-between mb-6">
263
+ <div>
264
+ <h2 className="text-xl font-bold">Database Migrations</h2>
265
+ <p className="text-sm text-muted-foreground">
266
+ production-db • PostgreSQL 15.4
267
+ </p>
268
+ </div>
269
+ <div className="flex items-center gap-2 text-sm">
270
+ <span className="text-muted-foreground">Current version:</span>
271
+ <code className="bg-muted px-2 py-0.5 rounded text-xs font-mono">
272
+ 20240125_001
273
+ </code>
274
+ </div>
275
+ </div>
276
+
277
+ <div className="w-[750px]">
278
+ <WakaMigrationList
279
+ migrations={defaultMigrations}
280
+ currentVersion="20240125_001"
281
+ showScripts
282
+ onApply={(m) => console.log('Apply:', m.version)}
283
+ onRollback={(m) => console.log('Rollback:', m.version)}
284
+ onViewDetails={(m) => console.log('View:', m.version)}
285
+ />
286
+ </div>
287
+ </div>
288
+ ),
289
+ }