@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,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
|
+
}
|