@wakastellar/ui 2.4.0 → 3.1.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 (173) hide show
  1. package/dist/blocks/antivirus-dashboard/index.d.ts +44 -0
  2. package/dist/blocks/clamav-service-status/index.d.ts +35 -0
  3. package/dist/blocks/file-scan-uploader/index.d.ts +29 -0
  4. package/dist/blocks/index.d.ts +18 -9
  5. package/dist/blocks/quarantine-manager/index.d.ts +27 -0
  6. package/dist/blocks/scan-history-log/index.d.ts +28 -0
  7. package/dist/blocks/scan-policy-editor/index.d.ts +27 -0
  8. package/dist/blocks/scan-report-generator/index.d.ts +47 -0
  9. package/dist/blocks/signature-database-manager/index.d.ts +39 -0
  10. package/dist/blocks/threat-alert-banner/index.d.ts +26 -0
  11. package/dist/components/index.d.ts +4 -4
  12. package/dist/components/waka-signature-pad/index.d.ts +1 -1
  13. package/dist/exceljs.min-BcLLX0PC.js +29 -0
  14. package/dist/exceljs.min-KOayaaQ4.mjs +23013 -0
  15. package/dist/export.cjs.js +1 -1
  16. package/dist/export.d.ts +2 -2
  17. package/dist/export.es.js +1 -1
  18. package/dist/index.cjs.js +136 -136
  19. package/dist/index.es.js +29978 -27215
  20. package/dist/stories/Button.stories.d.ts +1 -1
  21. package/dist/stories/Header.stories.d.ts +1 -1
  22. package/dist/stories/Page.stories.d.ts +1 -1
  23. package/dist/useDataTableImport-COVnvslz.js +9 -0
  24. package/dist/useDataTableImport-DAlxBY8w.mjs +237 -0
  25. package/dist/utils/index.d.ts +1 -0
  26. package/dist/utils/logger.d.ts +9 -0
  27. package/package.json +6 -5
  28. package/src/blocks/antivirus-dashboard/AntivirusDashboard.stories.tsx +291 -0
  29. package/src/blocks/antivirus-dashboard/index.tsx +525 -0
  30. package/src/blocks/clamav-service-status/ClamAVServiceStatus.stories.tsx +195 -0
  31. package/src/blocks/clamav-service-status/index.tsx +370 -0
  32. package/src/blocks/file-scan-uploader/FileScanUploader.stories.tsx +257 -0
  33. package/src/blocks/file-scan-uploader/index.tsx +311 -0
  34. package/src/blocks/index.ts +163 -11
  35. package/src/blocks/quarantine-manager/QuarantineManager.stories.tsx +209 -0
  36. package/src/blocks/quarantine-manager/index.tsx +435 -0
  37. package/src/blocks/scan-history-log/ScanHistoryLog.stories.tsx +231 -0
  38. package/src/blocks/scan-history-log/index.tsx +406 -0
  39. package/src/blocks/scan-policy-editor/ScanPolicyEditor.stories.tsx +106 -0
  40. package/src/blocks/scan-policy-editor/index.tsx +418 -0
  41. package/src/blocks/scan-report-generator/ScanReportGenerator.stories.tsx +232 -0
  42. package/src/blocks/scan-report-generator/index.tsx +612 -0
  43. package/src/blocks/sidebar/index.tsx +2 -1
  44. package/src/blocks/signature-database-manager/SignatureDatabaseManager.stories.tsx +279 -0
  45. package/src/blocks/signature-database-manager/index.tsx +470 -0
  46. package/src/blocks/theme-creator-block/index.tsx +16 -2
  47. package/src/blocks/threat-alert-banner/ThreatAlertBanner.stories.tsx +152 -0
  48. package/src/blocks/threat-alert-banner/index.tsx +320 -0
  49. package/src/components/DataTable/DataTable.stories.tsx +203 -0
  50. package/src/components/DataTable/hooks/useDataTableExport.ts +38 -31
  51. package/src/components/DataTable/hooks/useDataTableImport.ts +31 -20
  52. package/src/components/error-boundary/ErrorBoundary.stories.tsx +125 -0
  53. package/src/components/index.ts +45 -4
  54. package/src/components/language-selector/LanguageSelector.stories.tsx +112 -0
  55. package/src/components/theme-selector/ThemeSelector.stories.tsx +77 -0
  56. package/src/components/toaster/Toaster.stories.tsx +67 -0
  57. package/src/components/waka-activity-feed/WakaActivityFeed.stories.tsx +116 -0
  58. package/src/components/waka-ad-banner/WakaAdBanner.stories.tsx +102 -0
  59. package/src/components/waka-ad-fallback/WakaAdFallback.stories.tsx +117 -0
  60. package/src/components/waka-ad-inline/WakaAdInline.stories.tsx +105 -0
  61. package/src/components/waka-ad-interstitial/WakaAdInterstitial.stories.tsx +92 -0
  62. package/src/components/waka-ad-placeholder/WakaAdPlaceholder.stories.tsx +89 -0
  63. package/src/components/waka-ad-provider/WakaAdProvider.stories.tsx +110 -0
  64. package/src/components/waka-ad-sidebar/WakaAdSidebar.stories.tsx +89 -0
  65. package/src/components/waka-ad-sidebar/index.tsx +3 -2
  66. package/src/components/waka-ad-sticky-footer/WakaAdStickyFooter.stories.tsx +88 -0
  67. package/src/components/waka-address-autocomplete/WakaAddressAutocomplete.stories.tsx +46 -0
  68. package/src/components/waka-admincrumb/WakaAdmincrumb.stories.tsx +166 -0
  69. package/src/components/waka-alert-panel/WakaAlertPanel.stories.tsx +45 -0
  70. package/src/components/waka-alert-stack/WakaAlertStack.stories.tsx +62 -0
  71. package/src/components/waka-allocation-matrix/WakaAllocationMatrix.stories.tsx +68 -0
  72. package/src/components/waka-approval-chain/WakaApprovalChain.stories.tsx +63 -0
  73. package/src/components/waka-audit-log/WakaAuditLog.stories.tsx +73 -0
  74. package/src/components/waka-autocomplete/WakaAutocomplete.stories.tsx +132 -172
  75. package/src/components/waka-biometric-prompt/WakaBiometricPrompt.stories.tsx +48 -0
  76. package/src/components/waka-breadcrumb/WakaBreadcrumb.stories.tsx +74 -191
  77. package/src/components/waka-breadcrumb-path/WakaBreadcrumbPath.stories.tsx +40 -0
  78. package/src/components/waka-budget-burn/WakaBudgetBurn.stories.tsx +86 -0
  79. package/src/components/waka-capacity-planner/WakaCapacityPlanner.stories.tsx +273 -0
  80. package/src/components/waka-cart-summary/WakaCartSummary.stories.tsx +176 -0
  81. package/src/components/waka-cart-summary/index.tsx +19 -10
  82. package/src/components/waka-challenge-timer/WakaChallengeTimer.stories.tsx +98 -0
  83. package/src/components/waka-chat-bubble/WakaChatBubble.stories.tsx +118 -0
  84. package/src/components/waka-checklist/WakaChecklist.stories.tsx +71 -0
  85. package/src/components/waka-checkout-stepper/WakaCheckoutStepper.stories.tsx +102 -0
  86. package/src/components/waka-cohort-table/WakaCohortTable.stories.tsx +56 -0
  87. package/src/components/waka-color-picker/WakaColorPicker.stories.tsx +99 -155
  88. package/src/components/waka-combo-counter/WakaComboCounter.stories.tsx +128 -0
  89. package/src/components/waka-command-bar/WakaCommandBar.stories.tsx +45 -0
  90. package/src/components/waka-compare-period/WakaComparePeriod.stories.tsx +76 -0
  91. package/src/components/waka-config-comparator/WakaConfigComparator.stories.tsx +143 -0
  92. package/src/components/waka-connection-matrix/WakaConnectionMatrix.stories.tsx +52 -0
  93. package/src/components/waka-content-recommendation/WakaContentRecommendation.stories.tsx +41 -0
  94. package/src/components/waka-coupon-input/WakaCouponInput.stories.tsx +126 -0
  95. package/src/components/waka-credit-card-input/WakaCreditCardInput.stories.tsx +120 -0
  96. package/src/components/waka-datetime-picker.form-integration/WakaDateTimePickerForm.stories.tsx +79 -0
  97. package/src/components/waka-dependency-tree/WakaDependencyTree.stories.tsx +72 -0
  98. package/src/components/waka-device-trust/WakaDeviceTrust.stories.tsx +109 -0
  99. package/src/components/waka-empty-state/WakaEmptyState.stories.tsx +87 -0
  100. package/src/components/waka-feature-announcement/WakaFeatureAnnouncement.stories.tsx +47 -0
  101. package/src/components/waka-feature-flag-row/WakaFeatureFlagRow.stories.tsx +188 -0
  102. package/src/components/waka-file-upload/WakaFileUpload.stories.tsx +118 -174
  103. package/src/components/waka-floating-nav/WakaFloatingNav.stories.tsx +53 -0
  104. package/src/components/waka-goal-progress/WakaGoalProgress.stories.tsx +137 -0
  105. package/src/components/waka-hotspot/WakaHotspot.stories.tsx +56 -0
  106. package/src/components/waka-invoice-preview/WakaInvoicePreview.stories.tsx +169 -0
  107. package/src/components/waka-kpi-dashboard/WakaKpiDashboard.stories.tsx +46 -0
  108. package/src/components/waka-level-progress/WakaLevelProgress.stories.tsx +94 -75
  109. package/src/components/waka-liquid-button/WakaLiquidButton.stories.tsx +45 -0
  110. package/src/components/waka-magic-link/WakaMagicLink.stories.tsx +61 -0
  111. package/src/components/waka-magnetic-button/WakaMagneticButton.stories.tsx +40 -0
  112. package/src/components/waka-mention-input/WakaMentionInput.stories.tsx +140 -0
  113. package/src/components/waka-milestone-road/WakaMilestoneRoad.stories.tsx +143 -0
  114. package/src/components/waka-orbital-menu/WakaOrbitalMenu.stories.tsx +54 -0
  115. package/src/components/waka-order-tracker/WakaOrderTracker.stories.tsx +163 -0
  116. package/src/components/waka-outstream-video/WakaOutstreamVideo.stories.tsx +94 -0
  117. package/src/components/waka-pagination/WakaPagination.stories.tsx +110 -280
  118. package/src/components/waka-password-strength/WakaPasswordStrength.stories.tsx +132 -268
  119. package/src/components/waka-payment-method-picker/WakaPaymentMethodPicker.stories.tsx +141 -0
  120. package/src/components/waka-permission-matrix/WakaPermissionMatrix.stories.tsx +124 -0
  121. package/src/components/waka-phone-input/WakaPhoneInput.stories.tsx +56 -0
  122. package/src/components/waka-points-popup/WakaPointsPopup.stories.tsx +96 -0
  123. package/src/components/waka-power-up/WakaPowerUp.stories.tsx +121 -0
  124. package/src/components/waka-presence-indicator/WakaPresenceIndicator.stories.tsx +49 -0
  125. package/src/components/waka-pricing-table/WakaPricingTable.stories.tsx +159 -0
  126. package/src/components/waka-product-card/WakaProductCard.stories.tsx +202 -0
  127. package/src/components/waka-progress-onboarding/WakaProgressOnboarding.stories.tsx +57 -0
  128. package/src/components/waka-pull-to-refresh/WakaPullToRefresh.stories.tsx +51 -0
  129. package/src/components/waka-rank-badge/WakaRankBadge.stories.tsx +108 -0
  130. package/src/components/waka-rating-input/WakaRatingInput.stories.tsx +51 -0
  131. package/src/components/waka-reaction-picker/WakaReactionPicker.stories.tsx +52 -0
  132. package/src/components/waka-region-map/WakaRegionMap.stories.tsx +181 -0
  133. package/src/components/waka-resource-pool/WakaResourcePool.stories.tsx +70 -0
  134. package/src/components/waka-rich-text-editor/WakaRichTextEditor.stories.tsx +108 -197
  135. package/src/components/waka-rollback-slider/WakaRollbackSlider.stories.tsx +41 -0
  136. package/src/components/waka-schedule-picker/WakaSchedulePicker.stories.tsx +64 -0
  137. package/src/components/waka-season-pass/WakaSeasonPass.stories.tsx +107 -0
  138. package/src/components/waka-security-scan-result/WakaSecurityScanResult.stories.tsx +146 -0
  139. package/src/components/waka-security-score/WakaSecurityScore.stories.tsx +63 -0
  140. package/src/components/waka-session-manager/WakaSessionManager.stories.tsx +68 -0
  141. package/src/components/waka-signature-pad/WakaSignaturePad.stories.tsx +159 -0
  142. package/src/components/waka-signature-pad/index.tsx +5 -3
  143. package/src/components/waka-sla-tracker/WakaSlaTracker.stories.tsx +65 -0
  144. package/src/components/waka-slider-range/WakaSliderRange.stories.tsx +66 -0
  145. package/src/components/waka-sponsored-badge/WakaSponsoredBadge.stories.tsx +60 -0
  146. package/src/components/waka-sponsored-card/WakaSponsoredCard.stories.tsx +64 -0
  147. package/src/components/waka-sponsored-feed/WakaSponsoredFeed.stories.tsx +58 -0
  148. package/src/components/waka-spotlight/WakaSpotlight.stories.tsx +53 -0
  149. package/src/components/waka-stats-hexagon/WakaStatsHexagon.stories.tsx +161 -0
  150. package/src/components/waka-stepper/WakaStepper.stories.tsx +137 -410
  151. package/src/components/waka-swipe-card/WakaSwipeCard.stories.tsx +51 -0
  152. package/src/components/waka-tag-input/WakaTagInput.stories.tsx +224 -0
  153. package/src/components/waka-team-banner/WakaTeamBanner.stories.tsx +50 -0
  154. package/src/components/waka-theme-creator/WakaThemeCreator.stories.tsx +58 -0
  155. package/src/components/waka-theme-manager/WakaThemeManager.stories.tsx +298 -0
  156. package/src/components/waka-theme-manager/index.tsx +6 -11
  157. package/src/components/waka-thread-view/WakaThreadView.stories.tsx +143 -0
  158. package/src/components/waka-timeline/WakaTimeline.stories.tsx +171 -324
  159. package/src/components/waka-tooltip-tour/WakaTooltipTour.stories.tsx +92 -0
  160. package/src/components/waka-tour-guide/WakaTourGuide.stories.tsx +89 -0
  161. package/src/components/waka-treemap-chart/WakaTreemapChart.stories.tsx +234 -129
  162. package/src/components/waka-treemap-chart/index.tsx +2 -2
  163. package/src/components/waka-two-factor-setup/WakaTwoFactorSetup.stories.tsx +142 -0
  164. package/src/components/waka-typing-indicator/WakaTypingIndicator.stories.tsx +134 -0
  165. package/src/components/waka-video-ad/WakaVideoAd.stories.tsx +138 -0
  166. package/src/components/waka-video-call/WakaVideoCall.stories.tsx +186 -0
  167. package/src/components/waka-video-overlay/WakaVideoOverlay.stories.tsx +100 -0
  168. package/src/components/waka-voice-message/WakaVoiceMessage.stories.tsx +190 -0
  169. package/src/components/waka-welcome-modal/WakaWelcomeModal.stories.tsx +87 -0
  170. package/src/components/waka-xp-bar/WakaXPBar.stories.tsx +29 -29
  171. package/dist/useDataTableImport-D8R2HQl6.mjs +0 -229
  172. package/dist/useDataTableImport-S_hhA5Wo.js +0 -9
  173. package/src/components/DataTable/README.md +0 -446
@@ -0,0 +1,190 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import { WakaVoiceMessage } from "./index"
3
+
4
+ const meta: Meta<typeof WakaVoiceMessage> = {
5
+ title: "Communication/WakaVoiceMessage",
6
+ component: WakaVoiceMessage,
7
+ parameters: {
8
+ layout: "centered",
9
+ },
10
+ tags: ["autodocs"],
11
+ argTypes: {
12
+ mode: {
13
+ control: "select",
14
+ options: ["player", "recorder"],
15
+ description: "Mode du composant",
16
+ },
17
+ variant: {
18
+ control: "select",
19
+ options: ["default", "bubble", "bubble-sent", "bubble-received"],
20
+ description: "Style visuel",
21
+ },
22
+ size: {
23
+ control: "select",
24
+ options: ["sm", "md", "lg"],
25
+ description: "Taille du composant",
26
+ },
27
+ waveformBars: {
28
+ control: { type: "number", min: 10, max: 100 },
29
+ description: "Nombre de barres du waveform",
30
+ },
31
+ defaultSpeed: {
32
+ control: "select",
33
+ options: [0.5, 1, 1.5, 2],
34
+ description: "Vitesse de lecture par défaut",
35
+ },
36
+ showDownload: {
37
+ control: "boolean",
38
+ description: "Afficher le bouton télécharger",
39
+ },
40
+ showDelete: {
41
+ control: "boolean",
42
+ description: "Afficher le bouton supprimer",
43
+ },
44
+ showSpeedControl: {
45
+ control: "boolean",
46
+ description: "Afficher le contrôle de vitesse",
47
+ },
48
+ showSend: {
49
+ control: "boolean",
50
+ description: "Afficher le bouton envoyer (mode recorder)",
51
+ },
52
+ showCancel: {
53
+ control: "boolean",
54
+ description: "Afficher le bouton annuler (mode recorder)",
55
+ },
56
+ maxRecordingDuration: {
57
+ control: "number",
58
+ description: "Durée max d'enregistrement en secondes",
59
+ },
60
+ disabled: {
61
+ control: "boolean",
62
+ description: "État désactivé",
63
+ },
64
+ },
65
+ }
66
+
67
+ export default meta
68
+ type Story = StoryObj<typeof WakaVoiceMessage>
69
+
70
+ // Waveform de démonstration
71
+ const sampleWaveform = Array.from({ length: 50 }, () => Math.random() * 0.8 + 0.2)
72
+
73
+ export const Default: Story = {
74
+ args: {
75
+ mode: "player",
76
+ src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
77
+ waveform: sampleWaveform,
78
+ waveformBars: 50,
79
+ variant: "default",
80
+ size: "md",
81
+ showDownload: true,
82
+ showSpeedControl: true,
83
+ defaultSpeed: 1,
84
+ },
85
+ render: (args) => (
86
+ <div style={{ width: 350 }}>
87
+ <WakaVoiceMessage {...args} />
88
+ </div>
89
+ ),
90
+ }
91
+
92
+ export const BubbleSent: Story = {
93
+ args: {
94
+ mode: "player",
95
+ src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
96
+ waveform: sampleWaveform,
97
+ variant: "bubble-sent",
98
+ size: "md",
99
+ showSpeedControl: true,
100
+ },
101
+ render: (args) => (
102
+ <div style={{ width: 300 }}>
103
+ <WakaVoiceMessage {...args} />
104
+ </div>
105
+ ),
106
+ }
107
+
108
+ export const BubbleReceived: Story = {
109
+ args: {
110
+ mode: "player",
111
+ src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
112
+ waveform: sampleWaveform,
113
+ variant: "bubble-received",
114
+ size: "md",
115
+ showSpeedControl: true,
116
+ },
117
+ render: (args) => (
118
+ <div style={{ width: 300 }}>
119
+ <WakaVoiceMessage {...args} />
120
+ </div>
121
+ ),
122
+ }
123
+
124
+ export const Recorder: Story = {
125
+ args: {
126
+ mode: "recorder",
127
+ variant: "default",
128
+ size: "md",
129
+ showSend: true,
130
+ showCancel: true,
131
+ maxRecordingDuration: 60,
132
+ },
133
+ render: (args) => (
134
+ <div style={{ width: 350 }}>
135
+ <WakaVoiceMessage {...args} />
136
+ </div>
137
+ ),
138
+ }
139
+
140
+ export const SmallSize: Story = {
141
+ args: {
142
+ mode: "player",
143
+ src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
144
+ waveform: sampleWaveform.slice(0, 30),
145
+ waveformBars: 30,
146
+ variant: "default",
147
+ size: "sm",
148
+ },
149
+ render: (args) => (
150
+ <div style={{ width: 250 }}>
151
+ <WakaVoiceMessage {...args} />
152
+ </div>
153
+ ),
154
+ }
155
+
156
+ export const LargeSize: Story = {
157
+ args: {
158
+ mode: "player",
159
+ src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
160
+ waveform: sampleWaveform,
161
+ waveformBars: 60,
162
+ variant: "default",
163
+ size: "lg",
164
+ showDownload: true,
165
+ showDelete: true,
166
+ showSpeedControl: true,
167
+ },
168
+ render: (args) => (
169
+ <div style={{ width: 450 }}>
170
+ <WakaVoiceMessage {...args} />
171
+ </div>
172
+ ),
173
+ }
174
+
175
+ export const Disabled: Story = {
176
+ args: {
177
+ mode: "player",
178
+ src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
179
+ waveform: sampleWaveform,
180
+ variant: "default",
181
+ size: "md",
182
+ disabled: true,
183
+ },
184
+ render: (args) => (
185
+ <div style={{ width: 350 }}>
186
+ <WakaVoiceMessage {...args} />
187
+ </div>
188
+ ),
189
+ }
190
+
@@ -0,0 +1,87 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import * as React from "react"
3
+ import { WakaWelcomeModal, type WelcomeStep } from "./index"
4
+ import { Sparkles, Users, Settings, Rocket } from "lucide-react"
5
+
6
+ const meta: Meta<typeof WakaWelcomeModal> = {
7
+ title: "UI/WakaWelcomeModal",
8
+ component: WakaWelcomeModal,
9
+ parameters: { layout: "centered" },
10
+ tags: ["autodocs"],
11
+ argTypes: {
12
+ open: { control: "boolean", description: "Ouvert" },
13
+ allowSkip: { control: "boolean", description: "Autoriser le skip" },
14
+ showDontShowAgain: { control: "boolean", description: "Ne plus afficher" },
15
+ },
16
+ }
17
+
18
+ export default meta
19
+ type Story = StoryObj<typeof WakaWelcomeModal>
20
+
21
+ const steps: WelcomeStep[] = [
22
+ {
23
+ id: "welcome",
24
+ title: "Bienvenue",
25
+ description: "Bienvenue sur la plateforme WakaStart.",
26
+ icon: <Sparkles className="tw-h-10 tw-w-10 text-primary" />,
27
+ },
28
+ {
29
+ id: "team",
30
+ title: "Votre equipe",
31
+ description: "Invitez vos collaborateurs et configurez votre equipe.",
32
+ icon: <Users className="tw-h-10 tw-w-10 text-primary" />,
33
+ options: [
34
+ { id: "invite", label: "Inviter des membres", description: "Ajoutez votre equipe" },
35
+ { id: "roles", label: "Configurer les roles", description: "Gerez les permissions" },
36
+ ],
37
+ multiSelect: true,
38
+ },
39
+ {
40
+ id: "preferences",
41
+ title: "Preferences",
42
+ description: "Choisissez vos parametres par defaut.",
43
+ icon: <Settings className="tw-h-10 tw-w-10 text-primary" />,
44
+ options: [
45
+ { id: "dark", label: "Mode sombre" },
46
+ { id: "notifications", label: "Notifications" },
47
+ ],
48
+ multiSelect: true,
49
+ },
50
+ {
51
+ id: "launch",
52
+ title: "C'est parti",
53
+ description: "Vous etes pret a demarrer.",
54
+ icon: <Rocket className="tw-h-10 tw-w-10 text-primary" />,
55
+ },
56
+ ]
57
+
58
+ export const Default: Story = {
59
+ args: {
60
+ open: true,
61
+ userName: "Alex",
62
+ steps,
63
+ allowSkip: true,
64
+ showDontShowAgain: true,
65
+ },
66
+ render: (args) => {
67
+ const [open, setOpen] = React.useState(Boolean(args.open))
68
+
69
+ React.useEffect(() => {
70
+ setOpen(Boolean(args.open))
71
+ }, [args.open])
72
+
73
+ return <WakaWelcomeModal {...args} open={open} onOpenChange={setOpen} steps={steps} />
74
+ },
75
+ }
76
+
77
+ export const Locked: Story = {
78
+ args: {
79
+ open: true,
80
+ userName: "Marie",
81
+ steps,
82
+ allowSkip: false,
83
+ showDontShowAgain: false,
84
+ },
85
+ render: (args) => <WakaWelcomeModal {...args} open />,
86
+ }
87
+
@@ -76,20 +76,20 @@ export const Variants: Story = {
76
76
  render: () => (
77
77
  <div className="w-[400px] space-y-6">
78
78
  <div>
79
- <p className="text-sm text-muted-foreground mb-2">Default</p>
80
- <WakaXPBar currentXP={1500} maxXP={3000} level={3} variant="default" />
79
+ <p className="text-sm text-muted-foreground mb-2">Small size</p>
80
+ <WakaXPBar currentXP={1500} requiredXP={3000} level={3} size="sm" />
81
81
  </div>
82
82
  <div>
83
- <p className="text-sm text-muted-foreground mb-2">Gradient</p>
84
- <WakaXPBar currentXP={2000} maxXP={3000} level={5} variant="gradient" />
83
+ <p className="text-sm text-muted-foreground mb-2">Medium size (default)</p>
84
+ <WakaXPBar currentXP={2000} requiredXP={3000} level={5} size="md" />
85
85
  </div>
86
86
  <div>
87
- <p className="text-sm text-muted-foreground mb-2">Glow</p>
88
- <WakaXPBar currentXP={2800} maxXP={3000} level={8} variant="glow" />
87
+ <p className="text-sm text-muted-foreground mb-2">Large size</p>
88
+ <WakaXPBar currentXP={2800} requiredXP={3000} level={8} size="lg" />
89
89
  </div>
90
90
  <div>
91
- <p className="text-sm text-muted-foreground mb-2">Minimal</p>
92
- <WakaXPBar currentXP={1200} maxXP={3000} level={2} variant="minimal" />
91
+ <p className="text-sm text-muted-foreground mb-2">With particles</p>
92
+ <WakaXPBar currentXP={1200} requiredXP={3000} level={2} showParticles />
93
93
  </div>
94
94
  </div>
95
95
  ),
@@ -100,15 +100,15 @@ export const Sizes: Story = {
100
100
  <div className="w-[400px] space-y-6">
101
101
  <div>
102
102
  <p className="text-sm text-muted-foreground mb-2">Small</p>
103
- <WakaXPBar currentXP={1500} maxXP={3000} level={3} size="sm" />
103
+ <WakaXPBar currentXP={1500} requiredXP={3000} level={3} size="sm" />
104
104
  </div>
105
105
  <div>
106
106
  <p className="text-sm text-muted-foreground mb-2">Medium (Default)</p>
107
- <WakaXPBar currentXP={2000} maxXP={3000} level={5} size="md" />
107
+ <WakaXPBar currentXP={2000} requiredXP={3000} level={5} size="md" />
108
108
  </div>
109
109
  <div>
110
110
  <p className="text-sm text-muted-foreground mb-2">Large</p>
111
- <WakaXPBar currentXP={2500} maxXP={3000} level={8} size="lg" />
111
+ <WakaXPBar currentXP={2500} requiredXP={3000} level={8} size="lg" />
112
112
  </div>
113
113
  </div>
114
114
  ),
@@ -119,19 +119,19 @@ export const ProgressStates: Story = {
119
119
  <div className="w-[400px] space-y-6">
120
120
  <div>
121
121
  <p className="text-sm text-muted-foreground mb-2">Just Started (10%)</p>
122
- <WakaXPBar currentXP={300} maxXP={3000} level={1} />
122
+ <WakaXPBar currentXP={300} requiredXP={3000} level={1} />
123
123
  </div>
124
124
  <div>
125
125
  <p className="text-sm text-muted-foreground mb-2">Halfway (50%)</p>
126
- <WakaXPBar currentXP={1500} maxXP={3000} level={5} />
126
+ <WakaXPBar currentXP={1500} requiredXP={3000} level={5} />
127
127
  </div>
128
128
  <div>
129
129
  <p className="text-sm text-muted-foreground mb-2">Almost There (90%)</p>
130
- <WakaXPBar currentXP={2700} maxXP={3000} level={9} />
130
+ <WakaXPBar currentXP={2700} requiredXP={3000} level={9} />
131
131
  </div>
132
132
  <div>
133
133
  <p className="text-sm text-muted-foreground mb-2">Max Level Ready</p>
134
- <WakaXPBar currentXP={3000} maxXP={3000} level={10} />
134
+ <WakaXPBar currentXP={3000} requiredXP={3000} level={10} />
135
135
  </div>
136
136
  </div>
137
137
  ),
@@ -142,11 +142,11 @@ export const WithParticles: Story = {
142
142
  <div className="w-[400px] space-y-6">
143
143
  <div>
144
144
  <p className="text-sm text-muted-foreground mb-2">With Particles</p>
145
- <WakaXPBar currentXP={2500} maxXP={3000} level={7} showParticles />
145
+ <WakaXPBar currentXP={2500} requiredXP={3000} level={7} showParticles />
146
146
  </div>
147
147
  <div>
148
148
  <p className="text-sm text-muted-foreground mb-2">Without Particles</p>
149
- <WakaXPBar currentXP={2500} maxXP={3000} level={7} showParticles={false} />
149
+ <WakaXPBar currentXP={2500} requiredXP={3000} level={7} showParticles={false} />
150
150
  </div>
151
151
  </div>
152
152
  ),
@@ -155,15 +155,15 @@ export const WithParticles: Story = {
155
155
  export const Interactive: Story = {
156
156
  render: () => {
157
157
  const [xp, setXp] = React.useState(1000)
158
- const maxXP = 5000
158
+ const requiredXP = 5000
159
159
  const level = Math.floor(xp / 1000) + 1
160
160
 
161
161
  return (
162
162
  <div className="w-[400px] space-y-4">
163
- <WakaXPBar currentXP={xp} maxXP={maxXP} level={level} showParticles animated />
163
+ <WakaXPBar currentXP={xp} requiredXP={requiredXP} level={level} showParticles animated />
164
164
  <div className="flex gap-2">
165
165
  <button
166
- onClick={() => setXp((prev) => Math.min(prev + 500, maxXP))}
166
+ onClick={() => setXp((prev) => Math.min(prev + 500, requiredXP))}
167
167
  className="px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90"
168
168
  >
169
169
  +500 XP
@@ -182,7 +182,7 @@ export const Interactive: Story = {
182
182
  </button>
183
183
  </div>
184
184
  <p className="text-sm text-muted-foreground text-center">
185
- Level {level} • {xp.toLocaleString()} / {maxXP.toLocaleString()} XP
185
+ Level {level} • {xp.toLocaleString()} / {requiredXP.toLocaleString()} XP
186
186
  </p>
187
187
  </div>
188
188
  )
@@ -191,15 +191,15 @@ export const Interactive: Story = {
191
191
 
192
192
  export const WithHook: Story = {
193
193
  render: () => {
194
- const { currentXP, maxXP, level, percentage, addXP, reset, levelUp } = useXPBar({
194
+ const { currentXP, requiredXP, level, progressPercent, addXP, reset } = useXPBar({
195
195
  initialXP: 1500,
196
- initialMaxXP: 3000,
197
196
  initialLevel: 3,
197
+ xpPerLevel: 3000,
198
198
  })
199
199
 
200
200
  return (
201
201
  <div className="w-[400px] space-y-4">
202
- <WakaXPBar currentXP={currentXP} maxXP={maxXP} level={level} variant="gradient" showParticles />
202
+ <WakaXPBar currentXP={currentXP} requiredXP={requiredXP} level={level} showParticles />
203
203
 
204
204
  <div className="grid grid-cols-3 gap-2 text-center">
205
205
  <div className="p-3 rounded-lg border">
@@ -211,7 +211,7 @@ export const WithHook: Story = {
211
211
  <p className="text-xs text-muted-foreground">Current XP</p>
212
212
  </div>
213
213
  <div className="p-3 rounded-lg border">
214
- <p className="text-2xl font-bold">{Math.round(percentage)}%</p>
214
+ <p className="text-2xl font-bold">{Math.round(progressPercent)}%</p>
215
215
  <p className="text-xs text-muted-foreground">Progress</p>
216
216
  </div>
217
217
  </div>
@@ -230,7 +230,7 @@ export const WithHook: Story = {
230
230
  +500 XP
231
231
  </button>
232
232
  <button
233
- onClick={levelUp}
233
+ onClick={() => addXP(requiredXP - currentXP)}
234
234
  className="px-3 py-1.5 text-sm rounded bg-purple-500 text-white hover:bg-purple-600"
235
235
  >
236
236
  Level Up
@@ -264,7 +264,7 @@ export const GamerProfile: Story = {
264
264
  </div>
265
265
  </div>
266
266
 
267
- <WakaXPBar currentXP={8750} maxXP={10000} level={42} variant="glow" showParticles />
267
+ <WakaXPBar currentXP={8750} requiredXP={10000} level={42} showParticles />
268
268
 
269
269
  <div className="mt-6 grid grid-cols-3 gap-4 text-center">
270
270
  <div className="p-3 rounded-lg bg-muted/50">
@@ -287,7 +287,7 @@ export const GamerProfile: Story = {
287
287
  export const NoAnimation: Story = {
288
288
  render: () => (
289
289
  <div className="w-[400px]">
290
- <WakaXPBar currentXP={2500} maxXP={5000} level={5} animated={false} showParticles={false} />
290
+ <WakaXPBar currentXP={2500} requiredXP={5000} level={5} animated={false} showParticles={false} />
291
291
  </div>
292
292
  ),
293
293
  }
@@ -299,7 +299,7 @@ export const CompactWidget: Story = {
299
299
  <span className="text-sm font-medium">Your Progress</span>
300
300
  <span className="text-xs text-muted-foreground">Lv. 12</span>
301
301
  </div>
302
- <WakaXPBar currentXP={2200} maxXP={3000} level={12} size="sm" variant="minimal" />
302
+ <WakaXPBar currentXP={2200} requiredXP={3000} level={12} size="sm" />
303
303
  </div>
304
304
  ),
305
305
  }
@@ -1,229 +0,0 @@
1
- import { useMemo as S, useCallback as u } from "react";
2
- function X({
3
- data: h,
4
- columns: i,
5
- exportConfig: y
6
- }) {
7
- const p = S(() => ({
8
- formats: ["csv", "xlsx", "json"],
9
- filename: "export",
10
- includeHeaders: !0,
11
- ...y
12
- }), [y]), x = u((e, o) => {
13
- if (!e.length) return;
14
- const r = i.filter((a) => a.accessorKey || a.id).map((a) => a.header || a.accessorKey || a.id).join(","), s = e.map((a) => i.filter((n) => n.accessorKey || n.id).map((n) => {
15
- const f = n.accessorKey ? a[n.accessorKey] : a[n.id], k = n.formatter ? n.formatter(f) : f, L = String(k || "");
16
- return L.includes(",") || L.includes('"') || L.includes(`
17
- `) ? `"${L.replace(/"/g, '""')}"` : L;
18
- }).join(",")), t = [r, ...s].join(`
19
- `), d = new Blob([t], { type: "text/csv;charset=utf-8;" }), l = document.createElement("a");
20
- l.href = URL.createObjectURL(d), l.download = `${o || p.filename}.csv`, l.click(), URL.revokeObjectURL(l.href);
21
- }, [i, p.filename]), b = u((e, o) => {
22
- const r = JSON.stringify(e, null, 2), s = new Blob([r], { type: "application/json" }), t = document.createElement("a");
23
- t.href = URL.createObjectURL(s), t.download = `${o || p.filename}.json`, t.click(), URL.revokeObjectURL(t.href);
24
- }, [p.filename]), v = u(async (e, o) => {
25
- try {
26
- if (typeof window > "u")
27
- throw new Error("XLSX export not available in server environment");
28
- const r = await import("xlsx"), t = [
29
- i.filter((a) => a.accessorKey || a.id).map((a) => a.header || a.accessorKey || a.id),
30
- ...e.map(
31
- (a) => i.filter((n) => n.accessorKey || n.id).map((n) => {
32
- const f = n.accessorKey ? a[n.accessorKey] : a[n.id];
33
- return n.formatter ? n.formatter(f) : f;
34
- })
35
- )
36
- ], d = r.utils.aoa_to_sheet(t), l = r.utils.book_new();
37
- r.utils.book_append_sheet(l, d, "Sheet1"), r.writeFile(l, `${o || p.filename}.xlsx`);
38
- } catch (r) {
39
- throw console.error("Erreur lors de l'export XLSX:", r), new Error("La librairie xlsx n'est pas disponible");
40
- }
41
- }, [i, p.filename]), E = u(async (e, o) => {
42
- try {
43
- if (typeof window > "u")
44
- throw new Error("PDF export not available in server environment");
45
- const r = await import("jspdf"), s = await import("jspdf-autotable"), t = new r.default(), d = i.filter((a) => a.accessorKey || a.id).map((a) => a.header || a.accessorKey || a.id), l = e.map(
46
- (a) => i.filter((n) => n.accessorKey || n.id).map((n) => {
47
- const f = n.accessorKey ? a[n.accessorKey] : a[n.id];
48
- return n.formatter ? n.formatter(f) : f;
49
- })
50
- );
51
- t.autoTable({
52
- head: [d],
53
- body: l,
54
- startY: 20,
55
- styles: { fontSize: 8 },
56
- headStyles: { fillColor: [66, 139, 202] }
57
- }), t.save(`${o || p.filename}.pdf`);
58
- } catch (r) {
59
- throw console.error("Erreur lors de l'export PDF:", r), new Error("Les librairies jsPDF et jspdf-autotable ne sont pas disponibles");
60
- }
61
- }, [i, p.filename]), w = u((e, o) => {
62
- const r = i.filter((l) => l.accessorKey || l.id).map((l) => l.accessorKey || l.id);
63
- let s = `<?xml version="1.0" encoding="UTF-8"?>
64
- <data>
65
- `;
66
- e.forEach((l, a) => {
67
- s += ` <row id="${a}">
68
- `, r.forEach((n) => {
69
- const f = l[n], k = String(f || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
70
- s += ` <${n}>${k}</${n}>
71
- `;
72
- }), s += ` </row>
73
- `;
74
- }), s += "</data>";
75
- const t = new Blob([s], { type: "application/xml" }), d = document.createElement("a");
76
- d.href = URL.createObjectURL(t), d.download = `${o || p.filename}.xml`, d.click(), URL.revokeObjectURL(d.href);
77
- }, [i, p.filename]), m = u(async (e, o, r) => {
78
- const s = o || h, t = r || p.filename;
79
- if (p.onExport) {
80
- p.onExport(s, e);
81
- return;
82
- }
83
- switch (e.toLowerCase()) {
84
- case "csv":
85
- x(s, t);
86
- break;
87
- case "json":
88
- b(s, t);
89
- break;
90
- case "xlsx":
91
- await v(s, t);
92
- break;
93
- case "pdf":
94
- await E(s, t);
95
- break;
96
- case "xml":
97
- w(s, t);
98
- break;
99
- default:
100
- throw new Error(`Format d'export non supporté: ${e}`);
101
- }
102
- }, [h, p, x, b, v, E, w]), g = u(async (e) => m(e), [m]), c = u(async (e, o) => m(e, o), [m]);
103
- return {
104
- exportData: m,
105
- exportAll: g,
106
- exportSelected: c,
107
- supportedFormats: p.formats,
108
- isExportSupported: (e) => p.formats.includes(e)
109
- };
110
- }
111
- function D({
112
- importConfig: h
113
- }) {
114
- const i = S(() => ({
115
- accept: ".csv,.xlsx,.json,.xml",
116
- ...h
117
- }), [h]), y = u((c, e = ",") => {
118
- const o = c.split(`
119
- `).filter((t) => t.trim());
120
- if (o.length === 0) return [];
121
- const r = o[0].split(e).map((t) => t.trim().replace(/"/g, ""));
122
- return o.slice(1).map((t) => {
123
- const d = t.split(e).map((a) => a.trim().replace(/"/g, "")), l = {};
124
- return r.forEach((a, n) => {
125
- l[a] = d[n] || "";
126
- }), l;
127
- });
128
- }, []), p = u((c) => {
129
- try {
130
- const e = JSON.parse(c);
131
- return Array.isArray(e) ? e : [e];
132
- } catch {
133
- throw new Error("Format JSON invalide");
134
- }
135
- }, []), x = u((c) => {
136
- try {
137
- const r = new DOMParser().parseFromString(c, "text/xml").querySelectorAll("row");
138
- return Array.from(r).map((s) => {
139
- const t = {};
140
- return Array.from(s.children).forEach((d) => {
141
- t[d.tagName] = d.textContent || "";
142
- }), t;
143
- });
144
- } catch {
145
- throw new Error("Format XML invalide");
146
- }
147
- }, []), b = u(async (c) => {
148
- try {
149
- if (typeof window > "u")
150
- throw new Error("XLSX parsing not available in server environment");
151
- const e = await import("xlsx"), o = await c.arrayBuffer(), r = e.read(o, { type: "array" }), s = r.SheetNames[0], t = r.Sheets[s], d = e.utils.sheet_to_json(t, { header: 1 });
152
- if (d.length === 0) return [];
153
- const l = d[0];
154
- return d.slice(1).map((a) => {
155
- const n = {};
156
- return l.forEach((f, k) => {
157
- n[f] = a[k] || "";
158
- }), n;
159
- });
160
- } catch {
161
- throw new Error("Erreur lors du parsing du fichier XLSX");
162
- }
163
- }, []), v = u((c) => i.validate ? i.validate(c) : Array.isArray(c) ? c.length === 0 ? { valid: !1, errors: ["Aucune donnée trouvée"] } : { valid: !0, errors: [] } : { valid: !1, errors: ["Les données doivent être un tableau"] }, [i.validate]), E = u((c) => i.columnMapping ? c.map((e) => {
164
- const o = {};
165
- return Object.entries(i.columnMapping).forEach(([r, s]) => {
166
- e[r] !== void 0 && (o[s] = e[r]);
167
- }), o;
168
- }) : c, [i.columnMapping]), w = u(async (c) => {
169
- const e = c.name.split(".").pop()?.toLowerCase();
170
- let o = [];
171
- try {
172
- const r = await c.text();
173
- switch (e) {
174
- case "csv":
175
- o = y(r, i.parseOptions?.csv?.delimiter);
176
- break;
177
- case "json":
178
- o = p(r);
179
- break;
180
- case "xml":
181
- o = x(r);
182
- break;
183
- case "xlsx":
184
- o = await b(c);
185
- break;
186
- default:
187
- throw new Error(`Format de fichier non supporté: ${e}`);
188
- }
189
- const s = v(o);
190
- if (!s.valid)
191
- throw new Error(`Données invalides: ${s.errors.join(", ")}`);
192
- const t = E(o);
193
- return i.onImport && i.onImport(t), t;
194
- } catch (r) {
195
- throw new Error(`Erreur lors de l'import: ${r instanceof Error ? r.message : "Erreur inconnue"}`);
196
- }
197
- }, [i, y, p, x, b, v, E]), m = u(() => {
198
- const c = document.createElement("input");
199
- return c.type = "file", c.accept = i.accept, c.multiple = !1, c;
200
- }, [i.accept]), g = u(() => new Promise((c, e) => {
201
- const o = m();
202
- o.onchange = async (r) => {
203
- const s = r.target.files?.[0];
204
- if (!s) {
205
- e(new Error("Aucun fichier sélectionné"));
206
- return;
207
- }
208
- try {
209
- const t = await w(s);
210
- c(t);
211
- } catch (t) {
212
- e(t);
213
- }
214
- }, o.click();
215
- }), [m, w]);
216
- return {
217
- importData: w,
218
- importWithUI: g,
219
- supportedFormats: i.accept?.split(",") || [],
220
- isFormatSupported: (c) => {
221
- const e = c.split(".").pop()?.toLowerCase();
222
- return i.accept?.includes(e || "") || !1;
223
- }
224
- };
225
- }
226
- export {
227
- D as a,
228
- X as u
229
- };