@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,224 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { WakaAutocomplete, type AutocompleteOption } from './index'
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof WakaAutocomplete> = {
|
|
6
|
+
title: 'Components/Forms/WakaAutocomplete',
|
|
7
|
+
component: WakaAutocomplete,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'centered',
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component: 'An autocomplete component with async search, multi-select, and creatable options.',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
tags: ['autodocs'],
|
|
17
|
+
argTypes: {
|
|
18
|
+
multiple: {
|
|
19
|
+
control: 'boolean',
|
|
20
|
+
description: 'Enable multi-select mode',
|
|
21
|
+
},
|
|
22
|
+
creatable: {
|
|
23
|
+
control: 'boolean',
|
|
24
|
+
description: 'Allow creating new options',
|
|
25
|
+
},
|
|
26
|
+
disabled: {
|
|
27
|
+
control: 'boolean',
|
|
28
|
+
description: 'Disable the component',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default meta
|
|
34
|
+
type Story = StoryObj<typeof WakaAutocomplete>
|
|
35
|
+
|
|
36
|
+
const fruits: AutocompleteOption[] = [
|
|
37
|
+
{ value: 'apple', label: 'Apple' },
|
|
38
|
+
{ value: 'banana', label: 'Banana' },
|
|
39
|
+
{ value: 'cherry', label: 'Cherry' },
|
|
40
|
+
{ value: 'date', label: 'Date' },
|
|
41
|
+
{ value: 'elderberry', label: 'Elderberry' },
|
|
42
|
+
{ value: 'fig', label: 'Fig' },
|
|
43
|
+
{ value: 'grape', label: 'Grape' },
|
|
44
|
+
{ value: 'honeydew', label: 'Honeydew' },
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
const groupedOptions: AutocompleteOption[] = [
|
|
48
|
+
{ value: 'apple', label: 'Apple', group: 'Fruits' },
|
|
49
|
+
{ value: 'banana', label: 'Banana', group: 'Fruits' },
|
|
50
|
+
{ value: 'cherry', label: 'Cherry', group: 'Fruits' },
|
|
51
|
+
{ value: 'carrot', label: 'Carrot', group: 'Vegetables' },
|
|
52
|
+
{ value: 'broccoli', label: 'Broccoli', group: 'Vegetables' },
|
|
53
|
+
{ value: 'spinach', label: 'Spinach', group: 'Vegetables' },
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
export const Default: Story = {
|
|
57
|
+
render: function AutocompleteDemo() {
|
|
58
|
+
const [value, setValue] = React.useState<string | string[] | null>(null)
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div className="w-[300px]">
|
|
62
|
+
<WakaAutocomplete
|
|
63
|
+
options={fruits}
|
|
64
|
+
value={value as string | undefined}
|
|
65
|
+
onChange={setValue}
|
|
66
|
+
placeholder="Select a fruit..."
|
|
67
|
+
label="Favorite Fruit"
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
)
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const Multiple: Story = {
|
|
75
|
+
render: function MultipleDemo() {
|
|
76
|
+
const [value, setValue] = React.useState<string | string[] | null>([])
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div className="w-[300px]">
|
|
80
|
+
<WakaAutocomplete
|
|
81
|
+
options={fruits}
|
|
82
|
+
value={value as string[]}
|
|
83
|
+
onChange={setValue}
|
|
84
|
+
multiple
|
|
85
|
+
placeholder="Select fruits..."
|
|
86
|
+
label="Favorite Fruits"
|
|
87
|
+
description="You can select multiple options"
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
90
|
+
)
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const Creatable: Story = {
|
|
95
|
+
render: function CreatableDemo() {
|
|
96
|
+
const [value, setValue] = React.useState<string | string[] | null>(null)
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<div className="w-[300px]">
|
|
100
|
+
<WakaAutocomplete
|
|
101
|
+
options={fruits}
|
|
102
|
+
value={value as string | undefined}
|
|
103
|
+
onChange={setValue}
|
|
104
|
+
creatable
|
|
105
|
+
placeholder="Select or create..."
|
|
106
|
+
label="Fruit"
|
|
107
|
+
description="Type to create a new option"
|
|
108
|
+
/>
|
|
109
|
+
</div>
|
|
110
|
+
)
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export const WithGroups: Story = {
|
|
115
|
+
render: function GroupedDemo() {
|
|
116
|
+
const [value, setValue] = React.useState<string | string[] | null>(null)
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div className="w-[300px]">
|
|
120
|
+
<WakaAutocomplete
|
|
121
|
+
options={groupedOptions}
|
|
122
|
+
value={value as string | undefined}
|
|
123
|
+
onChange={setValue}
|
|
124
|
+
placeholder="Select an item..."
|
|
125
|
+
label="Food"
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
|
+
)
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export const AsyncSearch: Story = {
|
|
133
|
+
render: function AsyncDemo() {
|
|
134
|
+
const [value, setValue] = React.useState<string | string[] | null>(null)
|
|
135
|
+
|
|
136
|
+
const searchFn = async (query: string): Promise<AutocompleteOption[]> => {
|
|
137
|
+
await new Promise((resolve) => setTimeout(resolve, 500))
|
|
138
|
+
return fruits.filter((f) =>
|
|
139
|
+
f.label.toLowerCase().includes(query.toLowerCase())
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<div className="w-[300px]">
|
|
145
|
+
<WakaAutocomplete
|
|
146
|
+
options={[]}
|
|
147
|
+
value={value as string | undefined}
|
|
148
|
+
onChange={setValue}
|
|
149
|
+
onSearch={searchFn}
|
|
150
|
+
placeholder="Search fruits..."
|
|
151
|
+
label="Async Search"
|
|
152
|
+
description="Type to search"
|
|
153
|
+
/>
|
|
154
|
+
</div>
|
|
155
|
+
)
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export const WithMaxSelections: Story = {
|
|
160
|
+
render: function MaxSelectionsDemo() {
|
|
161
|
+
const [value, setValue] = React.useState<string | string[] | null>([])
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<div className="w-[300px]">
|
|
165
|
+
<WakaAutocomplete
|
|
166
|
+
options={fruits}
|
|
167
|
+
value={value as string[]}
|
|
168
|
+
onChange={setValue}
|
|
169
|
+
multiple
|
|
170
|
+
maxSelections={3}
|
|
171
|
+
placeholder="Select up to 3 fruits..."
|
|
172
|
+
label="Limited Selection"
|
|
173
|
+
description="Maximum 3 selections allowed"
|
|
174
|
+
/>
|
|
175
|
+
</div>
|
|
176
|
+
)
|
|
177
|
+
},
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export const WithError: Story = {
|
|
181
|
+
render: function ErrorDemo() {
|
|
182
|
+
const [value, setValue] = React.useState<string | string[] | null>(null)
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<div className="w-[300px]">
|
|
186
|
+
<WakaAutocomplete
|
|
187
|
+
options={fruits}
|
|
188
|
+
value={value as string | undefined}
|
|
189
|
+
onChange={setValue}
|
|
190
|
+
placeholder="Select a fruit..."
|
|
191
|
+
label="Required Field"
|
|
192
|
+
error="This field is required"
|
|
193
|
+
/>
|
|
194
|
+
</div>
|
|
195
|
+
)
|
|
196
|
+
},
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export const Disabled: Story = {
|
|
200
|
+
render: () => (
|
|
201
|
+
<div className="w-[300px]">
|
|
202
|
+
<WakaAutocomplete
|
|
203
|
+
options={fruits}
|
|
204
|
+
value="apple"
|
|
205
|
+
disabled
|
|
206
|
+
placeholder="Select a fruit..."
|
|
207
|
+
label="Disabled"
|
|
208
|
+
/>
|
|
209
|
+
</div>
|
|
210
|
+
),
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export const Loading: Story = {
|
|
214
|
+
render: () => (
|
|
215
|
+
<div className="w-[300px]">
|
|
216
|
+
<WakaAutocomplete
|
|
217
|
+
options={fruits}
|
|
218
|
+
loading
|
|
219
|
+
placeholder="Loading..."
|
|
220
|
+
label="Loading State"
|
|
221
|
+
/>
|
|
222
|
+
</div>
|
|
223
|
+
),
|
|
224
|
+
}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { WakaBadgeShowcase } from './index'
|
|
3
|
+
import type { Badge } from './index'
|
|
4
|
+
import * as React from 'react'
|
|
5
|
+
import { Trophy, Star, Flame, Crown, Gem, Shield, Zap, Target, Heart, Award } from 'lucide-react'
|
|
6
|
+
|
|
7
|
+
const sampleBadges: Badge[] = [
|
|
8
|
+
{ id: '1', name: 'First Steps', description: 'Complete the tutorial', icon: <Star className="h-6 w-6" />, rarity: 'common', unlockedAt: new Date() },
|
|
9
|
+
{ id: '2', name: 'Champion', description: 'Win 10 games', icon: <Trophy className="h-6 w-6" />, rarity: 'rare', unlockedAt: new Date() },
|
|
10
|
+
{ id: '3', name: 'Fire Starter', description: 'Get a 7-day streak', icon: <Flame className="h-6 w-6" />, rarity: 'rare', unlockedAt: new Date() },
|
|
11
|
+
{ id: '4', name: 'Gem Collector', description: 'Collect 100 gems', icon: <Gem className="h-6 w-6" />, rarity: 'epic', unlockedAt: new Date() },
|
|
12
|
+
{ id: '5', name: 'Guardian', description: 'Help 50 players', icon: <Shield className="h-6 w-6" />, rarity: 'epic', unlockedAt: new Date() },
|
|
13
|
+
{ id: '6', name: 'Legend', description: 'Reach max level', icon: <Crown className="h-6 w-6" />, rarity: 'legendary', unlockedAt: new Date() },
|
|
14
|
+
{ id: '7', name: 'Speed Demon', description: 'Complete speedrun', icon: <Zap className="h-6 w-6" />, rarity: 'legendary' },
|
|
15
|
+
{ id: '8', name: 'Sharpshooter', description: '100% accuracy', icon: <Target className="h-6 w-6" />, rarity: 'epic' },
|
|
16
|
+
{ id: '9', name: 'Beloved', description: 'Get 1000 likes', icon: <Heart className="h-6 w-6" />, rarity: 'rare' },
|
|
17
|
+
{ id: '10', name: 'Elite', description: 'Top 1% player', icon: <Award className="h-6 w-6" />, rarity: 'legendary' },
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
const meta: Meta<typeof WakaBadgeShowcase> = {
|
|
21
|
+
title: 'Components/Gamification/WakaBadgeShowcase',
|
|
22
|
+
component: WakaBadgeShowcase,
|
|
23
|
+
parameters: {
|
|
24
|
+
layout: 'centered',
|
|
25
|
+
docs: {
|
|
26
|
+
description: {
|
|
27
|
+
component: 'A badge showcase with grid/list/showcase modes, rarity tiers, and hover effects.',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
tags: ['autodocs'],
|
|
32
|
+
argTypes: {
|
|
33
|
+
variant: {
|
|
34
|
+
control: 'select',
|
|
35
|
+
options: ['grid', 'list', 'showcase'],
|
|
36
|
+
description: 'Display variant',
|
|
37
|
+
},
|
|
38
|
+
size: {
|
|
39
|
+
control: 'select',
|
|
40
|
+
options: ['sm', 'md', 'lg'],
|
|
41
|
+
description: 'Size variant',
|
|
42
|
+
},
|
|
43
|
+
columns: {
|
|
44
|
+
control: { type: 'number', min: 2, max: 6 },
|
|
45
|
+
description: 'Number of columns (grid mode)',
|
|
46
|
+
},
|
|
47
|
+
showLocked: {
|
|
48
|
+
control: 'boolean',
|
|
49
|
+
description: 'Show locked badges',
|
|
50
|
+
},
|
|
51
|
+
animated: {
|
|
52
|
+
control: 'boolean',
|
|
53
|
+
description: 'Enable animations',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default meta
|
|
59
|
+
type Story = StoryObj<typeof WakaBadgeShowcase>
|
|
60
|
+
|
|
61
|
+
export const Default: Story = {
|
|
62
|
+
args: {
|
|
63
|
+
badges: sampleBadges.slice(0, 6),
|
|
64
|
+
variant: 'grid',
|
|
65
|
+
size: 'md',
|
|
66
|
+
columns: 3,
|
|
67
|
+
showLocked: false,
|
|
68
|
+
animated: true,
|
|
69
|
+
},
|
|
70
|
+
render: (args) => (
|
|
71
|
+
<div className="w-[500px]">
|
|
72
|
+
<WakaBadgeShowcase {...args} />
|
|
73
|
+
</div>
|
|
74
|
+
),
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const Variants: Story = {
|
|
78
|
+
render: () => (
|
|
79
|
+
<div className="space-y-8">
|
|
80
|
+
<div>
|
|
81
|
+
<p className="text-sm text-muted-foreground mb-2">Grid</p>
|
|
82
|
+
<div className="w-[400px]">
|
|
83
|
+
<WakaBadgeShowcase badges={sampleBadges.slice(0, 6)} variant="grid" />
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
<div>
|
|
87
|
+
<p className="text-sm text-muted-foreground mb-2">List</p>
|
|
88
|
+
<div className="w-[350px]">
|
|
89
|
+
<WakaBadgeShowcase badges={sampleBadges.slice(0, 4)} variant="list" />
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
<div>
|
|
93
|
+
<p className="text-sm text-muted-foreground mb-2">Showcase</p>
|
|
94
|
+
<div className="w-[500px]">
|
|
95
|
+
<WakaBadgeShowcase badges={sampleBadges.slice(0, 5)} variant="showcase" />
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
),
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const Sizes: Story = {
|
|
103
|
+
render: () => (
|
|
104
|
+
<div className="space-y-8">
|
|
105
|
+
<div>
|
|
106
|
+
<p className="text-sm text-muted-foreground mb-2">Small</p>
|
|
107
|
+
<div className="w-[300px]">
|
|
108
|
+
<WakaBadgeShowcase badges={sampleBadges.slice(0, 6)} size="sm" columns={3} />
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
<div>
|
|
112
|
+
<p className="text-sm text-muted-foreground mb-2">Medium (Default)</p>
|
|
113
|
+
<div className="w-[400px]">
|
|
114
|
+
<WakaBadgeShowcase badges={sampleBadges.slice(0, 6)} size="md" columns={3} />
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
<div>
|
|
118
|
+
<p className="text-sm text-muted-foreground mb-2">Large</p>
|
|
119
|
+
<div className="w-[500px]">
|
|
120
|
+
<WakaBadgeShowcase badges={sampleBadges.slice(0, 6)} size="lg" columns={3} />
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
),
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const RarityTiers: Story = {
|
|
128
|
+
render: () => {
|
|
129
|
+
const badgesByRarity = {
|
|
130
|
+
common: sampleBadges.filter((b) => b.rarity === 'common'),
|
|
131
|
+
rare: sampleBadges.filter((b) => b.rarity === 'rare'),
|
|
132
|
+
epic: sampleBadges.filter((b) => b.rarity === 'epic'),
|
|
133
|
+
legendary: sampleBadges.filter((b) => b.rarity === 'legendary'),
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<div className="w-[500px] space-y-6">
|
|
138
|
+
<div>
|
|
139
|
+
<div className="flex items-center gap-2 mb-2">
|
|
140
|
+
<div className="h-2 w-2 rounded-full bg-slate-400" />
|
|
141
|
+
<span className="text-sm font-medium text-slate-500">Common</span>
|
|
142
|
+
</div>
|
|
143
|
+
<WakaBadgeShowcase badges={badgesByRarity.common} columns={4} size="sm" />
|
|
144
|
+
</div>
|
|
145
|
+
<div>
|
|
146
|
+
<div className="flex items-center gap-2 mb-2">
|
|
147
|
+
<div className="h-2 w-2 rounded-full bg-blue-400" />
|
|
148
|
+
<span className="text-sm font-medium text-blue-500">Rare</span>
|
|
149
|
+
</div>
|
|
150
|
+
<WakaBadgeShowcase badges={badgesByRarity.rare} columns={4} size="sm" />
|
|
151
|
+
</div>
|
|
152
|
+
<div>
|
|
153
|
+
<div className="flex items-center gap-2 mb-2">
|
|
154
|
+
<div className="h-2 w-2 rounded-full bg-purple-400" />
|
|
155
|
+
<span className="text-sm font-medium text-purple-500">Epic</span>
|
|
156
|
+
</div>
|
|
157
|
+
<WakaBadgeShowcase badges={badgesByRarity.epic} columns={4} size="sm" />
|
|
158
|
+
</div>
|
|
159
|
+
<div>
|
|
160
|
+
<div className="flex items-center gap-2 mb-2">
|
|
161
|
+
<div className="h-2 w-2 rounded-full bg-amber-400" />
|
|
162
|
+
<span className="text-sm font-medium text-amber-500">Legendary</span>
|
|
163
|
+
</div>
|
|
164
|
+
<WakaBadgeShowcase badges={badgesByRarity.legendary} columns={4} size="sm" />
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
)
|
|
168
|
+
},
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export const WithLockedBadges: Story = {
|
|
172
|
+
render: () => (
|
|
173
|
+
<div className="w-[500px]">
|
|
174
|
+
<WakaBadgeShowcase badges={sampleBadges} showLocked />
|
|
175
|
+
</div>
|
|
176
|
+
),
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export const Interactive: Story = {
|
|
180
|
+
render: () => {
|
|
181
|
+
const [selectedBadge, setSelectedBadge] = React.useState<Badge | null>(null)
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
<div className="w-[500px] space-y-4">
|
|
185
|
+
<WakaBadgeShowcase
|
|
186
|
+
badges={sampleBadges.slice(0, 6)}
|
|
187
|
+
onBadgeClick={setSelectedBadge}
|
|
188
|
+
/>
|
|
189
|
+
|
|
190
|
+
{selectedBadge && (
|
|
191
|
+
<div className="p-4 rounded-lg border bg-muted/30">
|
|
192
|
+
<div className="flex items-center gap-3">
|
|
193
|
+
<div className={`p-2 rounded-lg ${
|
|
194
|
+
selectedBadge.rarity === 'legendary' ? 'bg-amber-500/20 text-amber-500' :
|
|
195
|
+
selectedBadge.rarity === 'epic' ? 'bg-purple-500/20 text-purple-500' :
|
|
196
|
+
selectedBadge.rarity === 'rare' ? 'bg-blue-500/20 text-blue-500' :
|
|
197
|
+
'bg-slate-500/20 text-slate-500'
|
|
198
|
+
}`}>
|
|
199
|
+
{selectedBadge.icon}
|
|
200
|
+
</div>
|
|
201
|
+
<div>
|
|
202
|
+
<h4 className="font-semibold">{selectedBadge.name}</h4>
|
|
203
|
+
<p className="text-sm text-muted-foreground">{selectedBadge.description}</p>
|
|
204
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
205
|
+
{selectedBadge.unlockedAt ? `Unlocked ${selectedBadge.unlockedAt.toLocaleDateString()}` : 'Not unlocked'}
|
|
206
|
+
</p>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
)}
|
|
211
|
+
</div>
|
|
212
|
+
)
|
|
213
|
+
},
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export const ProfileShowcase: Story = {
|
|
217
|
+
render: () => (
|
|
218
|
+
<div className="w-[450px] p-6 rounded-xl border bg-card">
|
|
219
|
+
<div className="flex items-center gap-4 mb-6">
|
|
220
|
+
<div className="w-16 h-16 rounded-full bg-gradient-to-br from-violet-500 to-purple-600" />
|
|
221
|
+
<div>
|
|
222
|
+
<h3 className="text-xl font-bold">ProGamer_42</h3>
|
|
223
|
+
<p className="text-sm text-muted-foreground">Level 42 • 1,847 XP</p>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
|
|
227
|
+
<div className="mb-4">
|
|
228
|
+
<h4 className="text-sm font-medium text-muted-foreground mb-2">Featured Badges</h4>
|
|
229
|
+
<WakaBadgeShowcase
|
|
230
|
+
badges={sampleBadges.filter(b => b.unlockedAt).slice(0, 3)}
|
|
231
|
+
variant="showcase"
|
|
232
|
+
/>
|
|
233
|
+
</div>
|
|
234
|
+
|
|
235
|
+
<div>
|
|
236
|
+
<div className="flex justify-between items-center mb-2">
|
|
237
|
+
<h4 className="text-sm font-medium text-muted-foreground">All Badges</h4>
|
|
238
|
+
<span className="text-xs text-muted-foreground">6/10</span>
|
|
239
|
+
</div>
|
|
240
|
+
<WakaBadgeShowcase badges={sampleBadges} showLocked columns={5} size="sm" />
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
),
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export const CompactWidget: Story = {
|
|
247
|
+
render: () => (
|
|
248
|
+
<div className="w-[280px] p-4 rounded-lg border">
|
|
249
|
+
<div className="flex justify-between items-center mb-3">
|
|
250
|
+
<h4 className="text-sm font-semibold">Recent Badges</h4>
|
|
251
|
+
<a href="#" className="text-xs text-primary hover:underline">View All</a>
|
|
252
|
+
</div>
|
|
253
|
+
<WakaBadgeShowcase
|
|
254
|
+
badges={sampleBadges.filter(b => b.unlockedAt).slice(0, 4)}
|
|
255
|
+
variant="grid"
|
|
256
|
+
columns={4}
|
|
257
|
+
size="sm"
|
|
258
|
+
/>
|
|
259
|
+
</div>
|
|
260
|
+
),
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export const NoAnimation: Story = {
|
|
264
|
+
render: () => (
|
|
265
|
+
<div className="w-[500px]">
|
|
266
|
+
<WakaBadgeShowcase badges={sampleBadges.slice(0, 6)} animated={false} />
|
|
267
|
+
</div>
|
|
268
|
+
),
|
|
269
|
+
}
|