@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,318 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaPasswordStrength, WakaPasswordStrengthIndicator } from './index'
3
+ import * as React from 'react'
4
+
5
+ const meta: Meta<typeof WakaPasswordStrength> = {
6
+ title: 'Components/Forms/WakaPasswordStrength',
7
+ component: WakaPasswordStrength,
8
+ parameters: {
9
+ layout: 'centered',
10
+ docs: {
11
+ description: {
12
+ component: 'A password strength indicator with animated bar, checklist, and configurable requirements.',
13
+ },
14
+ },
15
+ },
16
+ tags: ['autodocs'],
17
+ argTypes: {
18
+ size: {
19
+ control: 'select',
20
+ options: ['sm', 'default', 'lg'],
21
+ description: 'Size of the component',
22
+ },
23
+ showInput: {
24
+ control: 'boolean',
25
+ description: 'Show password input',
26
+ },
27
+ showStrengthBar: {
28
+ control: 'boolean',
29
+ description: 'Show strength bar',
30
+ },
31
+ showChecklist: {
32
+ control: 'boolean',
33
+ description: 'Show requirements checklist',
34
+ },
35
+ showStrengthLabel: {
36
+ control: 'boolean',
37
+ description: 'Show strength label',
38
+ },
39
+ animated: {
40
+ control: 'boolean',
41
+ description: 'Enable animations',
42
+ },
43
+ },
44
+ }
45
+
46
+ export default meta
47
+ type Story = StoryObj<typeof WakaPasswordStrength>
48
+
49
+ export const Default: Story = {
50
+ render: function PasswordStrengthDemo() {
51
+ const [password, setPassword] = React.useState('')
52
+
53
+ return (
54
+ <div className="w-[350px]">
55
+ <WakaPasswordStrength
56
+ password={password}
57
+ onPasswordChange={setPassword}
58
+ label="Password"
59
+ placeholder="Enter password"
60
+ />
61
+ </div>
62
+ )
63
+ },
64
+ }
65
+
66
+ export const WithInitialValue: Story = {
67
+ render: function InitialValueDemo() {
68
+ const [password, setPassword] = React.useState('MyP@ssw0rd!')
69
+
70
+ return (
71
+ <div className="w-[350px]">
72
+ <WakaPasswordStrength
73
+ password={password}
74
+ onPasswordChange={setPassword}
75
+ label="Password"
76
+ />
77
+ </div>
78
+ )
79
+ },
80
+ }
81
+
82
+ export const BarOnly: Story = {
83
+ render: function BarOnlyDemo() {
84
+ const [password, setPassword] = React.useState('')
85
+
86
+ return (
87
+ <div className="w-[350px]">
88
+ <WakaPasswordStrength
89
+ password={password}
90
+ onPasswordChange={setPassword}
91
+ label="Password"
92
+ showChecklist={false}
93
+ />
94
+ </div>
95
+ )
96
+ },
97
+ }
98
+
99
+ export const ChecklistOnly: Story = {
100
+ render: function ChecklistOnlyDemo() {
101
+ const [password, setPassword] = React.useState('')
102
+
103
+ return (
104
+ <div className="w-[350px]">
105
+ <WakaPasswordStrength
106
+ password={password}
107
+ onPasswordChange={setPassword}
108
+ label="Password"
109
+ showStrengthBar={false}
110
+ />
111
+ </div>
112
+ )
113
+ },
114
+ }
115
+
116
+ export const CustomRequirements: Story = {
117
+ render: function CustomRequirementsDemo() {
118
+ const [password, setPassword] = React.useState('')
119
+
120
+ return (
121
+ <div className="w-[350px]">
122
+ <WakaPasswordStrength
123
+ password={password}
124
+ onPasswordChange={setPassword}
125
+ label="Password"
126
+ minLength={10}
127
+ requireUppercase
128
+ requireLowercase
129
+ requireNumber
130
+ requireSpecialChar={false}
131
+ customRequirements={[
132
+ {
133
+ key: 'noSpaces',
134
+ label: 'No spaces allowed',
135
+ validate: (p) => !p.includes(' '),
136
+ required: true,
137
+ },
138
+ ]}
139
+ />
140
+ </div>
141
+ )
142
+ },
143
+ }
144
+
145
+ export const Sizes: Story = {
146
+ render: function SizesDemo() {
147
+ const [password, setPassword] = React.useState('Test123!')
148
+
149
+ return (
150
+ <div className="space-y-8 w-[350px]">
151
+ <div>
152
+ <p className="text-sm text-muted-foreground mb-2">Small</p>
153
+ <WakaPasswordStrength
154
+ password={password}
155
+ onPasswordChange={setPassword}
156
+ size="sm"
157
+ />
158
+ </div>
159
+ <div>
160
+ <p className="text-sm text-muted-foreground mb-2">Default</p>
161
+ <WakaPasswordStrength
162
+ password={password}
163
+ onPasswordChange={setPassword}
164
+ size="default"
165
+ />
166
+ </div>
167
+ <div>
168
+ <p className="text-sm text-muted-foreground mb-2">Large</p>
169
+ <WakaPasswordStrength
170
+ password={password}
171
+ onPasswordChange={setPassword}
172
+ size="lg"
173
+ />
174
+ </div>
175
+ </div>
176
+ )
177
+ },
178
+ }
179
+
180
+ export const WithError: Story = {
181
+ render: function ErrorDemo() {
182
+ const [password, setPassword] = React.useState('weak')
183
+
184
+ return (
185
+ <div className="w-[350px]">
186
+ <WakaPasswordStrength
187
+ password={password}
188
+ onPasswordChange={setPassword}
189
+ label="Password"
190
+ error="Password does not meet requirements"
191
+ />
192
+ </div>
193
+ )
194
+ },
195
+ }
196
+
197
+ export const Disabled: Story = {
198
+ render: () => (
199
+ <div className="w-[350px]">
200
+ <WakaPasswordStrength
201
+ password="SecureP@ss123"
202
+ label="Password"
203
+ disabled
204
+ />
205
+ </div>
206
+ ),
207
+ }
208
+
209
+ export const NoAnimation: Story = {
210
+ render: function NoAnimationDemo() {
211
+ const [password, setPassword] = React.useState('')
212
+
213
+ return (
214
+ <div className="w-[350px]">
215
+ <WakaPasswordStrength
216
+ password={password}
217
+ onPasswordChange={setPassword}
218
+ label="Password"
219
+ animated={false}
220
+ />
221
+ </div>
222
+ )
223
+ },
224
+ }
225
+
226
+ export const IndicatorOnly: Story = {
227
+ render: function IndicatorOnlyDemo() {
228
+ const [password, setPassword] = React.useState('')
229
+
230
+ return (
231
+ <div className="w-[350px] space-y-4">
232
+ <div>
233
+ <label className="text-sm font-medium">Password</label>
234
+ <input
235
+ type="password"
236
+ value={password}
237
+ onChange={(e) => setPassword(e.target.value)}
238
+ className="w-full mt-1 px-3 py-2 border rounded-md"
239
+ placeholder="Enter password"
240
+ />
241
+ </div>
242
+ <WakaPasswordStrengthIndicator password={password} />
243
+ </div>
244
+ )
245
+ },
246
+ }
247
+
248
+ export const StrengthLevels: Story = {
249
+ render: () => (
250
+ <div className="w-[350px] space-y-6">
251
+ <div>
252
+ <p className="text-sm text-muted-foreground mb-2">Weak</p>
253
+ <WakaPasswordStrength password="abc" showInput={false} showChecklist={false} />
254
+ </div>
255
+ <div>
256
+ <p className="text-sm text-muted-foreground mb-2">Fair</p>
257
+ <WakaPasswordStrength password="abc12345" showInput={false} showChecklist={false} />
258
+ </div>
259
+ <div>
260
+ <p className="text-sm text-muted-foreground mb-2">Good</p>
261
+ <WakaPasswordStrength password="Abc12345" showInput={false} showChecklist={false} />
262
+ </div>
263
+ <div>
264
+ <p className="text-sm text-muted-foreground mb-2">Strong</p>
265
+ <WakaPasswordStrength password="Abc12345!" showInput={false} showChecklist={false} />
266
+ </div>
267
+ <div>
268
+ <p className="text-sm text-muted-foreground mb-2">Very Strong</p>
269
+ <WakaPasswordStrength password="Abc12345!@#$XYZ" showInput={false} showChecklist={false} />
270
+ </div>
271
+ </div>
272
+ ),
273
+ }
274
+
275
+ export const RegistrationForm: Story = {
276
+ render: function RegistrationDemo() {
277
+ const [password, setPassword] = React.useState('')
278
+ const [confirmPassword, setConfirmPassword] = React.useState('')
279
+ const [isValid, setIsValid] = React.useState(false)
280
+
281
+ return (
282
+ <div className="w-[400px] space-y-6 p-6 border rounded-lg">
283
+ <div>
284
+ <h3 className="font-semibold">Create Account</h3>
285
+ <p className="text-sm text-muted-foreground">Choose a strong password</p>
286
+ </div>
287
+
288
+ <WakaPasswordStrength
289
+ password={password}
290
+ onPasswordChange={setPassword}
291
+ label="Password"
292
+ onStrengthChange={(result) => setIsValid(result.isValid)}
293
+ />
294
+
295
+ <div className="space-y-2">
296
+ <label className="text-sm font-medium">Confirm Password</label>
297
+ <input
298
+ type="password"
299
+ value={confirmPassword}
300
+ onChange={(e) => setConfirmPassword(e.target.value)}
301
+ className="w-full px-3 py-2 border rounded-md"
302
+ placeholder="Confirm password"
303
+ />
304
+ {confirmPassword && password !== confirmPassword && (
305
+ <p className="text-sm text-destructive">Passwords do not match</p>
306
+ )}
307
+ </div>
308
+
309
+ <button
310
+ className="w-full py-2 px-4 bg-primary text-primary-foreground rounded-md disabled:opacity-50"
311
+ disabled={!isValid || password !== confirmPassword}
312
+ >
313
+ Create Account
314
+ </button>
315
+ </div>
316
+ )
317
+ },
318
+ }
@@ -0,0 +1,386 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaPipelineView } from './index'
3
+ import type { PipelineStage, StageStatus } from './index'
4
+ import * as React from 'react'
5
+
6
+ const completedPipeline: PipelineStage[] = [
7
+ { id: 'checkout', name: 'Checkout', status: 'success', duration: 3 },
8
+ { id: 'install', name: 'Install', status: 'success', duration: 45 },
9
+ { id: 'lint', name: 'Lint', status: 'success', duration: 12 },
10
+ { id: 'test', name: 'Test', status: 'success', duration: 89 },
11
+ { id: 'build', name: 'Build', status: 'success', duration: 34 },
12
+ { id: 'deploy', name: 'Deploy', status: 'success', duration: 28 },
13
+ ]
14
+
15
+ const runningPipeline: PipelineStage[] = [
16
+ { id: 'checkout', name: 'Checkout', status: 'success', duration: 3 },
17
+ { id: 'install', name: 'Install', status: 'success', duration: 45 },
18
+ { id: 'lint', name: 'Lint', status: 'success', duration: 12 },
19
+ { id: 'test', name: 'Test', status: 'running', duration: 42 },
20
+ { id: 'build', name: 'Build', status: 'pending' },
21
+ { id: 'deploy', name: 'Deploy', status: 'pending' },
22
+ ]
23
+
24
+ const failedPipeline: PipelineStage[] = [
25
+ { id: 'checkout', name: 'Checkout', status: 'success', duration: 3 },
26
+ { id: 'install', name: 'Install', status: 'success', duration: 45 },
27
+ { id: 'lint', name: 'Lint', status: 'success', duration: 12 },
28
+ { id: 'test', name: 'Test', status: 'failed', duration: 156 },
29
+ { id: 'build', name: 'Build', status: 'skipped' },
30
+ { id: 'deploy', name: 'Deploy', status: 'skipped' },
31
+ ]
32
+
33
+ const pipelineWithJobs: PipelineStage[] = [
34
+ { id: 'checkout', name: 'Checkout', status: 'success', duration: 3 },
35
+ {
36
+ id: 'test',
37
+ name: 'Test',
38
+ status: 'success',
39
+ duration: 156,
40
+ jobs: [
41
+ { id: 'unit', name: 'Unit Tests', status: 'success', duration: 45 },
42
+ { id: 'integration', name: 'Integration Tests', status: 'success', duration: 89 },
43
+ { id: 'e2e', name: 'E2E Tests', status: 'success', duration: 120 },
44
+ ],
45
+ },
46
+ {
47
+ id: 'build',
48
+ name: 'Build',
49
+ status: 'running',
50
+ jobs: [
51
+ { id: 'build-app', name: 'Build App', status: 'success', duration: 23 },
52
+ { id: 'build-docs', name: 'Build Docs', status: 'running' },
53
+ { id: 'build-storybook', name: 'Build Storybook', status: 'pending' },
54
+ ],
55
+ },
56
+ {
57
+ id: 'deploy',
58
+ name: 'Deploy',
59
+ status: 'pending',
60
+ jobs: [
61
+ { id: 'deploy-staging', name: 'Deploy Staging', status: 'pending' },
62
+ { id: 'deploy-prod', name: 'Deploy Production', status: 'pending' },
63
+ ],
64
+ },
65
+ ]
66
+
67
+ const meta: Meta<typeof WakaPipelineView> = {
68
+ title: 'Components/DevOps/WakaPipelineView',
69
+ component: WakaPipelineView,
70
+ parameters: {
71
+ layout: 'centered',
72
+ docs: {
73
+ description: {
74
+ component: 'A CI/CD pipeline visualization with stage status, duration, parallel jobs, retry support, and horizontal/vertical layouts.',
75
+ },
76
+ },
77
+ },
78
+ tags: ['autodocs'],
79
+ argTypes: {
80
+ variant: {
81
+ control: 'select',
82
+ options: ['horizontal', 'vertical'],
83
+ description: 'Layout variant',
84
+ },
85
+ size: {
86
+ control: 'select',
87
+ options: ['sm', 'md', 'lg'],
88
+ description: 'Size variant',
89
+ },
90
+ showDuration: {
91
+ control: 'boolean',
92
+ description: 'Show duration for each stage',
93
+ },
94
+ showJobs: {
95
+ control: 'boolean',
96
+ description: 'Show parallel jobs within stages',
97
+ },
98
+ animated: {
99
+ control: 'boolean',
100
+ description: 'Enable animations',
101
+ },
102
+ },
103
+ }
104
+
105
+ export default meta
106
+ type Story = StoryObj<typeof WakaPipelineView>
107
+
108
+ export const Default: Story = {
109
+ args: {
110
+ stages: completedPipeline,
111
+ variant: 'horizontal',
112
+ size: 'md',
113
+ showDuration: true,
114
+ showJobs: true,
115
+ animated: true,
116
+ },
117
+ render: (args) => <WakaPipelineView {...args} onStageClick={(id) => console.log('Clicked:', id)} />,
118
+ }
119
+
120
+ export const Running: Story = {
121
+ render: () => (
122
+ <WakaPipelineView
123
+ stages={runningPipeline}
124
+ onStageClick={(id) => console.log('Clicked:', id)}
125
+ />
126
+ ),
127
+ }
128
+
129
+ export const Failed: Story = {
130
+ render: () => (
131
+ <WakaPipelineView
132
+ stages={failedPipeline}
133
+ onStageClick={(id) => console.log('Clicked:', id)}
134
+ onRetry={(id) => console.log('Retry:', id)}
135
+ />
136
+ ),
137
+ }
138
+
139
+ export const WithJobs: Story = {
140
+ render: () => (
141
+ <WakaPipelineView
142
+ stages={pipelineWithJobs}
143
+ showJobs
144
+ onStageClick={(id) => console.log('Clicked:', id)}
145
+ />
146
+ ),
147
+ }
148
+
149
+ export const Vertical: Story = {
150
+ render: () => (
151
+ <div className="w-[400px]">
152
+ <WakaPipelineView
153
+ stages={runningPipeline}
154
+ variant="vertical"
155
+ onStageClick={(id) => console.log('Clicked:', id)}
156
+ />
157
+ </div>
158
+ ),
159
+ }
160
+
161
+ export const VerticalWithJobs: Story = {
162
+ render: () => (
163
+ <div className="w-[400px]">
164
+ <WakaPipelineView
165
+ stages={pipelineWithJobs}
166
+ variant="vertical"
167
+ showJobs
168
+ onStageClick={(id) => console.log('Clicked:', id)}
169
+ />
170
+ </div>
171
+ ),
172
+ }
173
+
174
+ export const Sizes: Story = {
175
+ render: () => (
176
+ <div className="space-y-8">
177
+ <div>
178
+ <p className="text-sm text-muted-foreground mb-4">Small</p>
179
+ <WakaPipelineView stages={completedPipeline} size="sm" />
180
+ </div>
181
+ <div>
182
+ <p className="text-sm text-muted-foreground mb-4">Medium (Default)</p>
183
+ <WakaPipelineView stages={completedPipeline} size="md" />
184
+ </div>
185
+ <div>
186
+ <p className="text-sm text-muted-foreground mb-4">Large</p>
187
+ <WakaPipelineView stages={completedPipeline} size="lg" />
188
+ </div>
189
+ </div>
190
+ ),
191
+ }
192
+
193
+ export const AllStatuses: Story = {
194
+ render: () => {
195
+ const allStatuses: PipelineStage[] = [
196
+ { id: '1', name: 'Pending', status: 'pending' },
197
+ { id: '2', name: 'Running', status: 'running' },
198
+ { id: '3', name: 'Success', status: 'success', duration: 30 },
199
+ { id: '4', name: 'Failed', status: 'failed', duration: 45 },
200
+ { id: '5', name: 'Skipped', status: 'skipped' },
201
+ { id: '6', name: 'Cancelled', status: 'cancelled' },
202
+ ]
203
+
204
+ return (
205
+ <div className="space-y-6">
206
+ <p className="text-sm text-muted-foreground">All possible stage statuses</p>
207
+ <WakaPipelineView stages={allStatuses} />
208
+ </div>
209
+ )
210
+ },
211
+ }
212
+
213
+ export const NoDuration: Story = {
214
+ render: () => (
215
+ <WakaPipelineView
216
+ stages={completedPipeline}
217
+ showDuration={false}
218
+ />
219
+ ),
220
+ }
221
+
222
+ export const NoAnimations: Story = {
223
+ render: () => (
224
+ <WakaPipelineView
225
+ stages={runningPipeline}
226
+ animated={false}
227
+ />
228
+ ),
229
+ }
230
+
231
+ export const Interactive: Story = {
232
+ render: () => {
233
+ const [stages, setStages] = React.useState<PipelineStage[]>([
234
+ { id: 'checkout', name: 'Checkout', status: 'pending' },
235
+ { id: 'install', name: 'Install', status: 'pending' },
236
+ { id: 'lint', name: 'Lint', status: 'pending' },
237
+ { id: 'test', name: 'Test', status: 'pending' },
238
+ { id: 'build', name: 'Build', status: 'pending' },
239
+ { id: 'deploy', name: 'Deploy', status: 'pending' },
240
+ ])
241
+ const [currentIndex, setCurrentIndex] = React.useState(-1)
242
+
243
+ const runPipeline = () => {
244
+ setStages(prev => prev.map(s => ({ ...s, status: 'pending' as StageStatus, duration: undefined })))
245
+ setCurrentIndex(0)
246
+ }
247
+
248
+ React.useEffect(() => {
249
+ if (currentIndex < 0 || currentIndex >= stages.length) return
250
+
251
+ // Set current stage to running
252
+ setStages(prev => prev.map((s, i) => ({
253
+ ...s,
254
+ status: i === currentIndex ? 'running' : i < currentIndex ? 'success' : 'pending',
255
+ })))
256
+
257
+ // Complete after random duration
258
+ const duration = Math.floor(Math.random() * 3000) + 1000
259
+ const timer = setTimeout(() => {
260
+ setStages(prev => prev.map((s, i) => ({
261
+ ...s,
262
+ status: i <= currentIndex ? 'success' : 'pending',
263
+ duration: i === currentIndex ? Math.floor(duration / 1000) : s.duration,
264
+ })))
265
+ setCurrentIndex(prev => prev + 1)
266
+ }, duration)
267
+
268
+ return () => clearTimeout(timer)
269
+ }, [currentIndex, stages.length])
270
+
271
+ const isRunning = currentIndex >= 0 && currentIndex < stages.length
272
+ const isComplete = currentIndex >= stages.length
273
+
274
+ return (
275
+ <div className="space-y-6">
276
+ <WakaPipelineView
277
+ stages={stages}
278
+ onStageClick={(id) => console.log('Clicked:', id)}
279
+ />
280
+
281
+ <div className="flex items-center gap-4">
282
+ <button
283
+ onClick={runPipeline}
284
+ disabled={isRunning}
285
+ className="px-4 py-2 text-sm rounded bg-primary text-primary-foreground disabled:opacity-50"
286
+ >
287
+ {isComplete ? 'Run Again' : isRunning ? 'Running...' : 'Start Pipeline'}
288
+ </button>
289
+ {isComplete && (
290
+ <span className="text-sm text-green-500">Pipeline completed successfully!</span>
291
+ )}
292
+ </div>
293
+ </div>
294
+ )
295
+ },
296
+ }
297
+
298
+ export const CICDDashboard: Story = {
299
+ render: () => {
300
+ const pipelines = [
301
+ {
302
+ name: 'main',
303
+ commit: 'fix: resolve memory leak in worker',
304
+ stages: completedPipeline,
305
+ time: '2 hours ago',
306
+ status: 'success' as const,
307
+ },
308
+ {
309
+ name: 'feature/auth',
310
+ commit: 'feat: add OAuth2 support',
311
+ stages: runningPipeline,
312
+ time: '5 minutes ago',
313
+ status: 'running' as const,
314
+ },
315
+ {
316
+ name: 'fix/api-timeout',
317
+ commit: 'fix: increase API timeout to 30s',
318
+ stages: failedPipeline,
319
+ time: '1 hour ago',
320
+ status: 'failed' as const,
321
+ },
322
+ ]
323
+
324
+ return (
325
+ <div className="w-[900px] p-6 rounded-xl border bg-card">
326
+ <h2 className="text-xl font-bold mb-6">CI/CD Pipelines</h2>
327
+
328
+ <div className="space-y-6">
329
+ {pipelines.map((pipeline) => (
330
+ <div key={pipeline.name} className="p-4 rounded-lg border bg-muted/20">
331
+ <div className="flex items-center justify-between mb-4">
332
+ <div className="flex items-center gap-3">
333
+ <div className={`w-2 h-2 rounded-full ${
334
+ pipeline.status === 'success' ? 'bg-green-500' :
335
+ pipeline.status === 'running' ? 'bg-blue-500 animate-pulse' :
336
+ 'bg-red-500'
337
+ }`} />
338
+ <span className="font-mono font-medium">{pipeline.name}</span>
339
+ <span className="text-sm text-muted-foreground truncate max-w-[300px]">
340
+ {pipeline.commit}
341
+ </span>
342
+ </div>
343
+ <span className="text-xs text-muted-foreground">{pipeline.time}</span>
344
+ </div>
345
+
346
+ <WakaPipelineView
347
+ stages={pipeline.stages}
348
+ size="sm"
349
+ onRetry={pipeline.status === 'failed' ? (id) => console.log('Retry:', id) : undefined}
350
+ />
351
+ </div>
352
+ ))}
353
+ </div>
354
+ </div>
355
+ )
356
+ },
357
+ }
358
+
359
+ export const LongPipeline: Story = {
360
+ render: () => {
361
+ const longPipeline: PipelineStage[] = [
362
+ { id: '1', name: 'Init', status: 'success', duration: 2 },
363
+ { id: '2', name: 'Checkout', status: 'success', duration: 5 },
364
+ { id: '3', name: 'Install', status: 'success', duration: 120 },
365
+ { id: '4', name: 'Lint', status: 'success', duration: 15 },
366
+ { id: '5', name: 'Type Check', status: 'success', duration: 25 },
367
+ { id: '6', name: 'Unit Tests', status: 'success', duration: 90 },
368
+ { id: '7', name: 'Integration', status: 'running', duration: 45 },
369
+ { id: '8', name: 'E2E Tests', status: 'pending' },
370
+ { id: '9', name: 'Build', status: 'pending' },
371
+ { id: '10', name: 'Docker', status: 'pending' },
372
+ { id: '11', name: 'Deploy Staging', status: 'pending' },
373
+ { id: '12', name: 'Smoke Tests', status: 'pending' },
374
+ { id: '13', name: 'Deploy Prod', status: 'pending' },
375
+ ]
376
+
377
+ return (
378
+ <div className="overflow-x-auto pb-4">
379
+ <WakaPipelineView
380
+ stages={longPipeline}
381
+ size="sm"
382
+ />
383
+ </div>
384
+ )
385
+ },
386
+ }