@wakastellar/ui 2.0.0 → 2.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 (290) hide show
  1. package/dist/cli/commands/add.d.ts +7 -0
  2. package/dist/cli/commands/init.d.ts +6 -0
  3. package/dist/cli/commands/list.d.ts +5 -0
  4. package/dist/cli/commands/search.d.ts +1 -0
  5. package/dist/cli/index.cjs +4844 -0
  6. package/dist/cli/index.d.ts +1 -0
  7. package/dist/cli/utils/config.d.ts +29 -0
  8. package/dist/cli/utils/logger.d.ts +20 -0
  9. package/dist/cli/utils/registry.d.ts +23 -0
  10. package/package.json +14 -3
  11. package/src/blocks/activity-timeline/index.tsx +586 -0
  12. package/src/blocks/calendar-view/index.tsx +756 -0
  13. package/src/blocks/chat/index.tsx +1018 -0
  14. package/src/blocks/chat/widget.tsx +504 -0
  15. package/src/blocks/dashboard/index.tsx +522 -0
  16. package/src/blocks/empty-states/index.tsx +452 -0
  17. package/src/blocks/error-pages/index.tsx +426 -0
  18. package/src/blocks/faq/index.tsx +479 -0
  19. package/src/blocks/file-manager/index.tsx +890 -0
  20. package/src/blocks/footer/index.tsx +133 -0
  21. package/src/blocks/header/index.tsx +357 -0
  22. package/src/blocks/headtab/index.tsx +139 -0
  23. package/src/blocks/i18n-editor/index.tsx +1016 -0
  24. package/src/blocks/index.ts +80 -0
  25. package/src/blocks/kanban-board/index.tsx +779 -0
  26. package/src/blocks/landing/index.tsx +677 -0
  27. package/src/blocks/language-selector/index.tsx +88 -0
  28. package/src/blocks/layout/index.tsx +159 -0
  29. package/src/blocks/login/index.tsx +339 -0
  30. package/src/blocks/login/types.ts +131 -0
  31. package/src/blocks/pricing/index.tsx +564 -0
  32. package/src/blocks/profile/index.tsx +746 -0
  33. package/src/blocks/settings/index.tsx +558 -0
  34. package/src/blocks/sidebar/index.tsx +713 -0
  35. package/src/blocks/theme-creator-block/index.tsx +835 -0
  36. package/src/blocks/user-management/index.tsx +1037 -0
  37. package/src/blocks/wizard/index.tsx +719 -0
  38. package/src/components/DataTable/DataTable.tsx +406 -0
  39. package/src/components/DataTable/DataTableAdvanced.tsx +720 -0
  40. package/src/components/DataTable/DataTableBody.tsx +216 -0
  41. package/src/components/DataTable/DataTableCell.tsx +172 -0
  42. package/src/components/DataTable/DataTableColumnResizer.tsx +62 -0
  43. package/src/components/DataTable/DataTableConflictResolver.tsx +478 -0
  44. package/src/components/DataTable/DataTableContextMenu.tsx +219 -0
  45. package/src/components/DataTable/DataTableEditCell.tsx +279 -0
  46. package/src/components/DataTable/DataTableFilterBuilder.tsx +519 -0
  47. package/src/components/DataTable/DataTableFilters.tsx +535 -0
  48. package/src/components/DataTable/DataTableGrouping.tsx +147 -0
  49. package/src/components/DataTable/DataTableHeader.tsx +172 -0
  50. package/src/components/DataTable/DataTablePagination.tsx +125 -0
  51. package/src/components/DataTable/DataTableSelection.tsx +269 -0
  52. package/src/components/DataTable/DataTableSyncStatus.tsx +281 -0
  53. package/src/components/DataTable/DataTableToolbar.tsx +262 -0
  54. package/src/components/DataTable/README.md +446 -0
  55. package/src/components/DataTable/__tests__/DataTableAdvanced.test.tsx +426 -0
  56. package/src/components/DataTable/__tests__/DataTableEdit.test.tsx +329 -0
  57. package/src/components/DataTable/__tests__/useDataTableAdvanced.test.ts +455 -0
  58. package/src/components/DataTable/examples/EditExample.tsx +166 -0
  59. package/src/components/DataTable/formatters/index.ts +335 -0
  60. package/src/components/DataTable/hooks/__tests__/useDataTableEdit.test.ts +239 -0
  61. package/src/components/DataTable/hooks/useDataTable.ts +145 -0
  62. package/src/components/DataTable/hooks/useDataTableAdvanced.ts +342 -0
  63. package/src/components/DataTable/hooks/useDataTableAdvancedFilters.ts +637 -0
  64. package/src/components/DataTable/hooks/useDataTableColumnTemplates.ts +186 -0
  65. package/src/components/DataTable/hooks/useDataTableEdit.ts +167 -0
  66. package/src/components/DataTable/hooks/useDataTableExport.ts +227 -0
  67. package/src/components/DataTable/hooks/useDataTableImport.ts +216 -0
  68. package/src/components/DataTable/hooks/useDataTableOffline.ts +481 -0
  69. package/src/components/DataTable/hooks/useDataTableTheme.ts +213 -0
  70. package/src/components/DataTable/hooks/useDataTableVirtualization.ts +99 -0
  71. package/src/components/DataTable/hooks/useTableLayout.ts +85 -0
  72. package/src/components/DataTable/index.ts +81 -0
  73. package/src/components/DataTable/services/IndexedDBService.ts +504 -0
  74. package/src/components/DataTable/templates/index.tsx +803 -0
  75. package/src/components/DataTable/types.ts +504 -0
  76. package/src/components/DataTable/utils.ts +164 -0
  77. package/src/components/DataTable/workers/exportWorker.ts +213 -0
  78. package/src/components/accordion/index.tsx +61 -0
  79. package/src/components/alert/index.tsx +61 -0
  80. package/src/components/alert-dialog/index.tsx +146 -0
  81. package/src/components/aspect-ratio/index.tsx +12 -0
  82. package/src/components/avatar/index.tsx +54 -0
  83. package/src/components/badge/Badge.stories.tsx +64 -0
  84. package/src/components/badge/index.tsx +38 -0
  85. package/src/components/button/Button.stories.tsx +173 -0
  86. package/src/components/button/index.tsx +56 -0
  87. package/src/components/calendar/index.tsx +73 -0
  88. package/src/components/card/index.tsx +78 -0
  89. package/src/components/checkbox/index.tsx +34 -0
  90. package/src/components/code/index.tsx +229 -0
  91. package/src/components/collapsible/index.tsx +16 -0
  92. package/src/components/command/index.tsx +162 -0
  93. package/src/components/context-menu/index.tsx +204 -0
  94. package/src/components/dialog/index.tsx +126 -0
  95. package/src/components/dropdown-menu/index.tsx +204 -0
  96. package/src/components/error-boundary/ErrorBoundary.tsx +281 -0
  97. package/src/components/error-boundary/index.ts +7 -0
  98. package/src/components/form/index.tsx +183 -0
  99. package/src/components/hover-card/index.tsx +33 -0
  100. package/src/components/index.ts +368 -0
  101. package/src/components/input/Input.stories.tsx +100 -0
  102. package/src/components/input/index.tsx +27 -0
  103. package/src/components/input-otp/index.tsx +277 -0
  104. package/src/components/label/index.tsx +30 -0
  105. package/src/components/language-selector/index.tsx +341 -0
  106. package/src/components/menubar/index.tsx +240 -0
  107. package/src/components/navigation-menu/index.tsx +134 -0
  108. package/src/components/popover/index.tsx +35 -0
  109. package/src/components/progress/index.tsx +32 -0
  110. package/src/components/radio-group/index.tsx +48 -0
  111. package/src/components/scroll-area/index.tsx +52 -0
  112. package/src/components/select/index.tsx +164 -0
  113. package/src/components/separator/index.tsx +35 -0
  114. package/src/components/sheet/index.tsx +147 -0
  115. package/src/components/skeleton/index.tsx +22 -0
  116. package/src/components/slider/index.tsx +32 -0
  117. package/src/components/switch/index.tsx +33 -0
  118. package/src/components/table/index.tsx +117 -0
  119. package/src/components/tabs/index.tsx +59 -0
  120. package/src/components/textarea/index.tsx +30 -0
  121. package/src/components/theme-selector/index.tsx +327 -0
  122. package/src/components/toast/index.tsx +133 -0
  123. package/src/components/toaster/index.tsx +34 -0
  124. package/src/components/toggle/index.tsx +49 -0
  125. package/src/components/tooltip/index.tsx +34 -0
  126. package/src/components/typography/index.tsx +276 -0
  127. package/src/components/waka-3d-pie-chart/index.tsx +486 -0
  128. package/src/components/waka-achievement-unlock/index.tsx +716 -0
  129. package/src/components/waka-activity-feed/index.tsx +686 -0
  130. package/src/components/waka-address-autocomplete/index.tsx +1202 -0
  131. package/src/components/waka-admincrumb/index.tsx +349 -0
  132. package/src/components/waka-alert-stack/index.tsx +827 -0
  133. package/src/components/waka-allocation-matrix/index.tsx +1278 -0
  134. package/src/components/waka-approval-chain/index.tsx +766 -0
  135. package/src/components/waka-audit-log/index.tsx +1475 -0
  136. package/src/components/waka-autocomplete/index.tsx +358 -0
  137. package/src/components/waka-badge-showcase/index.tsx +704 -0
  138. package/src/components/waka-barcode/index.tsx +260 -0
  139. package/src/components/waka-biometric-prompt/index.tsx +765 -0
  140. package/src/components/waka-bottom-sheet/index.tsx +495 -0
  141. package/src/components/waka-breadcrumb/index.tsx +376 -0
  142. package/src/components/waka-breadcrumb-path/index.tsx +513 -0
  143. package/src/components/waka-budget-burn/index.tsx +1234 -0
  144. package/src/components/waka-capacity-planner/index.tsx +1107 -0
  145. package/src/components/waka-carousel/index.tsx +893 -0
  146. package/src/components/waka-cart-summary/index.tsx +1055 -0
  147. package/src/components/waka-challenge-timer/index.tsx +1044 -0
  148. package/src/components/waka-charts/WakaAreaChart.tsx +251 -0
  149. package/src/components/waka-charts/WakaBarChart.tsx +222 -0
  150. package/src/components/waka-charts/WakaChart.tsx +124 -0
  151. package/src/components/waka-charts/WakaLineChart.tsx +219 -0
  152. package/src/components/waka-charts/WakaMiniChart.tsx +133 -0
  153. package/src/components/waka-charts/WakaPieChart.tsx +214 -0
  154. package/src/components/waka-charts/WakaSparkline.tsx +229 -0
  155. package/src/components/waka-charts/dataTableHelpers.ts +109 -0
  156. package/src/components/waka-charts/hooks/useChartTheme.ts +123 -0
  157. package/src/components/waka-charts/hooks/useRechartsLoader.ts +234 -0
  158. package/src/components/waka-charts/index.ts +90 -0
  159. package/src/components/waka-charts/types.ts +330 -0
  160. package/src/components/waka-chat-bubble/index.tsx +1060 -0
  161. package/src/components/waka-checklist/index.tsx +1067 -0
  162. package/src/components/waka-checkout-stepper/index.tsx +976 -0
  163. package/src/components/waka-cohort-table/index.tsx +1011 -0
  164. package/src/components/waka-color-picker/index.tsx +447 -0
  165. package/src/components/waka-combo-counter/index.tsx +864 -0
  166. package/src/components/waka-combobox/index.tsx +497 -0
  167. package/src/components/waka-command-bar/index.tsx +403 -0
  168. package/src/components/waka-compare-period/index.tsx +1230 -0
  169. package/src/components/waka-connection-matrix/index.tsx +1053 -0
  170. package/src/components/waka-contribution-graph/index.tsx +552 -0
  171. package/src/components/waka-cost-breakdown/index.tsx +1065 -0
  172. package/src/components/waka-coupon-input/index.tsx +592 -0
  173. package/src/components/waka-credit-card-input/index.tsx +982 -0
  174. package/src/components/waka-daily-reward/index.tsx +762 -0
  175. package/src/components/waka-date-range-picker/index.tsx +378 -0
  176. package/src/components/waka-datetime-picker/index.tsx +793 -0
  177. package/src/components/waka-datetime-picker.form-integration/index.tsx +402 -0
  178. package/src/components/waka-deployment-lane/index.tsx +673 -0
  179. package/src/components/waka-device-trust/index.tsx +1259 -0
  180. package/src/components/waka-dock/index.tsx +285 -0
  181. package/src/components/waka-drawer/index.tsx +319 -0
  182. package/src/components/waka-empty-state/index.tsx +545 -0
  183. package/src/components/waka-error-shake/index.tsx +398 -0
  184. package/src/components/waka-feature-announcement/index.tsx +991 -0
  185. package/src/components/waka-file-upload/index.tsx +437 -0
  186. package/src/components/waka-floating-nav/index.tsx +413 -0
  187. package/src/components/waka-flow-diagram/index.tsx +508 -0
  188. package/src/components/waka-funnel-chart/index.tsx +823 -0
  189. package/src/components/waka-glow-card/index.tsx +246 -0
  190. package/src/components/waka-goal-progress/index.tsx +1025 -0
  191. package/src/components/waka-haptic-button/index.tsx +388 -0
  192. package/src/components/waka-health-pulse/index.tsx +451 -0
  193. package/src/components/waka-heatmap/index.tsx +1026 -0
  194. package/src/components/waka-hotspot/index.tsx +682 -0
  195. package/src/components/waka-image/index.tsx +373 -0
  196. package/src/components/waka-incident-timeline/index.tsx +686 -0
  197. package/src/components/waka-invoice-preview/index.tsx +829 -0
  198. package/src/components/waka-kanban/index.tsx +646 -0
  199. package/src/components/waka-kpi-dashboard/index.tsx +755 -0
  200. package/src/components/waka-leaderboard/index.tsx +746 -0
  201. package/src/components/waka-level-progress/index.tsx +665 -0
  202. package/src/components/waka-liquid-button/index.tsx +520 -0
  203. package/src/components/waka-loading-orbit/index.tsx +478 -0
  204. package/src/components/waka-loot-box/index.tsx +1091 -0
  205. package/src/components/waka-magic-link/index.tsx +321 -0
  206. package/src/components/waka-magnetic-button/index.tsx +567 -0
  207. package/src/components/waka-mention-input/index.tsx +953 -0
  208. package/src/components/waka-metric-sparkline/index.tsx +627 -0
  209. package/src/components/waka-milestone-road/index.tsx +1064 -0
  210. package/src/components/waka-modal/index.tsx +374 -0
  211. package/src/components/waka-morph-button/index.tsx +495 -0
  212. package/src/components/waka-network-topology/index.tsx +801 -0
  213. package/src/components/waka-notifications/index.tsx +414 -0
  214. package/src/components/waka-number-input/index.tsx +373 -0
  215. package/src/components/waka-orbital-menu/index.tsx +445 -0
  216. package/src/components/waka-order-tracker/index.tsx +1041 -0
  217. package/src/components/waka-pagination/index.tsx +393 -0
  218. package/src/components/waka-password-strength/index.tsx +824 -0
  219. package/src/components/waka-payment-method-picker/index.tsx +715 -0
  220. package/src/components/waka-permission-matrix/index.tsx +1302 -0
  221. package/src/components/waka-phone-input/index.tsx +801 -0
  222. package/src/components/waka-pipeline-view/index.tsx +604 -0
  223. package/src/components/waka-player-card/index.tsx +691 -0
  224. package/src/components/waka-points-popup/index.tsx +366 -0
  225. package/src/components/waka-power-up/index.tsx +1155 -0
  226. package/src/components/waka-presence-indicator/index.tsx +1181 -0
  227. package/src/components/waka-pricing-table/index.tsx +755 -0
  228. package/src/components/waka-product-card/index.tsx +786 -0
  229. package/src/components/waka-progress-onboarding/index.tsx +878 -0
  230. package/src/components/waka-pull-to-refresh/index.tsx +451 -0
  231. package/src/components/waka-qrcode/index.tsx +232 -0
  232. package/src/components/waka-quest-card/index.tsx +1275 -0
  233. package/src/components/waka-quota-bar/index.tsx +693 -0
  234. package/src/components/waka-radar-score/index.tsx +512 -0
  235. package/src/components/waka-rank-badge/index.tsx +813 -0
  236. package/src/components/waka-rating-input/index.tsx +560 -0
  237. package/src/components/waka-reaction-picker/index.tsx +1062 -0
  238. package/src/components/waka-region-map/index.tsx +730 -0
  239. package/src/components/waka-resource-gauge/index.tsx +654 -0
  240. package/src/components/waka-resource-pool/index.tsx +1035 -0
  241. package/src/components/waka-rich-text-editor/index.tsx +594 -0
  242. package/src/components/waka-rollback-slider/index.tsx +891 -0
  243. package/src/components/waka-sankey-diagram/index.tsx +1032 -0
  244. package/src/components/waka-schedule-picker/index.tsx +1060 -0
  245. package/src/components/waka-scratch-card/index.tsx +914 -0
  246. package/src/components/waka-season-pass/index.tsx +886 -0
  247. package/src/components/waka-security-score/index.tsx +1126 -0
  248. package/src/components/waka-segmented-control/index.tsx +238 -0
  249. package/src/components/waka-server-rack/index.tsx +764 -0
  250. package/src/components/waka-session-manager/index.tsx +815 -0
  251. package/src/components/waka-signature-pad/index.tsx +744 -0
  252. package/src/components/waka-skeleton-wave/index.tsx +454 -0
  253. package/src/components/waka-skill-tree/index.tsx +1031 -0
  254. package/src/components/waka-sla-tracker/index.tsx +798 -0
  255. package/src/components/waka-slider-range/index.tsx +765 -0
  256. package/src/components/waka-spin-wheel/index.tsx +671 -0
  257. package/src/components/waka-spinner/index.tsx +284 -0
  258. package/src/components/waka-spotlight/index.tsx +410 -0
  259. package/src/components/waka-stat/index.tsx +428 -0
  260. package/src/components/waka-stats-hexagon/index.tsx +824 -0
  261. package/src/components/waka-status-matrix/index.tsx +565 -0
  262. package/src/components/waka-stepper/index.tsx +489 -0
  263. package/src/components/waka-streak-counter/index.tsx +334 -0
  264. package/src/components/waka-success-explosion/index.tsx +453 -0
  265. package/src/components/waka-swipe-card/index.tsx +574 -0
  266. package/src/components/waka-tabs-morph/index.tsx +509 -0
  267. package/src/components/waka-tag-input/index.tsx +877 -0
  268. package/src/components/waka-team-banner/index.tsx +1183 -0
  269. package/src/components/waka-terminal-output/index.tsx +836 -0
  270. package/src/components/waka-theme-creator/index.tsx +762 -0
  271. package/src/components/waka-theme-manager/index.tsx +654 -0
  272. package/src/components/waka-thread-view/index.tsx +874 -0
  273. package/src/components/waka-tilt-card/index.tsx +250 -0
  274. package/src/components/waka-time-picker/index.tsx +479 -0
  275. package/src/components/waka-timeline/index.tsx +385 -0
  276. package/src/components/waka-tooltip-tour/index.tsx +855 -0
  277. package/src/components/waka-tour-guide/index.tsx +920 -0
  278. package/src/components/waka-tournament-bracket/index.tsx +1276 -0
  279. package/src/components/waka-tree/index.tsx +557 -0
  280. package/src/components/waka-treemap-chart/index.tsx +1031 -0
  281. package/src/components/waka-two-factor-setup/index.tsx +995 -0
  282. package/src/components/waka-typewriter/index.tsx +566 -0
  283. package/src/components/waka-typing-indicator/index.tsx +649 -0
  284. package/src/components/waka-versus-card/index.tsx +1026 -0
  285. package/src/components/waka-video/index.tsx +557 -0
  286. package/src/components/waka-video-call/index.tsx +1087 -0
  287. package/src/components/waka-virtual-list/index.tsx +327 -0
  288. package/src/components/waka-voice-message/index.tsx +1019 -0
  289. package/src/components/waka-welcome-modal/index.tsx +790 -0
  290. package/src/components/waka-xp-bar/index.tsx +799 -0
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Configuration des couleurs du thème
3
+ */
4
+ export interface LoginColorConfig {
5
+ /** Couleur principale */
6
+ primary: string
7
+ /** Couleur secondaire */
8
+ secondary: string
9
+ /** Couleur d'accent */
10
+ accent: string
11
+ }
12
+
13
+ /**
14
+ * Configuration du thème
15
+ */
16
+ export interface LoginThemeConfig {
17
+ /** Nom du thème */
18
+ name: string
19
+ /** Mode sombre activé */
20
+ dark_mode: boolean
21
+ }
22
+
23
+ /**
24
+ * Assets (logos et images)
25
+ */
26
+ export interface LoginAssetsConfig {
27
+ /** Logo du thème en mode sombre */
28
+ theme_logo_dark?: string
29
+ /** Logo du thème en mode clair */
30
+ theme_logo_light?: string
31
+ /** Image du thème en mode clair */
32
+ theme_image_light?: string
33
+ /** Image du thème en mode sombre */
34
+ theme_image_dark?: string
35
+ /** Image du sponsor en mode clair */
36
+ sponsor_image_light?: string
37
+ /** Image du sponsor en mode sombre */
38
+ sponsor_image_dark?: string
39
+ }
40
+
41
+ /**
42
+ * Options d'inscription et de connexion
43
+ */
44
+ export interface LoginSignupOptions {
45
+ /** Autoriser la connexion classique */
46
+ allow_login: boolean
47
+ /** Requérir la MFA */
48
+ require_MFA: boolean
49
+ /** MFA par email */
50
+ MFA_email: boolean
51
+ /** MFA par WhatsApp */
52
+ MFA_whatsapp: boolean
53
+ /** MFA par RCS */
54
+ MFA_RCS: boolean
55
+ /** Autoriser SSO Google */
56
+ allow_sso_google: boolean
57
+ /** Autoriser SSO Microsoft */
58
+ allow_sso_microsoft: boolean
59
+ /** Autoriser SSO Apple */
60
+ allow_sso_apple: boolean
61
+ /** Autoriser SSO LinkedIn */
62
+ allow_sso_linkedIn: boolean
63
+ /** Autoriser SSO GitHub */
64
+ allow_sso_github: boolean
65
+ /** Autoriser SSO Facebook */
66
+ allow_sso_facebook: boolean
67
+ /** Autoriser SSO Instagram */
68
+ allow_sso_instagram: boolean
69
+ /** Autoriser SSO France Connect */
70
+ allow_sso_france_connect: boolean
71
+ }
72
+
73
+ /**
74
+ * Configuration complète du composant Login
75
+ *
76
+ * Structure JSON attendue :
77
+ * {
78
+ * "color_json": {
79
+ * "primary": "#000000",
80
+ * "secondary": "#FFFFFF",
81
+ * "accent": "#FF9900"
82
+ * },
83
+ * "theme_json": {
84
+ * "name": "Default Theme",
85
+ * "dark_mode": true
86
+ * },
87
+ * "assets": {
88
+ * "theme_logo_dark": "https://...",
89
+ * "theme_logo_light": "https://...",
90
+ * "theme_image_light": "https://...",
91
+ * "theme_image_dark": "https://...",
92
+ * "sponsor_image_light": "https://...",
93
+ * "sponsor_image_dark": "https://..."
94
+ * },
95
+ * "waka_powered": true,
96
+ * "lang_code": "fr_FR",
97
+ * "signup_options": {
98
+ * "allow_login": true,
99
+ * "require_MFA": false,
100
+ * "MFA_email": true,
101
+ * "MFA_whatsapp": false,
102
+ * "MFA_RCS": false,
103
+ * "allow_sso_google": true,
104
+ * "allow_sso_microsoft": true,
105
+ * "allow_sso_apple": false,
106
+ * "allow_sso_linkedIn": false,
107
+ * "allow_sso_github": false,
108
+ * "allow_sso_facebook": false,
109
+ * "allow_sso_instagram": false,
110
+ * "allow_sso_france_connect": false
111
+ * },
112
+ * "oem_resolution_rules": ["..."]
113
+ * }
114
+ */
115
+ export interface LoginConfig {
116
+ /** Configuration des couleurs du thème */
117
+ color_json: LoginColorConfig
118
+ /** Configuration du thème (nom et mode dark/light) */
119
+ theme_json: LoginThemeConfig
120
+ /** Assets (logos et images selon le thème) */
121
+ assets: LoginAssetsConfig
122
+ /** Afficher le badge "Waka Powered" en bas du formulaire */
123
+ waka_powered: boolean
124
+ /** Code de langue (ex: "fr_FR", "en_US") - utilisé pour l'i18n */
125
+ lang_code: string
126
+ /** Options d'inscription et de connexion (SSO, MFA, etc.) */
127
+ signup_options: LoginSignupOptions
128
+ /** Règles de résolution OEM (optionnel, utilisé pour la documentation/logique métier) */
129
+ oem_resolution_rules?: string[]
130
+ }
131
+
@@ -0,0 +1,564 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "../../utils"
5
+ import { Button } from "../../components/button"
6
+ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../../components/card"
7
+ import { Badge } from "../../components/badge"
8
+ import { Switch } from "../../components/switch"
9
+ import { Label } from "../../components/label"
10
+ import {
11
+ Check,
12
+ X,
13
+ Zap,
14
+ HelpCircle,
15
+ } from "lucide-react"
16
+ import {
17
+ Tooltip,
18
+ TooltipContent,
19
+ TooltipProvider,
20
+ TooltipTrigger,
21
+ } from "../../components/tooltip"
22
+
23
+ // ============================================
24
+ // TYPES
25
+ // ============================================
26
+
27
+ export interface PricingFeature {
28
+ name: string
29
+ included: boolean | "partial" | "limited"
30
+ tooltip?: string
31
+ value?: string
32
+ }
33
+
34
+ export interface PricingPlan {
35
+ id: string
36
+ name: string
37
+ description?: string
38
+ price: number | string
39
+ priceYearly?: number | string
40
+ currency?: string
41
+ period?: string
42
+ periodYearly?: string
43
+ features: PricingFeature[]
44
+ buttonText?: string
45
+ buttonVariant?: "default" | "outline" | "secondary"
46
+ onSelect?: () => void
47
+ href?: string
48
+ popular?: boolean
49
+ badge?: string
50
+ disabled?: boolean
51
+ }
52
+
53
+ export interface PricingFAQ {
54
+ question: string
55
+ answer: string
56
+ }
57
+
58
+ export interface WakaPricingProps {
59
+ /** Titre */
60
+ title?: string
61
+ /** Description */
62
+ description?: string
63
+ /** Plans de tarification */
64
+ plans: PricingPlan[]
65
+ /** Afficher le toggle mensuel/annuel */
66
+ showBillingToggle?: boolean
67
+ /** Période de facturation */
68
+ billingPeriod?: "monthly" | "yearly"
69
+ /** Callback changement de période */
70
+ onBillingPeriodChange?: (period: "monthly" | "yearly") => void
71
+ /** Réduction annuelle (ex: "20%") */
72
+ yearlyDiscount?: string
73
+ /** FAQ */
74
+ faq?: PricingFAQ[]
75
+ /** Titre de la FAQ */
76
+ faqTitle?: string
77
+ /** Layout */
78
+ layout?: "cards" | "table"
79
+ /** Nombre de colonnes */
80
+ columns?: 2 | 3 | 4
81
+ /** Afficher la comparaison de features */
82
+ showComparison?: boolean
83
+ /** Classes CSS additionnelles */
84
+ className?: string
85
+ }
86
+
87
+ // ============================================
88
+ // SUB-COMPONENTS
89
+ // ============================================
90
+
91
+ interface PricingToggleProps {
92
+ period: "monthly" | "yearly"
93
+ onChange: (period: "monthly" | "yearly") => void
94
+ yearlyDiscount?: string
95
+ }
96
+
97
+ function PricingToggle({ period, onChange, yearlyDiscount }: PricingToggleProps) {
98
+ return (
99
+ <div className="flex items-center justify-center gap-4 mb-8">
100
+ <Label
101
+ htmlFor="billing-toggle"
102
+ className={cn(
103
+ "cursor-pointer transition-colors",
104
+ period === "monthly" ? "text-foreground" : "text-muted-foreground"
105
+ )}
106
+ >
107
+ Mensuel
108
+ </Label>
109
+ <Switch
110
+ id="billing-toggle"
111
+ checked={period === "yearly"}
112
+ onCheckedChange={(checked) => onChange(checked ? "yearly" : "monthly")}
113
+ />
114
+ <Label
115
+ htmlFor="billing-toggle"
116
+ className={cn(
117
+ "cursor-pointer transition-colors flex items-center gap-2",
118
+ period === "yearly" ? "text-foreground" : "text-muted-foreground"
119
+ )}
120
+ >
121
+ Annuel
122
+ {yearlyDiscount && (
123
+ <Badge variant="secondary" className="text-xs">
124
+ -{yearlyDiscount}
125
+ </Badge>
126
+ )}
127
+ </Label>
128
+ </div>
129
+ )
130
+ }
131
+
132
+ interface PricingCardProps {
133
+ plan: PricingPlan
134
+ billingPeriod: "monthly" | "yearly"
135
+ }
136
+
137
+ function PricingCard({ plan, billingPeriod }: PricingCardProps) {
138
+ const price = billingPeriod === "yearly" && plan.priceYearly !== undefined
139
+ ? plan.priceYearly
140
+ : plan.price
141
+ const period = billingPeriod === "yearly" && plan.periodYearly
142
+ ? plan.periodYearly
143
+ : plan.period || "/mois"
144
+
145
+ const isCustomPrice = typeof price === "string"
146
+
147
+ return (
148
+ <Card
149
+ className={cn(
150
+ "relative flex flex-col",
151
+ plan.popular && "border-primary shadow-lg scale-105"
152
+ )}
153
+ >
154
+ {/* Popular badge */}
155
+ {plan.popular && (
156
+ <div className="absolute -top-3 left-1/2 -translate-x-1/2">
157
+ <Badge className="px-3">
158
+ <Zap className="h-3 w-3 mr-1" />
159
+ {plan.badge || "Populaire"}
160
+ </Badge>
161
+ </div>
162
+ )}
163
+
164
+ <CardHeader className="text-center pb-2">
165
+ <CardTitle className="text-xl">{plan.name}</CardTitle>
166
+ {plan.description && (
167
+ <CardDescription>{plan.description}</CardDescription>
168
+ )}
169
+ </CardHeader>
170
+
171
+ <CardContent className="flex-1">
172
+ {/* Price */}
173
+ <div className="text-center mb-6">
174
+ {isCustomPrice ? (
175
+ <div className="text-3xl font-bold">{price}</div>
176
+ ) : (
177
+ <div className="flex items-baseline justify-center">
178
+ <span className="text-sm text-muted-foreground mr-1">
179
+ {plan.currency || "€"}
180
+ </span>
181
+ <span className="text-4xl font-bold">{price}</span>
182
+ <span className="text-sm text-muted-foreground ml-1">
183
+ {period}
184
+ </span>
185
+ </div>
186
+ )}
187
+ </div>
188
+
189
+ {/* Features */}
190
+ <ul className="space-y-3">
191
+ {plan.features.map((feature, index) => (
192
+ <li key={index} className="flex items-start gap-2">
193
+ {feature.included === true ? (
194
+ <Check className="h-5 w-5 text-green-500 flex-shrink-0" />
195
+ ) : feature.included === "partial" || feature.included === "limited" ? (
196
+ <Check className="h-5 w-5 text-yellow-500 flex-shrink-0" />
197
+ ) : (
198
+ <X className="h-5 w-5 text-muted-foreground flex-shrink-0" />
199
+ )}
200
+ <span
201
+ className={cn(
202
+ "text-sm",
203
+ !feature.included && "text-muted-foreground"
204
+ )}
205
+ >
206
+ {feature.name}
207
+ {feature.value && (
208
+ <span className="text-muted-foreground ml-1">
209
+ ({feature.value})
210
+ </span>
211
+ )}
212
+ </span>
213
+ {feature.tooltip && (
214
+ <TooltipProvider>
215
+ <Tooltip>
216
+ <TooltipTrigger asChild>
217
+ <HelpCircle className="h-4 w-4 text-muted-foreground cursor-help" />
218
+ </TooltipTrigger>
219
+ <TooltipContent>
220
+ <p className="max-w-xs">{feature.tooltip}</p>
221
+ </TooltipContent>
222
+ </Tooltip>
223
+ </TooltipProvider>
224
+ )}
225
+ </li>
226
+ ))}
227
+ </ul>
228
+ </CardContent>
229
+
230
+ <CardFooter>
231
+ <Button
232
+ className="w-full"
233
+ variant={plan.buttonVariant || (plan.popular ? "default" : "outline")}
234
+ onClick={plan.onSelect}
235
+ disabled={plan.disabled}
236
+ asChild={!!plan.href}
237
+ >
238
+ {plan.href ? (
239
+ <a href={plan.href}>{plan.buttonText || "Choisir"}</a>
240
+ ) : (
241
+ plan.buttonText || "Choisir"
242
+ )}
243
+ </Button>
244
+ </CardFooter>
245
+ </Card>
246
+ )
247
+ }
248
+
249
+ interface PricingTableProps {
250
+ plans: PricingPlan[]
251
+ billingPeriod: "monthly" | "yearly"
252
+ }
253
+
254
+ function PricingTable({ plans, billingPeriod }: PricingTableProps) {
255
+ // Get all unique features
256
+ const allFeatures = Array.from(
257
+ new Set(plans.flatMap((plan) => plan.features.map((f) => f.name)))
258
+ )
259
+
260
+ return (
261
+ <div className="overflow-x-auto">
262
+ <table className="w-full border-collapse">
263
+ <thead>
264
+ <tr>
265
+ <th className="text-left p-4 border-b bg-muted/50">Fonctionnalité</th>
266
+ {plans.map((plan) => (
267
+ <th
268
+ key={plan.id}
269
+ className={cn(
270
+ "text-center p-4 border-b min-w-[150px]",
271
+ plan.popular && "bg-primary/5"
272
+ )}
273
+ >
274
+ <div className="font-bold">{plan.name}</div>
275
+ {plan.popular && (
276
+ <Badge className="mt-1" variant="default">
277
+ Populaire
278
+ </Badge>
279
+ )}
280
+ </th>
281
+ ))}
282
+ </tr>
283
+ {/* Price row */}
284
+ <tr>
285
+ <td className="p-4 border-b bg-muted/50 font-medium">Prix</td>
286
+ {plans.map((plan) => {
287
+ const price = billingPeriod === "yearly" && plan.priceYearly !== undefined
288
+ ? plan.priceYearly
289
+ : plan.price
290
+ const period = billingPeriod === "yearly" && plan.periodYearly
291
+ ? plan.periodYearly
292
+ : plan.period || "/mois"
293
+ const isCustomPrice = typeof price === "string"
294
+
295
+ return (
296
+ <td
297
+ key={plan.id}
298
+ className={cn(
299
+ "text-center p-4 border-b",
300
+ plan.popular && "bg-primary/5"
301
+ )}
302
+ >
303
+ {isCustomPrice ? (
304
+ <span className="font-bold">{price}</span>
305
+ ) : (
306
+ <span className="font-bold">
307
+ {plan.currency || "€"}{price}
308
+ <span className="text-sm font-normal text-muted-foreground">
309
+ {period}
310
+ </span>
311
+ </span>
312
+ )}
313
+ </td>
314
+ )
315
+ })}
316
+ </tr>
317
+ </thead>
318
+ <tbody>
319
+ {allFeatures.map((featureName, index) => (
320
+ <tr key={index} className={index % 2 === 0 ? "bg-muted/20" : ""}>
321
+ <td className="p-4 border-b">{featureName}</td>
322
+ {plans.map((plan) => {
323
+ const feature = plan.features.find((f) => f.name === featureName)
324
+ return (
325
+ <td
326
+ key={plan.id}
327
+ className={cn(
328
+ "text-center p-4 border-b",
329
+ plan.popular && "bg-primary/5"
330
+ )}
331
+ >
332
+ {feature ? (
333
+ feature.included === true ? (
334
+ feature.value ? (
335
+ <span>{feature.value}</span>
336
+ ) : (
337
+ <Check className="h-5 w-5 text-green-500 mx-auto" />
338
+ )
339
+ ) : feature.included === "partial" || feature.included === "limited" ? (
340
+ <span className="text-yellow-600">{feature.value || "Limité"}</span>
341
+ ) : (
342
+ <X className="h-5 w-5 text-muted-foreground mx-auto" />
343
+ )
344
+ ) : (
345
+ <X className="h-5 w-5 text-muted-foreground mx-auto" />
346
+ )}
347
+ </td>
348
+ )
349
+ })}
350
+ </tr>
351
+ ))}
352
+ {/* Action row */}
353
+ <tr>
354
+ <td className="p-4"></td>
355
+ {plans.map((plan) => (
356
+ <td
357
+ key={plan.id}
358
+ className={cn(
359
+ "text-center p-4",
360
+ plan.popular && "bg-primary/5"
361
+ )}
362
+ >
363
+ <Button
364
+ variant={plan.buttonVariant || (plan.popular ? "default" : "outline")}
365
+ onClick={plan.onSelect}
366
+ disabled={plan.disabled}
367
+ asChild={!!plan.href}
368
+ >
369
+ {plan.href ? (
370
+ <a href={plan.href}>{plan.buttonText || "Choisir"}</a>
371
+ ) : (
372
+ plan.buttonText || "Choisir"
373
+ )}
374
+ </Button>
375
+ </td>
376
+ ))}
377
+ </tr>
378
+ </tbody>
379
+ </table>
380
+ </div>
381
+ )
382
+ }
383
+
384
+ interface PricingFAQSectionProps {
385
+ title?: string
386
+ items: PricingFAQ[]
387
+ }
388
+
389
+ function PricingFAQSection({ title = "Questions fréquentes", items }: PricingFAQSectionProps) {
390
+ return (
391
+ <div className="mt-16">
392
+ <h2 className="text-2xl font-bold text-center mb-8">{title}</h2>
393
+ <div className="grid md:grid-cols-2 gap-6 max-w-4xl mx-auto">
394
+ {items.map((item, index) => (
395
+ <div key={index} className="space-y-2">
396
+ <h3 className="font-semibold">{item.question}</h3>
397
+ <p className="text-muted-foreground text-sm">{item.answer}</p>
398
+ </div>
399
+ ))}
400
+ </div>
401
+ </div>
402
+ )
403
+ }
404
+
405
+ // ============================================
406
+ // MAIN COMPONENT
407
+ // ============================================
408
+
409
+ export function WakaPricing({
410
+ title = "Tarification",
411
+ description,
412
+ plans,
413
+ showBillingToggle = true,
414
+ billingPeriod: externalBillingPeriod,
415
+ onBillingPeriodChange,
416
+ yearlyDiscount,
417
+ faq,
418
+ faqTitle,
419
+ layout = "cards",
420
+ columns = 3,
421
+ showComparison = false,
422
+ className,
423
+ }: WakaPricingProps) {
424
+ const [internalBillingPeriod, setInternalBillingPeriod] = React.useState<"monthly" | "yearly">("monthly")
425
+
426
+ const billingPeriod = externalBillingPeriod ?? internalBillingPeriod
427
+
428
+ const handleBillingPeriodChange = (period: "monthly" | "yearly") => {
429
+ if (onBillingPeriodChange) {
430
+ onBillingPeriodChange(period)
431
+ } else {
432
+ setInternalBillingPeriod(period)
433
+ }
434
+ }
435
+
436
+ const columnClasses = {
437
+ 2: "md:grid-cols-2",
438
+ 3: "md:grid-cols-2 lg:grid-cols-3",
439
+ 4: "md:grid-cols-2 lg:grid-cols-4",
440
+ }
441
+
442
+ return (
443
+ <div className={cn("container py-16", className)}>
444
+ {/* Header */}
445
+ <div className="text-center mb-12">
446
+ <h1 className="text-3xl md:text-4xl font-bold tracking-tight mb-4">
447
+ {title}
448
+ </h1>
449
+ {description && (
450
+ <p className="text-lg text-muted-foreground max-w-2xl mx-auto">
451
+ {description}
452
+ </p>
453
+ )}
454
+ </div>
455
+
456
+ {/* Billing toggle */}
457
+ {showBillingToggle && (
458
+ <PricingToggle
459
+ period={billingPeriod}
460
+ onChange={handleBillingPeriodChange}
461
+ yearlyDiscount={yearlyDiscount}
462
+ />
463
+ )}
464
+
465
+ {/* Plans */}
466
+ {layout === "cards" && !showComparison ? (
467
+ <div className={cn("grid gap-6 items-stretch", columnClasses[columns])}>
468
+ {plans.map((plan) => (
469
+ <PricingCard key={plan.id} plan={plan} billingPeriod={billingPeriod} />
470
+ ))}
471
+ </div>
472
+ ) : (
473
+ <PricingTable plans={plans} billingPeriod={billingPeriod} />
474
+ )}
475
+
476
+ {/* FAQ */}
477
+ {faq && faq.length > 0 && (
478
+ <PricingFAQSection title={faqTitle} items={faq} />
479
+ )}
480
+ </div>
481
+ )
482
+ }
483
+
484
+ // ============================================
485
+ // PRESETS
486
+ // ============================================
487
+
488
+ export const defaultPricingPlans: PricingPlan[] = [
489
+ {
490
+ id: "free",
491
+ name: "Gratuit",
492
+ description: "Pour démarrer",
493
+ price: 0,
494
+ priceYearly: 0,
495
+ features: [
496
+ { name: "1 utilisateur", included: true },
497
+ { name: "5 projets", included: true },
498
+ { name: "1 Go de stockage", included: true },
499
+ { name: "Support email", included: true },
500
+ { name: "API Access", included: false },
501
+ { name: "Analytics avancés", included: false },
502
+ { name: "Support prioritaire", included: false },
503
+ ],
504
+ buttonText: "Commencer gratuitement",
505
+ buttonVariant: "outline",
506
+ },
507
+ {
508
+ id: "pro",
509
+ name: "Pro",
510
+ description: "Pour les équipes",
511
+ price: 29,
512
+ priceYearly: 24,
513
+ periodYearly: "/mois (facturé annuellement)",
514
+ popular: true,
515
+ features: [
516
+ { name: "5 utilisateurs", included: true },
517
+ { name: "Projets illimités", included: true },
518
+ { name: "50 Go de stockage", included: true },
519
+ { name: "Support email", included: true },
520
+ { name: "API Access", included: true },
521
+ { name: "Analytics avancés", included: true },
522
+ { name: "Support prioritaire", included: false },
523
+ ],
524
+ buttonText: "Essai gratuit 14 jours",
525
+ },
526
+ {
527
+ id: "enterprise",
528
+ name: "Enterprise",
529
+ description: "Pour les grandes équipes",
530
+ price: "Sur mesure",
531
+ features: [
532
+ { name: "Utilisateurs illimités", included: true },
533
+ { name: "Projets illimités", included: true },
534
+ { name: "Stockage illimité", included: true },
535
+ { name: "Support email", included: true },
536
+ { name: "API Access", included: true },
537
+ { name: "Analytics avancés", included: true },
538
+ { name: "Support prioritaire", included: true },
539
+ ],
540
+ buttonText: "Contacter les ventes",
541
+ buttonVariant: "outline",
542
+ },
543
+ ]
544
+
545
+ export const defaultPricingFAQ: PricingFAQ[] = [
546
+ {
547
+ question: "Puis-je changer de plan à tout moment ?",
548
+ answer: "Oui, vous pouvez upgrader ou downgrader votre plan à tout moment. Les changements prennent effet immédiatement.",
549
+ },
550
+ {
551
+ question: "Y a-t-il une période d'essai ?",
552
+ answer: "Oui, tous nos plans payants incluent une période d'essai gratuite de 14 jours, sans carte bancaire requise.",
553
+ },
554
+ {
555
+ question: "Quels moyens de paiement acceptez-vous ?",
556
+ answer: "Nous acceptons les cartes de crédit (Visa, Mastercard, Amex), PayPal et les virements bancaires pour les entreprises.",
557
+ },
558
+ {
559
+ question: "Puis-je annuler à tout moment ?",
560
+ answer: "Absolument. Vous pouvez annuler votre abonnement à tout moment sans frais supplémentaires.",
561
+ },
562
+ ]
563
+
564
+ export default WakaPricing