@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.
- package/dist/blocks/dashboard/index.d.ts +4 -1
- package/dist/blocks/empty-states/index.d.ts +4 -1
- package/dist/blocks/error-pages/index.d.ts +4 -1
- package/dist/blocks/index.d.ts +1 -1
- package/dist/blocks/landing/index.d.ts +4 -1
- package/dist/blocks/pricing/index.d.ts +5 -1
- package/dist/blocks/sidebar/index.d.ts +5 -1
- package/dist/index.cjs.js +130 -130
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +7905 -7856
- package/dist/stories/Button.d.ts +14 -0
- package/dist/stories/Button.stories.d.ts +8 -0
- package/dist/stories/Header.d.ts +11 -0
- package/dist/stories/Header.stories.d.ts +6 -0
- package/dist/stories/Page.d.ts +2 -0
- package/dist/stories/Page.stories.d.ts +6 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/link.d.ts +23 -0
- package/package.json +11 -3
- package/src/blocks/activity-timeline/ActivityTimeline.stories.tsx +460 -0
- package/src/blocks/apm-overview/APMOverview.stories.tsx +435 -0
- package/src/blocks/auth-2fa/Auth2FA.stories.tsx +308 -0
- package/src/blocks/calendar-view/CalendarView.stories.tsx +398 -0
- package/src/blocks/chat/Chat.stories.tsx +466 -0
- package/src/blocks/chat-interface/ChatInterface.stories.tsx +412 -0
- package/src/blocks/checkout-flow/CheckoutFlow.stories.tsx +408 -0
- package/src/blocks/cicd-builder/CICDBuilder.stories.tsx +499 -0
- package/src/blocks/cloud-cost-dashboard/CloudCostDashboard.stories.tsx +356 -0
- package/src/blocks/container-orchestrator/ContainerOrchestrator.stories.tsx +461 -0
- package/src/blocks/dashboard/Dashboard.stories.tsx +559 -0
- package/src/blocks/dashboard/index.tsx +68 -27
- package/src/blocks/dashboard-kpi/DashboardKPI.stories.tsx +422 -0
- package/src/blocks/database-admin/DatabaseAdmin.stories.tsx +393 -0
- package/src/blocks/deployment-dashboard/DeploymentDashboard.stories.tsx +457 -0
- package/src/blocks/empty-states/EmptyStates.stories.tsx +467 -0
- package/src/blocks/empty-states/index.tsx +26 -8
- package/src/blocks/error-pages/ErrorPages.stories.tsx +401 -0
- package/src/blocks/error-pages/index.tsx +26 -8
- package/src/blocks/faq/FAQ.stories.tsx +416 -0
- package/src/blocks/file-manager/FileManager.stories.tsx +413 -0
- package/src/blocks/footer/Footer.stories.tsx +328 -0
- package/src/blocks/gitops-sync-status/GitOpsSyncStatus.stories.tsx +529 -0
- package/src/blocks/header/WakaHeader.stories.tsx +455 -0
- package/src/blocks/headtab/Headtab.stories.tsx +369 -0
- package/src/blocks/i18n-editor/I18nEditor.stories.tsx +451 -0
- package/src/blocks/incident-manager/IncidentManager.stories.tsx +464 -0
- package/src/blocks/index.ts +1 -1
- package/src/blocks/infrastructure-map/InfrastructureMap.stories.tsx +533 -0
- package/src/blocks/kanban-board/KanbanBoard.stories.tsx +494 -0
- package/src/blocks/landing/WakaLanding.stories.tsx +449 -0
- package/src/blocks/landing/index.tsx +125 -66
- package/src/blocks/language-selector/LanguageSelector.stories.tsx +345 -0
- package/src/blocks/layout/Layout.stories.tsx +373 -0
- package/src/blocks/login/Login.stories.tsx +443 -0
- package/src/blocks/on-call-schedule/OnCallSchedule.stories.tsx +381 -0
- package/src/blocks/player-profile/PlayerProfile.stories.tsx +316 -0
- package/src/blocks/pricing/WakaPricing.stories.tsx +530 -0
- package/src/blocks/pricing/index.tsx +38 -4
- package/src/blocks/profile/Profile.stories.tsx +371 -0
- package/src/blocks/release-notes/ReleaseNotes.stories.tsx +431 -0
- package/src/blocks/settings/Settings.stories.tsx +520 -0
- package/src/blocks/sidebar/WakaSidebar.stories.tsx +513 -0
- package/src/blocks/sidebar/index.tsx +49 -20
- package/src/blocks/theme-creator-block/ThemeCreatorBlock.stories.tsx +370 -0
- package/src/blocks/user-management/UserManagement.stories.tsx +411 -0
- package/src/blocks/wizard/Wizard.stories.tsx +683 -0
- package/src/components/accordion/Accordion.stories.tsx +93 -0
- package/src/components/alert/Alert.stories.tsx +95 -0
- package/src/components/alert-dialog/AlertDialog.stories.tsx +126 -0
- package/src/components/aspect-ratio/AspectRatio.stories.tsx +118 -0
- package/src/components/avatar/Avatar.stories.tsx +104 -0
- package/src/components/button/Button.stories.tsx +12 -1
- package/src/components/calendar/Calendar.stories.tsx +102 -0
- package/src/components/card/Card.stories.tsx +125 -0
- package/src/components/checkbox/Checkbox.stories.tsx +100 -0
- package/src/components/code/Code.stories.tsx +402 -0
- package/src/components/collapsible/Collapsible.stories.tsx +123 -0
- package/src/components/command/Command.stories.tsx +207 -0
- package/src/components/context-menu/ContextMenu.stories.tsx +220 -0
- package/src/components/dialog/Dialog.stories.tsx +157 -0
- package/src/components/dropdown-menu/DropdownMenu.stories.tsx +225 -0
- package/src/components/form/Form.stories.tsx +413 -0
- package/src/components/hover-card/HoverCard.stories.tsx +148 -0
- package/src/components/input-otp/InputOTP.stories.tsx +255 -0
- package/src/components/label/Label.stories.tsx +68 -0
- package/src/components/menubar/Menubar.stories.tsx +278 -0
- package/src/components/navigation-menu/NavigationMenu.stories.tsx +202 -0
- package/src/components/popover/Popover.stories.tsx +199 -0
- package/src/components/progress/Progress.stories.tsx +104 -0
- package/src/components/radio-group/RadioGroup.stories.tsx +138 -0
- package/src/components/scroll-area/ScrollArea.stories.tsx +153 -0
- package/src/components/select/Select.stories.tsx +146 -0
- package/src/components/separator/Separator.stories.tsx +117 -0
- package/src/components/sheet/Sheet.stories.tsx +195 -0
- package/src/components/skeleton/Skeleton.stories.tsx +114 -0
- package/src/components/slider/Slider.stories.tsx +157 -0
- package/src/components/switch/Switch.stories.tsx +114 -0
- package/src/components/table/Table.stories.tsx +153 -0
- package/src/components/tabs/Tabs.stories.tsx +155 -0
- package/src/components/textarea/Textarea.stories.tsx +116 -0
- package/src/components/toast/Toast.stories.tsx +160 -0
- package/src/components/toggle/Toggle.stories.tsx +125 -0
- package/src/components/tooltip/Tooltip.stories.tsx +133 -0
- package/src/components/typography/Typography.stories.tsx +207 -0
- package/src/components/waka-3d-pie-chart/Waka3DPieChart.stories.tsx +308 -0
- package/src/components/waka-achievement-unlock/WakaAchievementUnlock.stories.tsx +353 -0
- package/src/components/waka-artifact-list/WakaArtifactList.stories.tsx +258 -0
- package/src/components/waka-autocomplete/WakaAutocomplete.stories.tsx +224 -0
- package/src/components/waka-badge-showcase/WakaBadgeShowcase.stories.tsx +269 -0
- package/src/components/waka-barcode/WakaBarcode.stories.tsx +227 -0
- package/src/components/waka-bottom-sheet/WakaBottomSheet.stories.tsx +408 -0
- package/src/components/waka-breadcrumb/WakaBreadcrumb.stories.tsx +237 -0
- package/src/components/waka-build-matrix/WakaBuildMatrix.stories.tsx +328 -0
- package/src/components/waka-carousel/WakaCarousel.stories.tsx +296 -0
- package/src/components/waka-charts/WakaCharts.stories.tsx +519 -0
- package/src/components/waka-color-picker/WakaColorPicker.stories.tsx +200 -0
- package/src/components/waka-combobox/WakaCombobox.stories.tsx +250 -0
- package/src/components/waka-container-list/WakaContainerList.stories.tsx +315 -0
- package/src/components/waka-contribution-graph/WakaContributionGraph.stories.tsx +354 -0
- package/src/components/waka-cost-breakdown/WakaCostBreakdown.stories.tsx +348 -0
- package/src/components/waka-daily-reward/WakaDailyReward.stories.tsx +365 -0
- package/src/components/waka-database-card/WakaDatabaseCard.stories.tsx +306 -0
- package/src/components/waka-date-range-picker/WakaDateRangePicker.stories.tsx +339 -0
- package/src/components/waka-datetime-picker/WakaDateTimePicker.stories.tsx +317 -0
- package/src/components/waka-deployment-lane/WakaDeploymentLane.stories.tsx +292 -0
- package/src/components/waka-dock/WakaDock.stories.tsx +332 -0
- package/src/components/waka-drawer/WakaDrawer.stories.tsx +437 -0
- package/src/components/waka-env-var-editor/WakaEnvVarEditor.stories.tsx +263 -0
- package/src/components/waka-error-shake/WakaErrorShake.stories.tsx +410 -0
- package/src/components/waka-file-upload/WakaFileUpload.stories.tsx +239 -0
- package/src/components/waka-flow-diagram/WakaFlowDiagram.stories.tsx +365 -0
- package/src/components/waka-funnel-chart/WakaFunnelChart.stories.tsx +281 -0
- package/src/components/waka-glow-card/WakaGlowCard.stories.tsx +274 -0
- package/src/components/waka-haptic-button/WakaHapticButton.stories.tsx +349 -0
- package/src/components/waka-health-pulse/WakaHealthPulse.stories.tsx +293 -0
- package/src/components/waka-heatmap/WakaHeatmap.stories.tsx +376 -0
- package/src/components/waka-image/WakaImage.stories.tsx +255 -0
- package/src/components/waka-incident-timeline/WakaIncidentTimeline.stories.tsx +300 -0
- package/src/components/waka-kanban/WakaKanban.stories.tsx +399 -0
- package/src/components/waka-kubernetes-overview/WakaKubernetesOverview.stories.tsx +281 -0
- package/src/components/waka-leaderboard/WakaLeaderboard.stories.tsx +300 -0
- package/src/components/waka-level-progress/WakaLevelProgress.stories.tsx +313 -0
- package/src/components/waka-loading-orbit/WakaLoadingOrbit.stories.tsx +413 -0
- package/src/components/waka-log-viewer/WakaLogViewer.stories.tsx +312 -0
- package/src/components/waka-loot-box/WakaLootBox.stories.tsx +374 -0
- package/src/components/waka-metric-sparkline/WakaMetricSparkline.stories.tsx +312 -0
- package/src/components/waka-migration-list/WakaMigrationList.stories.tsx +289 -0
- package/src/components/waka-modal/WakaModal.stories.tsx +434 -0
- package/src/components/waka-morph-button/WakaMorphButton.stories.tsx +405 -0
- package/src/components/waka-network-topology/WakaNetworkTopology.stories.tsx +364 -0
- package/src/components/waka-notifications/WakaNotifications.stories.tsx +290 -0
- package/src/components/waka-number-input/WakaNumberInput.stories.tsx +282 -0
- package/src/components/waka-pagination/WakaPagination.stories.tsx +328 -0
- package/src/components/waka-password-strength/WakaPasswordStrength.stories.tsx +318 -0
- package/src/components/waka-pipeline-view/WakaPipelineView.stories.tsx +386 -0
- package/src/components/waka-player-card/WakaPlayerCard.stories.tsx +333 -0
- package/src/components/waka-pod-card/WakaPodCard.stories.tsx +435 -0
- package/src/components/waka-qrcode/WakaQRCode.stories.tsx +232 -0
- package/src/components/waka-query-explain/WakaQueryExplain.stories.tsx +407 -0
- package/src/components/waka-quest-card/WakaQuestCard.stories.tsx +394 -0
- package/src/components/waka-quota-bar/WakaQuotaBar.stories.tsx +435 -0
- package/src/components/waka-radar-score/WakaRadarScore.stories.tsx +372 -0
- package/src/components/waka-resource-gauge/WakaResourceGauge.stories.tsx +366 -0
- package/src/components/waka-rich-text-editor/WakaRichTextEditor.stories.tsx +238 -0
- package/src/components/waka-sankey-diagram/WakaSankeyDiagram.stories.tsx +389 -0
- package/src/components/waka-scratch-card/WakaScratchCard.stories.tsx +388 -0
- package/src/components/waka-secret-card/WakaSecretCard.stories.tsx +314 -0
- package/src/components/waka-segmented-control/WakaSegmentedControl.stories.tsx +309 -0
- package/src/components/waka-server-rack/WakaServerRack.stories.tsx +382 -0
- package/src/components/waka-service-graph/WakaServiceGraph.stories.tsx +262 -0
- package/src/components/waka-skeleton-wave/WakaSkeletonWave.stories.tsx +321 -0
- package/src/components/waka-skill-tree/WakaSkillTree.stories.tsx +308 -0
- package/src/components/waka-spin-wheel/WakaSpinWheel.stories.tsx +368 -0
- package/src/components/waka-spinner/WakaSpinner.stories.tsx +156 -0
- package/src/components/waka-stat/WakaStat.stories.tsx +334 -0
- package/src/components/waka-status-matrix/WakaStatusMatrix.stories.tsx +331 -0
- package/src/components/waka-stepper/WakaStepper.stories.tsx +468 -0
- package/src/components/waka-streak-counter/WakaStreakCounter.stories.tsx +235 -0
- package/src/components/waka-success-explosion/WakaSuccessExplosion.stories.tsx +389 -0
- package/src/components/waka-tabs-morph/WakaTabsMorph.stories.tsx +471 -0
- package/src/components/waka-terminal-output/WakaTerminalOutput.stories.tsx +351 -0
- package/src/components/waka-test-report/WakaTestReport.stories.tsx +322 -0
- package/src/components/waka-tilt-card/WakaTiltCard.stories.tsx +300 -0
- package/src/components/waka-time-picker/WakaTimePicker.stories.tsx +227 -0
- package/src/components/waka-timeline/WakaTimeline.stories.tsx +383 -0
- package/src/components/waka-tournament-bracket/WakaTournamentBracket.stories.tsx +375 -0
- package/src/components/waka-trace-viewer/WakaTraceViewer.stories.tsx +445 -0
- package/src/components/waka-tree/WakaTree.stories.tsx +359 -0
- package/src/components/waka-treemap-chart/WakaTreemapChart.stories.tsx +378 -0
- package/src/components/waka-typewriter/WakaTypewriter.stories.tsx +366 -0
- package/src/components/waka-versus-card/WakaVersusCard.stories.tsx +530 -0
- package/src/components/waka-video/WakaVideo.stories.tsx +203 -0
- package/src/components/waka-virtual-list/WakaVirtualList.stories.tsx +273 -0
- 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
|
+
}
|