@wakastellar/ui 2.3.4 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/dist/blocks/dashboard/index.d.ts +4 -1
  2. package/dist/blocks/empty-states/index.d.ts +4 -1
  3. package/dist/blocks/error-pages/index.d.ts +4 -1
  4. package/dist/blocks/index.d.ts +1 -1
  5. package/dist/blocks/landing/index.d.ts +4 -1
  6. package/dist/blocks/pricing/index.d.ts +5 -1
  7. package/dist/blocks/sidebar/index.d.ts +5 -1
  8. package/dist/index.cjs.js +130 -130
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.es.js +7905 -7856
  11. package/dist/stories/Button.d.ts +14 -0
  12. package/dist/stories/Button.stories.d.ts +8 -0
  13. package/dist/stories/Header.d.ts +11 -0
  14. package/dist/stories/Header.stories.d.ts +6 -0
  15. package/dist/stories/Page.d.ts +2 -0
  16. package/dist/stories/Page.stories.d.ts +6 -0
  17. package/dist/types/index.d.ts +1 -0
  18. package/dist/types/link.d.ts +23 -0
  19. package/package.json +11 -3
  20. package/src/blocks/activity-timeline/ActivityTimeline.stories.tsx +460 -0
  21. package/src/blocks/apm-overview/APMOverview.stories.tsx +435 -0
  22. package/src/blocks/auth-2fa/Auth2FA.stories.tsx +308 -0
  23. package/src/blocks/calendar-view/CalendarView.stories.tsx +398 -0
  24. package/src/blocks/chat/Chat.stories.tsx +466 -0
  25. package/src/blocks/chat-interface/ChatInterface.stories.tsx +412 -0
  26. package/src/blocks/checkout-flow/CheckoutFlow.stories.tsx +408 -0
  27. package/src/blocks/cicd-builder/CICDBuilder.stories.tsx +499 -0
  28. package/src/blocks/cloud-cost-dashboard/CloudCostDashboard.stories.tsx +356 -0
  29. package/src/blocks/container-orchestrator/ContainerOrchestrator.stories.tsx +461 -0
  30. package/src/blocks/dashboard/Dashboard.stories.tsx +559 -0
  31. package/src/blocks/dashboard/index.tsx +68 -27
  32. package/src/blocks/dashboard-kpi/DashboardKPI.stories.tsx +422 -0
  33. package/src/blocks/database-admin/DatabaseAdmin.stories.tsx +393 -0
  34. package/src/blocks/deployment-dashboard/DeploymentDashboard.stories.tsx +457 -0
  35. package/src/blocks/empty-states/EmptyStates.stories.tsx +467 -0
  36. package/src/blocks/empty-states/index.tsx +26 -8
  37. package/src/blocks/error-pages/ErrorPages.stories.tsx +401 -0
  38. package/src/blocks/error-pages/index.tsx +26 -8
  39. package/src/blocks/faq/FAQ.stories.tsx +416 -0
  40. package/src/blocks/file-manager/FileManager.stories.tsx +413 -0
  41. package/src/blocks/footer/Footer.stories.tsx +328 -0
  42. package/src/blocks/gitops-sync-status/GitOpsSyncStatus.stories.tsx +529 -0
  43. package/src/blocks/header/WakaHeader.stories.tsx +455 -0
  44. package/src/blocks/headtab/Headtab.stories.tsx +369 -0
  45. package/src/blocks/i18n-editor/I18nEditor.stories.tsx +451 -0
  46. package/src/blocks/incident-manager/IncidentManager.stories.tsx +464 -0
  47. package/src/blocks/index.ts +1 -1
  48. package/src/blocks/infrastructure-map/InfrastructureMap.stories.tsx +533 -0
  49. package/src/blocks/kanban-board/KanbanBoard.stories.tsx +494 -0
  50. package/src/blocks/landing/WakaLanding.stories.tsx +449 -0
  51. package/src/blocks/landing/index.tsx +125 -66
  52. package/src/blocks/language-selector/LanguageSelector.stories.tsx +345 -0
  53. package/src/blocks/layout/Layout.stories.tsx +373 -0
  54. package/src/blocks/login/Login.stories.tsx +443 -0
  55. package/src/blocks/on-call-schedule/OnCallSchedule.stories.tsx +381 -0
  56. package/src/blocks/player-profile/PlayerProfile.stories.tsx +316 -0
  57. package/src/blocks/pricing/WakaPricing.stories.tsx +530 -0
  58. package/src/blocks/pricing/index.tsx +38 -4
  59. package/src/blocks/profile/Profile.stories.tsx +371 -0
  60. package/src/blocks/release-notes/ReleaseNotes.stories.tsx +431 -0
  61. package/src/blocks/settings/Settings.stories.tsx +520 -0
  62. package/src/blocks/sidebar/WakaSidebar.stories.tsx +513 -0
  63. package/src/blocks/sidebar/index.tsx +49 -20
  64. package/src/blocks/theme-creator-block/ThemeCreatorBlock.stories.tsx +370 -0
  65. package/src/blocks/user-management/UserManagement.stories.tsx +411 -0
  66. package/src/blocks/wizard/Wizard.stories.tsx +683 -0
  67. package/src/components/accordion/Accordion.stories.tsx +93 -0
  68. package/src/components/alert/Alert.stories.tsx +95 -0
  69. package/src/components/alert-dialog/AlertDialog.stories.tsx +126 -0
  70. package/src/components/aspect-ratio/AspectRatio.stories.tsx +118 -0
  71. package/src/components/avatar/Avatar.stories.tsx +104 -0
  72. package/src/components/button/Button.stories.tsx +12 -1
  73. package/src/components/calendar/Calendar.stories.tsx +102 -0
  74. package/src/components/card/Card.stories.tsx +125 -0
  75. package/src/components/checkbox/Checkbox.stories.tsx +100 -0
  76. package/src/components/code/Code.stories.tsx +402 -0
  77. package/src/components/collapsible/Collapsible.stories.tsx +123 -0
  78. package/src/components/command/Command.stories.tsx +207 -0
  79. package/src/components/context-menu/ContextMenu.stories.tsx +220 -0
  80. package/src/components/dialog/Dialog.stories.tsx +157 -0
  81. package/src/components/dropdown-menu/DropdownMenu.stories.tsx +225 -0
  82. package/src/components/form/Form.stories.tsx +413 -0
  83. package/src/components/hover-card/HoverCard.stories.tsx +148 -0
  84. package/src/components/input-otp/InputOTP.stories.tsx +255 -0
  85. package/src/components/label/Label.stories.tsx +68 -0
  86. package/src/components/menubar/Menubar.stories.tsx +278 -0
  87. package/src/components/navigation-menu/NavigationMenu.stories.tsx +202 -0
  88. package/src/components/popover/Popover.stories.tsx +199 -0
  89. package/src/components/progress/Progress.stories.tsx +104 -0
  90. package/src/components/radio-group/RadioGroup.stories.tsx +138 -0
  91. package/src/components/scroll-area/ScrollArea.stories.tsx +153 -0
  92. package/src/components/select/Select.stories.tsx +146 -0
  93. package/src/components/separator/Separator.stories.tsx +117 -0
  94. package/src/components/sheet/Sheet.stories.tsx +195 -0
  95. package/src/components/skeleton/Skeleton.stories.tsx +114 -0
  96. package/src/components/slider/Slider.stories.tsx +157 -0
  97. package/src/components/switch/Switch.stories.tsx +114 -0
  98. package/src/components/table/Table.stories.tsx +153 -0
  99. package/src/components/tabs/Tabs.stories.tsx +155 -0
  100. package/src/components/textarea/Textarea.stories.tsx +116 -0
  101. package/src/components/toast/Toast.stories.tsx +160 -0
  102. package/src/components/toggle/Toggle.stories.tsx +125 -0
  103. package/src/components/tooltip/Tooltip.stories.tsx +133 -0
  104. package/src/components/typography/Typography.stories.tsx +207 -0
  105. package/src/components/waka-3d-pie-chart/Waka3DPieChart.stories.tsx +308 -0
  106. package/src/components/waka-achievement-unlock/WakaAchievementUnlock.stories.tsx +353 -0
  107. package/src/components/waka-artifact-list/WakaArtifactList.stories.tsx +258 -0
  108. package/src/components/waka-autocomplete/WakaAutocomplete.stories.tsx +224 -0
  109. package/src/components/waka-badge-showcase/WakaBadgeShowcase.stories.tsx +269 -0
  110. package/src/components/waka-barcode/WakaBarcode.stories.tsx +227 -0
  111. package/src/components/waka-bottom-sheet/WakaBottomSheet.stories.tsx +408 -0
  112. package/src/components/waka-breadcrumb/WakaBreadcrumb.stories.tsx +237 -0
  113. package/src/components/waka-build-matrix/WakaBuildMatrix.stories.tsx +328 -0
  114. package/src/components/waka-carousel/WakaCarousel.stories.tsx +296 -0
  115. package/src/components/waka-charts/WakaCharts.stories.tsx +519 -0
  116. package/src/components/waka-color-picker/WakaColorPicker.stories.tsx +200 -0
  117. package/src/components/waka-combobox/WakaCombobox.stories.tsx +250 -0
  118. package/src/components/waka-container-list/WakaContainerList.stories.tsx +315 -0
  119. package/src/components/waka-contribution-graph/WakaContributionGraph.stories.tsx +354 -0
  120. package/src/components/waka-cost-breakdown/WakaCostBreakdown.stories.tsx +348 -0
  121. package/src/components/waka-daily-reward/WakaDailyReward.stories.tsx +365 -0
  122. package/src/components/waka-database-card/WakaDatabaseCard.stories.tsx +306 -0
  123. package/src/components/waka-date-range-picker/WakaDateRangePicker.stories.tsx +339 -0
  124. package/src/components/waka-datetime-picker/WakaDateTimePicker.stories.tsx +317 -0
  125. package/src/components/waka-deployment-lane/WakaDeploymentLane.stories.tsx +292 -0
  126. package/src/components/waka-dock/WakaDock.stories.tsx +332 -0
  127. package/src/components/waka-drawer/WakaDrawer.stories.tsx +437 -0
  128. package/src/components/waka-env-var-editor/WakaEnvVarEditor.stories.tsx +263 -0
  129. package/src/components/waka-error-shake/WakaErrorShake.stories.tsx +410 -0
  130. package/src/components/waka-file-upload/WakaFileUpload.stories.tsx +239 -0
  131. package/src/components/waka-flow-diagram/WakaFlowDiagram.stories.tsx +365 -0
  132. package/src/components/waka-funnel-chart/WakaFunnelChart.stories.tsx +281 -0
  133. package/src/components/waka-glow-card/WakaGlowCard.stories.tsx +274 -0
  134. package/src/components/waka-haptic-button/WakaHapticButton.stories.tsx +349 -0
  135. package/src/components/waka-health-pulse/WakaHealthPulse.stories.tsx +293 -0
  136. package/src/components/waka-heatmap/WakaHeatmap.stories.tsx +376 -0
  137. package/src/components/waka-image/WakaImage.stories.tsx +255 -0
  138. package/src/components/waka-incident-timeline/WakaIncidentTimeline.stories.tsx +300 -0
  139. package/src/components/waka-kanban/WakaKanban.stories.tsx +399 -0
  140. package/src/components/waka-kubernetes-overview/WakaKubernetesOverview.stories.tsx +281 -0
  141. package/src/components/waka-leaderboard/WakaLeaderboard.stories.tsx +300 -0
  142. package/src/components/waka-level-progress/WakaLevelProgress.stories.tsx +313 -0
  143. package/src/components/waka-loading-orbit/WakaLoadingOrbit.stories.tsx +413 -0
  144. package/src/components/waka-log-viewer/WakaLogViewer.stories.tsx +312 -0
  145. package/src/components/waka-loot-box/WakaLootBox.stories.tsx +374 -0
  146. package/src/components/waka-metric-sparkline/WakaMetricSparkline.stories.tsx +312 -0
  147. package/src/components/waka-migration-list/WakaMigrationList.stories.tsx +289 -0
  148. package/src/components/waka-modal/WakaModal.stories.tsx +434 -0
  149. package/src/components/waka-morph-button/WakaMorphButton.stories.tsx +405 -0
  150. package/src/components/waka-network-topology/WakaNetworkTopology.stories.tsx +364 -0
  151. package/src/components/waka-notifications/WakaNotifications.stories.tsx +290 -0
  152. package/src/components/waka-number-input/WakaNumberInput.stories.tsx +282 -0
  153. package/src/components/waka-pagination/WakaPagination.stories.tsx +328 -0
  154. package/src/components/waka-password-strength/WakaPasswordStrength.stories.tsx +318 -0
  155. package/src/components/waka-pipeline-view/WakaPipelineView.stories.tsx +386 -0
  156. package/src/components/waka-player-card/WakaPlayerCard.stories.tsx +333 -0
  157. package/src/components/waka-pod-card/WakaPodCard.stories.tsx +435 -0
  158. package/src/components/waka-qrcode/WakaQRCode.stories.tsx +232 -0
  159. package/src/components/waka-query-explain/WakaQueryExplain.stories.tsx +407 -0
  160. package/src/components/waka-quest-card/WakaQuestCard.stories.tsx +394 -0
  161. package/src/components/waka-quota-bar/WakaQuotaBar.stories.tsx +435 -0
  162. package/src/components/waka-radar-score/WakaRadarScore.stories.tsx +372 -0
  163. package/src/components/waka-resource-gauge/WakaResourceGauge.stories.tsx +366 -0
  164. package/src/components/waka-rich-text-editor/WakaRichTextEditor.stories.tsx +238 -0
  165. package/src/components/waka-sankey-diagram/WakaSankeyDiagram.stories.tsx +389 -0
  166. package/src/components/waka-scratch-card/WakaScratchCard.stories.tsx +388 -0
  167. package/src/components/waka-secret-card/WakaSecretCard.stories.tsx +314 -0
  168. package/src/components/waka-segmented-control/WakaSegmentedControl.stories.tsx +309 -0
  169. package/src/components/waka-server-rack/WakaServerRack.stories.tsx +382 -0
  170. package/src/components/waka-service-graph/WakaServiceGraph.stories.tsx +262 -0
  171. package/src/components/waka-skeleton-wave/WakaSkeletonWave.stories.tsx +321 -0
  172. package/src/components/waka-skill-tree/WakaSkillTree.stories.tsx +308 -0
  173. package/src/components/waka-spin-wheel/WakaSpinWheel.stories.tsx +368 -0
  174. package/src/components/waka-spinner/WakaSpinner.stories.tsx +156 -0
  175. package/src/components/waka-stat/WakaStat.stories.tsx +334 -0
  176. package/src/components/waka-status-matrix/WakaStatusMatrix.stories.tsx +331 -0
  177. package/src/components/waka-stepper/WakaStepper.stories.tsx +468 -0
  178. package/src/components/waka-streak-counter/WakaStreakCounter.stories.tsx +235 -0
  179. package/src/components/waka-success-explosion/WakaSuccessExplosion.stories.tsx +389 -0
  180. package/src/components/waka-tabs-morph/WakaTabsMorph.stories.tsx +471 -0
  181. package/src/components/waka-terminal-output/WakaTerminalOutput.stories.tsx +351 -0
  182. package/src/components/waka-test-report/WakaTestReport.stories.tsx +322 -0
  183. package/src/components/waka-tilt-card/WakaTiltCard.stories.tsx +300 -0
  184. package/src/components/waka-time-picker/WakaTimePicker.stories.tsx +227 -0
  185. package/src/components/waka-timeline/WakaTimeline.stories.tsx +383 -0
  186. package/src/components/waka-tournament-bracket/WakaTournamentBracket.stories.tsx +375 -0
  187. package/src/components/waka-trace-viewer/WakaTraceViewer.stories.tsx +445 -0
  188. package/src/components/waka-tree/WakaTree.stories.tsx +359 -0
  189. package/src/components/waka-treemap-chart/WakaTreemapChart.stories.tsx +378 -0
  190. package/src/components/waka-typewriter/WakaTypewriter.stories.tsx +366 -0
  191. package/src/components/waka-versus-card/WakaVersusCard.stories.tsx +530 -0
  192. package/src/components/waka-video/WakaVideo.stories.tsx +203 -0
  193. package/src/components/waka-virtual-list/WakaVirtualList.stories.tsx +273 -0
  194. package/src/components/waka-xp-bar/WakaXPBar.stories.tsx +305 -0
@@ -0,0 +1,451 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WakaI18nEditor } from './index'
3
+ import type { I18nEditorConfig, TranslationEntry, LanguageConfig } from './index'
4
+ import * as React from 'react'
5
+
6
+ const meta: Meta<typeof WakaI18nEditor> = {
7
+ title: 'Blocks/I18nEditor',
8
+ component: WakaI18nEditor,
9
+ parameters: {
10
+ layout: 'fullscreen',
11
+ docs: {
12
+ description: {
13
+ component:
14
+ 'A comprehensive internationalization (i18n) translation editor with multi-language support, key management, status tracking (missing/identical/valid), import/export, and inline editing.',
15
+ },
16
+ },
17
+ },
18
+ tags: ['autodocs'],
19
+ }
20
+
21
+ export default meta
22
+ type Story = StoryObj<typeof WakaI18nEditor>
23
+
24
+ const defaultConfig: I18nEditorConfig = {
25
+ languages: [
26
+ { code: 'en', label: 'English', flag: '🇺🇸', isSource: true },
27
+ { code: 'fr', label: 'French', flag: '🇫🇷' },
28
+ { code: 'de', label: 'German', flag: '🇩🇪' },
29
+ { code: 'es', label: 'Spanish', flag: '🇪🇸' },
30
+ ],
31
+ sourceLanguage: 'en',
32
+ keyPathSeparator: '.',
33
+ autoSave: true,
34
+ }
35
+
36
+ const defaultTranslations: TranslationEntry[] = [
37
+ {
38
+ key: 'common.buttons.submit',
39
+ translations: {
40
+ en: { value: 'Submit', updatedAt: new Date() },
41
+ fr: { value: 'Soumettre', updatedAt: new Date() },
42
+ de: { value: 'Einreichen', updatedAt: new Date() },
43
+ es: { value: 'Enviar', updatedAt: new Date() },
44
+ },
45
+ },
46
+ {
47
+ key: 'common.buttons.cancel',
48
+ translations: {
49
+ en: { value: 'Cancel', updatedAt: new Date() },
50
+ fr: { value: 'Annuler', updatedAt: new Date() },
51
+ de: { value: 'Abbrechen', updatedAt: new Date() },
52
+ es: { value: 'Cancelar', updatedAt: new Date() },
53
+ },
54
+ },
55
+ {
56
+ key: 'common.buttons.save',
57
+ translations: {
58
+ en: { value: 'Save', updatedAt: new Date() },
59
+ fr: { value: 'Sauvegarder', updatedAt: new Date() },
60
+ de: { value: '', updatedAt: new Date() }, // Missing
61
+ es: { value: 'Guardar', updatedAt: new Date() },
62
+ },
63
+ },
64
+ {
65
+ key: 'common.buttons.delete',
66
+ translations: {
67
+ en: { value: 'Delete', updatedAt: new Date() },
68
+ fr: { value: 'Supprimer', updatedAt: new Date() },
69
+ de: { value: 'Delete', updatedAt: new Date() }, // Identical (not translated)
70
+ es: { value: 'Eliminar', updatedAt: new Date() },
71
+ },
72
+ },
73
+ {
74
+ key: 'auth.login.title',
75
+ translations: {
76
+ en: { value: 'Welcome back', updatedAt: new Date() },
77
+ fr: { value: 'Content de vous revoir', updatedAt: new Date() },
78
+ de: { value: 'Willkommen zurück', updatedAt: new Date() },
79
+ es: { value: 'Bienvenido de nuevo', updatedAt: new Date() },
80
+ },
81
+ },
82
+ {
83
+ key: 'auth.login.email',
84
+ translations: {
85
+ en: { value: 'Email address', updatedAt: new Date() },
86
+ fr: { value: 'Adresse email', updatedAt: new Date() },
87
+ de: { value: '', updatedAt: new Date() }, // Missing
88
+ es: { value: '', updatedAt: new Date() }, // Missing
89
+ },
90
+ },
91
+ {
92
+ key: 'auth.login.password',
93
+ translations: {
94
+ en: { value: 'Password', updatedAt: new Date() },
95
+ fr: { value: 'Mot de passe', updatedAt: new Date() },
96
+ de: { value: 'Passwort', updatedAt: new Date() },
97
+ es: { value: 'Contraseña', updatedAt: new Date() },
98
+ },
99
+ },
100
+ {
101
+ key: 'errors.required',
102
+ translations: {
103
+ en: { value: 'This field is required', updatedAt: new Date() },
104
+ fr: { value: 'Ce champ est obligatoire', updatedAt: new Date() },
105
+ de: { value: 'Dieses Feld ist erforderlich', updatedAt: new Date() },
106
+ es: { value: 'Este campo es requerido', updatedAt: new Date() },
107
+ },
108
+ },
109
+ {
110
+ key: 'errors.invalid_email',
111
+ translations: {
112
+ en: { value: 'Please enter a valid email', updatedAt: new Date() },
113
+ fr: { value: '', updatedAt: new Date() }, // Missing
114
+ de: { value: '', updatedAt: new Date() }, // Missing
115
+ es: { value: '', updatedAt: new Date() }, // Missing
116
+ },
117
+ },
118
+ ]
119
+
120
+ export const Default: Story = {
121
+ render: () => (
122
+ <div className="h-screen">
123
+ <WakaI18nEditor
124
+ config={defaultConfig}
125
+ translations={defaultTranslations}
126
+ onChange={(key, lang, value) => console.log('Changed:', key, lang, value)}
127
+ onSave={async (translations) => {
128
+ console.log('Save:', translations)
129
+ await new Promise((resolve) => setTimeout(resolve, 500))
130
+ }}
131
+ onAddKey={async (key) => console.log('Add key:', key)}
132
+ onDeleteKey={async (key) => console.log('Delete key:', key)}
133
+ title="Translation Editor"
134
+ description="Manage your application translations"
135
+ />
136
+ </div>
137
+ ),
138
+ }
139
+
140
+ export const AllTranslated: Story = {
141
+ render: () => {
142
+ const translatedEntries: TranslationEntry[] = [
143
+ {
144
+ key: 'greeting.hello',
145
+ translations: {
146
+ en: { value: 'Hello', updatedAt: new Date() },
147
+ fr: { value: 'Bonjour', updatedAt: new Date() },
148
+ de: { value: 'Hallo', updatedAt: new Date() },
149
+ },
150
+ },
151
+ {
152
+ key: 'greeting.goodbye',
153
+ translations: {
154
+ en: { value: 'Goodbye', updatedAt: new Date() },
155
+ fr: { value: 'Au revoir', updatedAt: new Date() },
156
+ de: { value: 'Auf Wiedersehen', updatedAt: new Date() },
157
+ },
158
+ },
159
+ {
160
+ key: 'greeting.thanks',
161
+ translations: {
162
+ en: { value: 'Thank you', updatedAt: new Date() },
163
+ fr: { value: 'Merci', updatedAt: new Date() },
164
+ de: { value: 'Danke', updatedAt: new Date() },
165
+ },
166
+ },
167
+ ]
168
+
169
+ const simpleConfig: I18nEditorConfig = {
170
+ languages: [
171
+ { code: 'en', label: 'English', flag: '🇺🇸', isSource: true },
172
+ { code: 'fr', label: 'French', flag: '🇫🇷' },
173
+ { code: 'de', label: 'German', flag: '🇩🇪' },
174
+ ],
175
+ sourceLanguage: 'en',
176
+ }
177
+
178
+ return (
179
+ <div className="h-screen">
180
+ <WakaI18nEditor
181
+ config={simpleConfig}
182
+ translations={translatedEntries}
183
+ onChange={(key, lang, value) => console.log('Changed:', key, lang, value)}
184
+ />
185
+ </div>
186
+ )
187
+ },
188
+ }
189
+
190
+ export const ManyMissing: Story = {
191
+ render: () => {
192
+ const incompleteEntries: TranslationEntry[] = [
193
+ {
194
+ key: 'page.home.title',
195
+ translations: {
196
+ en: { value: 'Welcome to our platform', updatedAt: new Date() },
197
+ fr: { value: '', updatedAt: new Date() },
198
+ de: { value: '', updatedAt: new Date() },
199
+ ja: { value: '', updatedAt: new Date() },
200
+ },
201
+ },
202
+ {
203
+ key: 'page.home.subtitle',
204
+ translations: {
205
+ en: { value: 'The best solution for your needs', updatedAt: new Date() },
206
+ fr: { value: '', updatedAt: new Date() },
207
+ de: { value: '', updatedAt: new Date() },
208
+ ja: { value: '', updatedAt: new Date() },
209
+ },
210
+ },
211
+ {
212
+ key: 'page.about.title',
213
+ translations: {
214
+ en: { value: 'About Us', updatedAt: new Date() },
215
+ fr: { value: '', updatedAt: new Date() },
216
+ de: { value: '', updatedAt: new Date() },
217
+ ja: { value: '', updatedAt: new Date() },
218
+ },
219
+ },
220
+ {
221
+ key: 'page.contact.title',
222
+ translations: {
223
+ en: { value: 'Contact Us', updatedAt: new Date() },
224
+ fr: { value: '', updatedAt: new Date() },
225
+ de: { value: '', updatedAt: new Date() },
226
+ ja: { value: '', updatedAt: new Date() },
227
+ },
228
+ },
229
+ ]
230
+
231
+ const multiLangConfig: I18nEditorConfig = {
232
+ languages: [
233
+ { code: 'en', label: 'English', flag: '🇺🇸', isSource: true },
234
+ { code: 'fr', label: 'French', flag: '🇫🇷' },
235
+ { code: 'de', label: 'German', flag: '🇩🇪' },
236
+ { code: 'ja', label: 'Japanese', flag: '🇯🇵' },
237
+ ],
238
+ sourceLanguage: 'en',
239
+ }
240
+
241
+ return (
242
+ <div className="h-screen">
243
+ <WakaI18nEditor
244
+ config={multiLangConfig}
245
+ translations={incompleteEntries}
246
+ onChange={(key, lang, value) => console.log('Changed:', key, lang, value)}
247
+ title="Incomplete Translations"
248
+ description="Many translations are missing"
249
+ />
250
+ </div>
251
+ )
252
+ },
253
+ }
254
+
255
+ export const TwoLanguages: Story = {
256
+ render: () => {
257
+ const bilingualConfig: I18nEditorConfig = {
258
+ languages: [
259
+ { code: 'en', label: 'English', flag: '🇺🇸', isSource: true },
260
+ { code: 'es', label: 'Spanish', flag: '🇪🇸' },
261
+ ],
262
+ sourceLanguage: 'en',
263
+ }
264
+
265
+ const bilingualEntries: TranslationEntry[] = [
266
+ { key: 'nav.home', translations: { en: { value: 'Home' }, es: { value: 'Inicio' } } },
267
+ { key: 'nav.products', translations: { en: { value: 'Products' }, es: { value: 'Productos' } } },
268
+ { key: 'nav.services', translations: { en: { value: 'Services' }, es: { value: 'Servicios' } } },
269
+ { key: 'nav.about', translations: { en: { value: 'About' }, es: { value: 'Acerca de' } } },
270
+ { key: 'nav.contact', translations: { en: { value: 'Contact' }, es: { value: 'Contacto' } } },
271
+ ]
272
+
273
+ return (
274
+ <div className="h-screen">
275
+ <WakaI18nEditor
276
+ config={bilingualConfig}
277
+ translations={bilingualEntries}
278
+ onChange={(key, lang, value) => console.log('Changed:', key, lang, value)}
279
+ title="English / Spanish"
280
+ />
281
+ </div>
282
+ )
283
+ },
284
+ }
285
+
286
+ export const ManyLanguages: Story = {
287
+ render: () => {
288
+ const manyLangConfig: I18nEditorConfig = {
289
+ languages: [
290
+ { code: 'en', label: 'English', flag: '🇺🇸', isSource: true },
291
+ { code: 'fr', label: 'French', flag: '🇫🇷' },
292
+ { code: 'de', label: 'German', flag: '🇩🇪' },
293
+ { code: 'es', label: 'Spanish', flag: '🇪🇸' },
294
+ { code: 'it', label: 'Italian', flag: '🇮🇹' },
295
+ { code: 'pt', label: 'Portuguese', flag: '🇵🇹' },
296
+ { code: 'nl', label: 'Dutch', flag: '🇳🇱' },
297
+ { code: 'pl', label: 'Polish', flag: '🇵🇱' },
298
+ ],
299
+ sourceLanguage: 'en',
300
+ }
301
+
302
+ const manyLangEntries: TranslationEntry[] = defaultTranslations.slice(0, 4).map((entry) => ({
303
+ ...entry,
304
+ translations: {
305
+ ...entry.translations,
306
+ it: { value: '', updatedAt: new Date() },
307
+ pt: { value: '', updatedAt: new Date() },
308
+ nl: { value: '', updatedAt: new Date() },
309
+ pl: { value: '', updatedAt: new Date() },
310
+ },
311
+ }))
312
+
313
+ return (
314
+ <div className="h-screen">
315
+ <WakaI18nEditor
316
+ config={manyLangConfig}
317
+ translations={manyLangEntries}
318
+ onChange={(key, lang, value) => console.log('Changed:', key, lang, value)}
319
+ title="Multi-Language Project"
320
+ />
321
+ </div>
322
+ )
323
+ },
324
+ }
325
+
326
+ export const Empty: Story = {
327
+ render: () => (
328
+ <div className="h-screen">
329
+ <WakaI18nEditor
330
+ config={defaultConfig}
331
+ translations={[]}
332
+ onAddKey={async (key) => console.log('Add key:', key)}
333
+ title="New Translation Project"
334
+ description="Start by adding translation keys"
335
+ />
336
+ </div>
337
+ ),
338
+ }
339
+
340
+ export const Loading: Story = {
341
+ render: () => (
342
+ <div className="h-screen">
343
+ <WakaI18nEditor
344
+ config={defaultConfig}
345
+ translations={[]}
346
+ isLoading={true}
347
+ title="Loading Translations..."
348
+ />
349
+ </div>
350
+ ),
351
+ }
352
+
353
+ export const Interactive: Story = {
354
+ render: () => {
355
+ const [translations, setTranslations] = React.useState<TranslationEntry[]>(defaultTranslations)
356
+ const [isSaving, setIsSaving] = React.useState(false)
357
+
358
+ const handleChange = (key: string, lang: string, value: string) => {
359
+ setTranslations((prev) =>
360
+ prev.map((entry) =>
361
+ entry.key === key
362
+ ? {
363
+ ...entry,
364
+ translations: {
365
+ ...entry.translations,
366
+ [lang]: { value, updatedAt: new Date() },
367
+ },
368
+ }
369
+ : entry
370
+ )
371
+ )
372
+ }
373
+
374
+ const handleSave = async () => {
375
+ setIsSaving(true)
376
+ await new Promise((resolve) => setTimeout(resolve, 1000))
377
+ setIsSaving(false)
378
+ alert('Translations saved!')
379
+ }
380
+
381
+ const handleAddKey = async (key: string) => {
382
+ setTranslations((prev) => [
383
+ ...prev,
384
+ {
385
+ key,
386
+ translations: {
387
+ en: { value: '', updatedAt: new Date() },
388
+ fr: { value: '', updatedAt: new Date() },
389
+ de: { value: '', updatedAt: new Date() },
390
+ es: { value: '', updatedAt: new Date() },
391
+ },
392
+ },
393
+ ])
394
+ }
395
+
396
+ const handleDeleteKey = async (key: string) => {
397
+ setTranslations((prev) => prev.filter((e) => e.key !== key))
398
+ }
399
+
400
+ return (
401
+ <div className="h-screen">
402
+ <WakaI18nEditor
403
+ config={defaultConfig}
404
+ translations={translations}
405
+ onChange={handleChange}
406
+ onSave={handleSave}
407
+ onAddKey={handleAddKey}
408
+ onDeleteKey={handleDeleteKey}
409
+ isSaving={isSaving}
410
+ title="Interactive Editor"
411
+ description="Try adding, editing, and deleting translations"
412
+ />
413
+ </div>
414
+ )
415
+ },
416
+ }
417
+
418
+ export const TranslationDashboard: Story = {
419
+ render: () => (
420
+ <div className="min-h-screen bg-muted/30">
421
+ <header className="bg-background border-b px-6 py-4">
422
+ <div className="flex items-center justify-between">
423
+ <div>
424
+ <h1 className="font-bold text-xl">Localization Dashboard</h1>
425
+ <p className="text-sm text-muted-foreground">Manage translations for your application</p>
426
+ </div>
427
+ <nav className="flex gap-4 text-sm">
428
+ <a href="#" className="text-foreground font-medium">Translations</a>
429
+ <a href="#" className="text-muted-foreground hover:text-foreground">Languages</a>
430
+ <a href="#" className="text-muted-foreground hover:text-foreground">Export</a>
431
+ <a href="#" className="text-muted-foreground hover:text-foreground">Settings</a>
432
+ </nav>
433
+ </div>
434
+ </header>
435
+ <main className="h-[calc(100vh-73px)]">
436
+ <WakaI18nEditor
437
+ config={defaultConfig}
438
+ translations={defaultTranslations}
439
+ onChange={(key, lang, value) => console.log('Changed:', key, lang, value)}
440
+ onSave={async (translations) => {
441
+ console.log('Save:', translations)
442
+ await new Promise((resolve) => setTimeout(resolve, 500))
443
+ }}
444
+ onAddKey={async (key) => console.log('Add key:', key)}
445
+ onDeleteKey={async (key) => console.log('Delete key:', key)}
446
+ onExport={async (lang) => console.log('Export:', lang)}
447
+ />
448
+ </main>
449
+ </div>
450
+ ),
451
+ }