@wakastellar/ui 2.0.0 → 2.1.1

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 (291) hide show
  1. package/README.md +71 -8
  2. package/dist/cli/commands/add.d.ts +7 -0
  3. package/dist/cli/commands/init.d.ts +6 -0
  4. package/dist/cli/commands/list.d.ts +5 -0
  5. package/dist/cli/commands/search.d.ts +1 -0
  6. package/dist/cli/index.cjs +6014 -0
  7. package/dist/cli/index.d.ts +1 -0
  8. package/dist/cli/utils/config.d.ts +29 -0
  9. package/dist/cli/utils/logger.d.ts +20 -0
  10. package/dist/cli/utils/registry.d.ts +23 -0
  11. package/package.json +14 -3
  12. package/src/blocks/activity-timeline/index.tsx +586 -0
  13. package/src/blocks/calendar-view/index.tsx +756 -0
  14. package/src/blocks/chat/index.tsx +1018 -0
  15. package/src/blocks/chat/widget.tsx +504 -0
  16. package/src/blocks/dashboard/index.tsx +522 -0
  17. package/src/blocks/empty-states/index.tsx +452 -0
  18. package/src/blocks/error-pages/index.tsx +426 -0
  19. package/src/blocks/faq/index.tsx +479 -0
  20. package/src/blocks/file-manager/index.tsx +890 -0
  21. package/src/blocks/footer/index.tsx +133 -0
  22. package/src/blocks/header/index.tsx +357 -0
  23. package/src/blocks/headtab/index.tsx +139 -0
  24. package/src/blocks/i18n-editor/index.tsx +1016 -0
  25. package/src/blocks/index.ts +80 -0
  26. package/src/blocks/kanban-board/index.tsx +779 -0
  27. package/src/blocks/landing/index.tsx +677 -0
  28. package/src/blocks/language-selector/index.tsx +88 -0
  29. package/src/blocks/layout/index.tsx +159 -0
  30. package/src/blocks/login/index.tsx +339 -0
  31. package/src/blocks/login/types.ts +131 -0
  32. package/src/blocks/pricing/index.tsx +564 -0
  33. package/src/blocks/profile/index.tsx +746 -0
  34. package/src/blocks/settings/index.tsx +558 -0
  35. package/src/blocks/sidebar/index.tsx +713 -0
  36. package/src/blocks/theme-creator-block/index.tsx +835 -0
  37. package/src/blocks/user-management/index.tsx +1037 -0
  38. package/src/blocks/wizard/index.tsx +719 -0
  39. package/src/components/DataTable/DataTable.tsx +406 -0
  40. package/src/components/DataTable/DataTableAdvanced.tsx +720 -0
  41. package/src/components/DataTable/DataTableBody.tsx +216 -0
  42. package/src/components/DataTable/DataTableCell.tsx +172 -0
  43. package/src/components/DataTable/DataTableColumnResizer.tsx +62 -0
  44. package/src/components/DataTable/DataTableConflictResolver.tsx +478 -0
  45. package/src/components/DataTable/DataTableContextMenu.tsx +219 -0
  46. package/src/components/DataTable/DataTableEditCell.tsx +279 -0
  47. package/src/components/DataTable/DataTableFilterBuilder.tsx +519 -0
  48. package/src/components/DataTable/DataTableFilters.tsx +535 -0
  49. package/src/components/DataTable/DataTableGrouping.tsx +147 -0
  50. package/src/components/DataTable/DataTableHeader.tsx +172 -0
  51. package/src/components/DataTable/DataTablePagination.tsx +125 -0
  52. package/src/components/DataTable/DataTableSelection.tsx +269 -0
  53. package/src/components/DataTable/DataTableSyncStatus.tsx +281 -0
  54. package/src/components/DataTable/DataTableToolbar.tsx +262 -0
  55. package/src/components/DataTable/README.md +446 -0
  56. package/src/components/DataTable/__tests__/DataTableAdvanced.test.tsx +426 -0
  57. package/src/components/DataTable/__tests__/DataTableEdit.test.tsx +329 -0
  58. package/src/components/DataTable/__tests__/useDataTableAdvanced.test.ts +455 -0
  59. package/src/components/DataTable/examples/EditExample.tsx +166 -0
  60. package/src/components/DataTable/formatters/index.ts +335 -0
  61. package/src/components/DataTable/hooks/__tests__/useDataTableEdit.test.ts +239 -0
  62. package/src/components/DataTable/hooks/useDataTable.ts +145 -0
  63. package/src/components/DataTable/hooks/useDataTableAdvanced.ts +342 -0
  64. package/src/components/DataTable/hooks/useDataTableAdvancedFilters.ts +637 -0
  65. package/src/components/DataTable/hooks/useDataTableColumnTemplates.ts +186 -0
  66. package/src/components/DataTable/hooks/useDataTableEdit.ts +167 -0
  67. package/src/components/DataTable/hooks/useDataTableExport.ts +227 -0
  68. package/src/components/DataTable/hooks/useDataTableImport.ts +216 -0
  69. package/src/components/DataTable/hooks/useDataTableOffline.ts +481 -0
  70. package/src/components/DataTable/hooks/useDataTableTheme.ts +213 -0
  71. package/src/components/DataTable/hooks/useDataTableVirtualization.ts +99 -0
  72. package/src/components/DataTable/hooks/useTableLayout.ts +85 -0
  73. package/src/components/DataTable/index.ts +81 -0
  74. package/src/components/DataTable/services/IndexedDBService.ts +504 -0
  75. package/src/components/DataTable/templates/index.tsx +803 -0
  76. package/src/components/DataTable/types.ts +504 -0
  77. package/src/components/DataTable/utils.ts +164 -0
  78. package/src/components/DataTable/workers/exportWorker.ts +213 -0
  79. package/src/components/accordion/index.tsx +61 -0
  80. package/src/components/alert/index.tsx +61 -0
  81. package/src/components/alert-dialog/index.tsx +146 -0
  82. package/src/components/aspect-ratio/index.tsx +12 -0
  83. package/src/components/avatar/index.tsx +54 -0
  84. package/src/components/badge/Badge.stories.tsx +64 -0
  85. package/src/components/badge/index.tsx +38 -0
  86. package/src/components/button/Button.stories.tsx +173 -0
  87. package/src/components/button/index.tsx +56 -0
  88. package/src/components/calendar/index.tsx +73 -0
  89. package/src/components/card/index.tsx +78 -0
  90. package/src/components/checkbox/index.tsx +34 -0
  91. package/src/components/code/index.tsx +229 -0
  92. package/src/components/collapsible/index.tsx +16 -0
  93. package/src/components/command/index.tsx +162 -0
  94. package/src/components/context-menu/index.tsx +204 -0
  95. package/src/components/dialog/index.tsx +126 -0
  96. package/src/components/dropdown-menu/index.tsx +204 -0
  97. package/src/components/error-boundary/ErrorBoundary.tsx +281 -0
  98. package/src/components/error-boundary/index.ts +7 -0
  99. package/src/components/form/index.tsx +183 -0
  100. package/src/components/hover-card/index.tsx +33 -0
  101. package/src/components/index.ts +368 -0
  102. package/src/components/input/Input.stories.tsx +100 -0
  103. package/src/components/input/index.tsx +27 -0
  104. package/src/components/input-otp/index.tsx +277 -0
  105. package/src/components/label/index.tsx +30 -0
  106. package/src/components/language-selector/index.tsx +341 -0
  107. package/src/components/menubar/index.tsx +240 -0
  108. package/src/components/navigation-menu/index.tsx +134 -0
  109. package/src/components/popover/index.tsx +35 -0
  110. package/src/components/progress/index.tsx +32 -0
  111. package/src/components/radio-group/index.tsx +48 -0
  112. package/src/components/scroll-area/index.tsx +52 -0
  113. package/src/components/select/index.tsx +164 -0
  114. package/src/components/separator/index.tsx +35 -0
  115. package/src/components/sheet/index.tsx +147 -0
  116. package/src/components/skeleton/index.tsx +22 -0
  117. package/src/components/slider/index.tsx +32 -0
  118. package/src/components/switch/index.tsx +33 -0
  119. package/src/components/table/index.tsx +117 -0
  120. package/src/components/tabs/index.tsx +59 -0
  121. package/src/components/textarea/index.tsx +30 -0
  122. package/src/components/theme-selector/index.tsx +327 -0
  123. package/src/components/toast/index.tsx +133 -0
  124. package/src/components/toaster/index.tsx +34 -0
  125. package/src/components/toggle/index.tsx +49 -0
  126. package/src/components/tooltip/index.tsx +34 -0
  127. package/src/components/typography/index.tsx +276 -0
  128. package/src/components/waka-3d-pie-chart/index.tsx +486 -0
  129. package/src/components/waka-achievement-unlock/index.tsx +716 -0
  130. package/src/components/waka-activity-feed/index.tsx +686 -0
  131. package/src/components/waka-address-autocomplete/index.tsx +1202 -0
  132. package/src/components/waka-admincrumb/index.tsx +349 -0
  133. package/src/components/waka-alert-stack/index.tsx +827 -0
  134. package/src/components/waka-allocation-matrix/index.tsx +1278 -0
  135. package/src/components/waka-approval-chain/index.tsx +766 -0
  136. package/src/components/waka-audit-log/index.tsx +1475 -0
  137. package/src/components/waka-autocomplete/index.tsx +358 -0
  138. package/src/components/waka-badge-showcase/index.tsx +704 -0
  139. package/src/components/waka-barcode/index.tsx +260 -0
  140. package/src/components/waka-biometric-prompt/index.tsx +765 -0
  141. package/src/components/waka-bottom-sheet/index.tsx +495 -0
  142. package/src/components/waka-breadcrumb/index.tsx +376 -0
  143. package/src/components/waka-breadcrumb-path/index.tsx +513 -0
  144. package/src/components/waka-budget-burn/index.tsx +1234 -0
  145. package/src/components/waka-capacity-planner/index.tsx +1107 -0
  146. package/src/components/waka-carousel/index.tsx +893 -0
  147. package/src/components/waka-cart-summary/index.tsx +1055 -0
  148. package/src/components/waka-challenge-timer/index.tsx +1044 -0
  149. package/src/components/waka-charts/WakaAreaChart.tsx +251 -0
  150. package/src/components/waka-charts/WakaBarChart.tsx +222 -0
  151. package/src/components/waka-charts/WakaChart.tsx +124 -0
  152. package/src/components/waka-charts/WakaLineChart.tsx +219 -0
  153. package/src/components/waka-charts/WakaMiniChart.tsx +133 -0
  154. package/src/components/waka-charts/WakaPieChart.tsx +214 -0
  155. package/src/components/waka-charts/WakaSparkline.tsx +229 -0
  156. package/src/components/waka-charts/dataTableHelpers.ts +109 -0
  157. package/src/components/waka-charts/hooks/useChartTheme.ts +123 -0
  158. package/src/components/waka-charts/hooks/useRechartsLoader.ts +234 -0
  159. package/src/components/waka-charts/index.ts +90 -0
  160. package/src/components/waka-charts/types.ts +330 -0
  161. package/src/components/waka-chat-bubble/index.tsx +1060 -0
  162. package/src/components/waka-checklist/index.tsx +1067 -0
  163. package/src/components/waka-checkout-stepper/index.tsx +976 -0
  164. package/src/components/waka-cohort-table/index.tsx +1011 -0
  165. package/src/components/waka-color-picker/index.tsx +447 -0
  166. package/src/components/waka-combo-counter/index.tsx +864 -0
  167. package/src/components/waka-combobox/index.tsx +497 -0
  168. package/src/components/waka-command-bar/index.tsx +403 -0
  169. package/src/components/waka-compare-period/index.tsx +1230 -0
  170. package/src/components/waka-connection-matrix/index.tsx +1053 -0
  171. package/src/components/waka-contribution-graph/index.tsx +552 -0
  172. package/src/components/waka-cost-breakdown/index.tsx +1065 -0
  173. package/src/components/waka-coupon-input/index.tsx +592 -0
  174. package/src/components/waka-credit-card-input/index.tsx +982 -0
  175. package/src/components/waka-daily-reward/index.tsx +762 -0
  176. package/src/components/waka-date-range-picker/index.tsx +378 -0
  177. package/src/components/waka-datetime-picker/index.tsx +793 -0
  178. package/src/components/waka-datetime-picker.form-integration/index.tsx +402 -0
  179. package/src/components/waka-deployment-lane/index.tsx +673 -0
  180. package/src/components/waka-device-trust/index.tsx +1259 -0
  181. package/src/components/waka-dock/index.tsx +285 -0
  182. package/src/components/waka-drawer/index.tsx +319 -0
  183. package/src/components/waka-empty-state/index.tsx +545 -0
  184. package/src/components/waka-error-shake/index.tsx +398 -0
  185. package/src/components/waka-feature-announcement/index.tsx +991 -0
  186. package/src/components/waka-file-upload/index.tsx +437 -0
  187. package/src/components/waka-floating-nav/index.tsx +413 -0
  188. package/src/components/waka-flow-diagram/index.tsx +508 -0
  189. package/src/components/waka-funnel-chart/index.tsx +823 -0
  190. package/src/components/waka-glow-card/index.tsx +246 -0
  191. package/src/components/waka-goal-progress/index.tsx +1025 -0
  192. package/src/components/waka-haptic-button/index.tsx +388 -0
  193. package/src/components/waka-health-pulse/index.tsx +451 -0
  194. package/src/components/waka-heatmap/index.tsx +1026 -0
  195. package/src/components/waka-hotspot/index.tsx +682 -0
  196. package/src/components/waka-image/index.tsx +373 -0
  197. package/src/components/waka-incident-timeline/index.tsx +686 -0
  198. package/src/components/waka-invoice-preview/index.tsx +829 -0
  199. package/src/components/waka-kanban/index.tsx +646 -0
  200. package/src/components/waka-kpi-dashboard/index.tsx +755 -0
  201. package/src/components/waka-leaderboard/index.tsx +746 -0
  202. package/src/components/waka-level-progress/index.tsx +665 -0
  203. package/src/components/waka-liquid-button/index.tsx +520 -0
  204. package/src/components/waka-loading-orbit/index.tsx +478 -0
  205. package/src/components/waka-loot-box/index.tsx +1091 -0
  206. package/src/components/waka-magic-link/index.tsx +321 -0
  207. package/src/components/waka-magnetic-button/index.tsx +567 -0
  208. package/src/components/waka-mention-input/index.tsx +953 -0
  209. package/src/components/waka-metric-sparkline/index.tsx +627 -0
  210. package/src/components/waka-milestone-road/index.tsx +1064 -0
  211. package/src/components/waka-modal/index.tsx +374 -0
  212. package/src/components/waka-morph-button/index.tsx +495 -0
  213. package/src/components/waka-network-topology/index.tsx +801 -0
  214. package/src/components/waka-notifications/index.tsx +414 -0
  215. package/src/components/waka-number-input/index.tsx +373 -0
  216. package/src/components/waka-orbital-menu/index.tsx +445 -0
  217. package/src/components/waka-order-tracker/index.tsx +1041 -0
  218. package/src/components/waka-pagination/index.tsx +393 -0
  219. package/src/components/waka-password-strength/index.tsx +824 -0
  220. package/src/components/waka-payment-method-picker/index.tsx +715 -0
  221. package/src/components/waka-permission-matrix/index.tsx +1302 -0
  222. package/src/components/waka-phone-input/index.tsx +801 -0
  223. package/src/components/waka-pipeline-view/index.tsx +604 -0
  224. package/src/components/waka-player-card/index.tsx +691 -0
  225. package/src/components/waka-points-popup/index.tsx +366 -0
  226. package/src/components/waka-power-up/index.tsx +1155 -0
  227. package/src/components/waka-presence-indicator/index.tsx +1181 -0
  228. package/src/components/waka-pricing-table/index.tsx +755 -0
  229. package/src/components/waka-product-card/index.tsx +786 -0
  230. package/src/components/waka-progress-onboarding/index.tsx +878 -0
  231. package/src/components/waka-pull-to-refresh/index.tsx +451 -0
  232. package/src/components/waka-qrcode/index.tsx +232 -0
  233. package/src/components/waka-quest-card/index.tsx +1275 -0
  234. package/src/components/waka-quota-bar/index.tsx +693 -0
  235. package/src/components/waka-radar-score/index.tsx +512 -0
  236. package/src/components/waka-rank-badge/index.tsx +813 -0
  237. package/src/components/waka-rating-input/index.tsx +560 -0
  238. package/src/components/waka-reaction-picker/index.tsx +1062 -0
  239. package/src/components/waka-region-map/index.tsx +730 -0
  240. package/src/components/waka-resource-gauge/index.tsx +654 -0
  241. package/src/components/waka-resource-pool/index.tsx +1035 -0
  242. package/src/components/waka-rich-text-editor/index.tsx +594 -0
  243. package/src/components/waka-rollback-slider/index.tsx +891 -0
  244. package/src/components/waka-sankey-diagram/index.tsx +1032 -0
  245. package/src/components/waka-schedule-picker/index.tsx +1060 -0
  246. package/src/components/waka-scratch-card/index.tsx +914 -0
  247. package/src/components/waka-season-pass/index.tsx +886 -0
  248. package/src/components/waka-security-score/index.tsx +1126 -0
  249. package/src/components/waka-segmented-control/index.tsx +238 -0
  250. package/src/components/waka-server-rack/index.tsx +764 -0
  251. package/src/components/waka-session-manager/index.tsx +815 -0
  252. package/src/components/waka-signature-pad/index.tsx +744 -0
  253. package/src/components/waka-skeleton-wave/index.tsx +454 -0
  254. package/src/components/waka-skill-tree/index.tsx +1031 -0
  255. package/src/components/waka-sla-tracker/index.tsx +798 -0
  256. package/src/components/waka-slider-range/index.tsx +765 -0
  257. package/src/components/waka-spin-wheel/index.tsx +671 -0
  258. package/src/components/waka-spinner/index.tsx +284 -0
  259. package/src/components/waka-spotlight/index.tsx +410 -0
  260. package/src/components/waka-stat/index.tsx +428 -0
  261. package/src/components/waka-stats-hexagon/index.tsx +824 -0
  262. package/src/components/waka-status-matrix/index.tsx +565 -0
  263. package/src/components/waka-stepper/index.tsx +489 -0
  264. package/src/components/waka-streak-counter/index.tsx +334 -0
  265. package/src/components/waka-success-explosion/index.tsx +453 -0
  266. package/src/components/waka-swipe-card/index.tsx +574 -0
  267. package/src/components/waka-tabs-morph/index.tsx +509 -0
  268. package/src/components/waka-tag-input/index.tsx +877 -0
  269. package/src/components/waka-team-banner/index.tsx +1183 -0
  270. package/src/components/waka-terminal-output/index.tsx +836 -0
  271. package/src/components/waka-theme-creator/index.tsx +762 -0
  272. package/src/components/waka-theme-manager/index.tsx +654 -0
  273. package/src/components/waka-thread-view/index.tsx +874 -0
  274. package/src/components/waka-tilt-card/index.tsx +250 -0
  275. package/src/components/waka-time-picker/index.tsx +479 -0
  276. package/src/components/waka-timeline/index.tsx +385 -0
  277. package/src/components/waka-tooltip-tour/index.tsx +855 -0
  278. package/src/components/waka-tour-guide/index.tsx +920 -0
  279. package/src/components/waka-tournament-bracket/index.tsx +1276 -0
  280. package/src/components/waka-tree/index.tsx +557 -0
  281. package/src/components/waka-treemap-chart/index.tsx +1031 -0
  282. package/src/components/waka-two-factor-setup/index.tsx +995 -0
  283. package/src/components/waka-typewriter/index.tsx +566 -0
  284. package/src/components/waka-typing-indicator/index.tsx +649 -0
  285. package/src/components/waka-versus-card/index.tsx +1026 -0
  286. package/src/components/waka-video/index.tsx +557 -0
  287. package/src/components/waka-video-call/index.tsx +1087 -0
  288. package/src/components/waka-virtual-list/index.tsx +327 -0
  289. package/src/components/waka-voice-message/index.tsx +1019 -0
  290. package/src/components/waka-welcome-modal/index.tsx +790 -0
  291. package/src/components/waka-xp-bar/index.tsx +799 -0
@@ -0,0 +1,133 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "../../utils"
5
+ import { Button } from "../../components/button"
6
+ import { Separator } from "../../components/separator"
7
+ import { Github, Twitter, Linkedin, Mail } from "lucide-react"
8
+
9
+ export interface FooterLink {
10
+ label: string
11
+ href: string
12
+ }
13
+
14
+ export interface FooterColumn {
15
+ title: string
16
+ links: FooterLink[]
17
+ }
18
+
19
+ export interface SocialLink {
20
+ platform: "github" | "twitter" | "linkedin" | "email"
21
+ url: string
22
+ }
23
+
24
+ export interface FooterProps {
25
+ columns?: FooterColumn[]
26
+ socialLinks?: SocialLink[]
27
+ copyright?: string
28
+ className?: string
29
+ }
30
+
31
+ const socialIcons = {
32
+ github: Github,
33
+ twitter: Twitter,
34
+ linkedin: Linkedin,
35
+ email: Mail,
36
+ }
37
+
38
+ export function Footer({
39
+ columns = [],
40
+ socialLinks = [],
41
+ copyright = "© 2024 Tous droits réservés.",
42
+ className,
43
+ }: FooterProps) {
44
+ return (
45
+ <footer className={cn("bg-muted/40", className)}>
46
+ <div className="container mx-auto px-4 py-12">
47
+ <div className="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-4">
48
+ {/* Colonnes de liens */}
49
+ {columns.map((column, index) => (
50
+ <div key={index} className="space-y-4">
51
+ <h3 className="text-sm font-semibold text-foreground">
52
+ {column.title}
53
+ </h3>
54
+ <ul className="space-y-2">
55
+ {column.links.map((link, linkIndex) => (
56
+ <li key={linkIndex}>
57
+ <a
58
+ href={link.href}
59
+ className="text-sm text-muted-foreground hover:text-foreground transition-colors"
60
+ >
61
+ {link.label}
62
+ </a>
63
+ </li>
64
+ ))}
65
+ </ul>
66
+ </div>
67
+ ))}
68
+
69
+ {/* Liens sociaux */}
70
+ {socialLinks.length > 0 && (
71
+ <div className="space-y-4">
72
+ <h3 className="text-sm font-semibold text-foreground">
73
+ Suivez-nous
74
+ </h3>
75
+ <div className="flex space-x-4">
76
+ {socialLinks.map((social, index) => {
77
+ const Icon = socialIcons[social.platform]
78
+ return (
79
+ <Button
80
+ key={index}
81
+ variant="ghost"
82
+ size="icon"
83
+ asChild
84
+ className="h-8 w-8"
85
+ >
86
+ <a
87
+ href={social.url}
88
+ target="_blank"
89
+ rel="noopener noreferrer"
90
+ aria-label={social.platform}
91
+ >
92
+ <Icon className="h-4 w-4" />
93
+ </a>
94
+ </Button>
95
+ )
96
+ })}
97
+ </div>
98
+ </div>
99
+ )}
100
+ </div>
101
+
102
+ <Separator className="my-8" />
103
+
104
+ <div className="flex flex-col items-center justify-between space-y-4 md:flex-row md:space-y-0">
105
+ <p className="text-sm text-muted-foreground">
106
+ {copyright}
107
+ </p>
108
+ <div className="flex space-x-6">
109
+ <a
110
+ href="/privacy"
111
+ className="text-sm text-muted-foreground hover:text-foreground transition-colors"
112
+ >
113
+ Politique de confidentialité
114
+ </a>
115
+ <a
116
+ href="/terms"
117
+ className="text-sm text-muted-foreground hover:text-foreground transition-colors"
118
+ >
119
+ Conditions d'utilisation
120
+ </a>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ </footer>
125
+ )
126
+ }
127
+
128
+
129
+
130
+
131
+
132
+
133
+
@@ -0,0 +1,357 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Button } from "../../components/button"
5
+ import { Input } from "../../components/input"
6
+ import {
7
+ DropdownMenu,
8
+ DropdownMenuContent,
9
+ DropdownMenuItem,
10
+ DropdownMenuTrigger,
11
+ DropdownMenuSeparator,
12
+ } from "../../components/dropdown-menu"
13
+ import {
14
+ Select,
15
+ SelectContent,
16
+ SelectItem,
17
+ SelectTrigger,
18
+ SelectValue,
19
+ } from "../../components/select"
20
+ import { Avatar, AvatarFallback, AvatarImage } from "../../components/avatar"
21
+ import { Badge } from "../../components/badge"
22
+ import { cn } from "../../utils/cn"
23
+ import { Search, Bell, ChevronDown, Plus, X } from "lucide-react"
24
+
25
+ // Types
26
+ export interface HeaderAction {
27
+ id: string
28
+ label: string
29
+ icon?: React.ReactNode
30
+ onClick?: () => void
31
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link"
32
+ }
33
+
34
+ export interface HeaderFilter {
35
+ id: string
36
+ label: string
37
+ icon?: React.ReactNode
38
+ options: { value: string; label: string }[]
39
+ value?: string
40
+ onChange?: (value: string) => void
41
+ placeholder?: string
42
+ }
43
+
44
+ export interface HeaderNotification {
45
+ id: string
46
+ title: string
47
+ description?: string
48
+ time?: string
49
+ read?: boolean
50
+ onClick?: () => void
51
+ }
52
+
53
+ export interface HeaderUserMenu {
54
+ name: string
55
+ email?: string
56
+ avatar?: string
57
+ initials?: string
58
+ items: {
59
+ label: string
60
+ icon?: React.ReactNode
61
+ onClick?: () => void
62
+ separator?: boolean
63
+ }[]
64
+ }
65
+
66
+ export interface WakaHeaderProps {
67
+ /** Titre principal affiché au centre */
68
+ title?: string
69
+ /** Sous-titre optionnel */
70
+ subtitle?: string
71
+ /** Afficher le champ de recherche */
72
+ showSearch?: boolean
73
+ /** Placeholder du champ de recherche */
74
+ searchPlaceholder?: string
75
+ /** Valeur du champ de recherche */
76
+ searchValue?: string
77
+ /** Callback lors de la recherche */
78
+ onSearchChange?: (value: string) => void
79
+ /** Callback lors de la soumission de recherche */
80
+ onSearchSubmit?: (value: string) => void
81
+ /** Bouton d'action principal (ex: "Création rapide") */
82
+ primaryAction?: HeaderAction
83
+ /** Actions secondaires (boutons) */
84
+ secondaryActions?: HeaderAction[]
85
+ /** Filtres affichés sous le header */
86
+ filters?: HeaderFilter[]
87
+ /** Notifications */
88
+ notifications?: HeaderNotification[]
89
+ /** Nombre de notifications non lues */
90
+ unreadCount?: number
91
+ /** Callback lors du clic sur les notifications */
92
+ onNotificationsClick?: () => void
93
+ /** Menu utilisateur */
94
+ userMenu?: HeaderUserMenu
95
+ /** Éléments personnalisés à gauche */
96
+ leftContent?: React.ReactNode
97
+ /** Éléments personnalisés à droite */
98
+ rightContent?: React.ReactNode
99
+ /** Éléments personnalisés dans la barre de filtres */
100
+ filterContent?: React.ReactNode
101
+ /** Classes CSS additionnelles */
102
+ className?: string
103
+ /** Classes CSS pour la barre principale */
104
+ mainBarClassName?: string
105
+ /** Classes CSS pour la barre de filtres */
106
+ filterBarClassName?: string
107
+ /** Sticky header */
108
+ sticky?: boolean
109
+ }
110
+
111
+ export function WakaHeader({
112
+ title,
113
+ subtitle,
114
+ showSearch = true,
115
+ searchPlaceholder = "Rechercher...",
116
+ searchValue,
117
+ onSearchChange,
118
+ onSearchSubmit,
119
+ primaryAction,
120
+ secondaryActions,
121
+ filters,
122
+ notifications,
123
+ unreadCount = 0,
124
+ onNotificationsClick,
125
+ userMenu,
126
+ leftContent,
127
+ rightContent,
128
+ filterContent,
129
+ className,
130
+ mainBarClassName,
131
+ filterBarClassName,
132
+ sticky = true,
133
+ }: WakaHeaderProps) {
134
+ const [internalSearchValue, setInternalSearchValue] = React.useState(searchValue || "")
135
+
136
+ const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
137
+ const value = e.target.value
138
+ setInternalSearchValue(value)
139
+ onSearchChange?.(value)
140
+ }
141
+
142
+ const handleSearchKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
143
+ if (e.key === "Enter") {
144
+ onSearchSubmit?.(internalSearchValue)
145
+ }
146
+ }
147
+
148
+ const hasFilters = (filters && filters.length > 0) || filterContent
149
+
150
+ return (
151
+ <header
152
+ className={cn(
153
+ "w-full bg-background border-b",
154
+ sticky && "sticky top-0 z-50",
155
+ className
156
+ )}
157
+ >
158
+ {/* Main Bar */}
159
+ <div
160
+ className={cn(
161
+ "flex items-center gap-4 px-4 py-2 min-h-[56px]",
162
+ mainBarClassName
163
+ )}
164
+ >
165
+ {/* Left Section */}
166
+ <div className="flex items-center gap-3 flex-shrink-0">
167
+ {/* Primary Action */}
168
+ {primaryAction && (
169
+ <Button
170
+ variant={primaryAction.variant || "default"}
171
+ size="sm"
172
+ onClick={primaryAction.onClick}
173
+ className="gap-2"
174
+ >
175
+ {primaryAction.icon || <Plus className="h-4 w-4" />}
176
+ {primaryAction.label}
177
+ </Button>
178
+ )}
179
+
180
+ {/* Search */}
181
+ {showSearch && (
182
+ <div className="relative">
183
+ <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
184
+ <Input
185
+ type="search"
186
+ placeholder={searchPlaceholder}
187
+ value={internalSearchValue}
188
+ onChange={handleSearchChange}
189
+ onKeyDown={handleSearchKeyDown}
190
+ className="pl-9 w-[200px] h-9 bg-muted/50"
191
+ />
192
+ </div>
193
+ )}
194
+
195
+ {/* Custom Left Content */}
196
+ {leftContent}
197
+ </div>
198
+
199
+ {/* Center Section - Title */}
200
+ {(title || subtitle) && (
201
+ <div className="flex-1 text-center">
202
+ {title && (
203
+ <h1 className="text-lg font-semibold leading-none">{title}</h1>
204
+ )}
205
+ {subtitle && (
206
+ <p className="text-sm text-muted-foreground mt-0.5">{subtitle}</p>
207
+ )}
208
+ </div>
209
+ )}
210
+
211
+ {/* Right Section */}
212
+ <div className="flex items-center gap-2 flex-shrink-0 ml-auto">
213
+ {/* Secondary Actions */}
214
+ {secondaryActions?.map((action) => (
215
+ <Button
216
+ key={action.id}
217
+ variant={action.variant || "ghost"}
218
+ size="sm"
219
+ onClick={action.onClick}
220
+ className="gap-2"
221
+ >
222
+ {action.icon}
223
+ {action.label}
224
+ </Button>
225
+ ))}
226
+
227
+ {/* Custom Right Content */}
228
+ {rightContent}
229
+
230
+ {/* Notifications */}
231
+ {(notifications || onNotificationsClick) && (
232
+ <DropdownMenu>
233
+ <DropdownMenuTrigger asChild>
234
+ <Button
235
+ variant="ghost"
236
+ size="icon"
237
+ className="relative"
238
+ onClick={notifications ? undefined : onNotificationsClick}
239
+ >
240
+ <Bell className="h-5 w-5" />
241
+ {unreadCount > 0 && (
242
+ <Badge
243
+ variant="destructive"
244
+ className="absolute -top-1 -right-1 h-5 w-5 p-0 flex items-center justify-center text-xs"
245
+ >
246
+ {unreadCount > 9 ? "9+" : unreadCount}
247
+ </Badge>
248
+ )}
249
+ </Button>
250
+ </DropdownMenuTrigger>
251
+ {notifications && notifications.length > 0 && (
252
+ <DropdownMenuContent align="end" className="w-80">
253
+ <div className="p-2 font-semibold border-b">Notifications</div>
254
+ {notifications.slice(0, 5).map((notification) => (
255
+ <DropdownMenuItem
256
+ key={notification.id}
257
+ onClick={notification.onClick}
258
+ className={cn(
259
+ "flex flex-col items-start gap-1 p-3",
260
+ !notification.read && "bg-muted/50"
261
+ )}
262
+ >
263
+ <div className="font-medium">{notification.title}</div>
264
+ {notification.description && (
265
+ <div className="text-sm text-muted-foreground">
266
+ {notification.description}
267
+ </div>
268
+ )}
269
+ {notification.time && (
270
+ <div className="text-xs text-muted-foreground">
271
+ {notification.time}
272
+ </div>
273
+ )}
274
+ </DropdownMenuItem>
275
+ ))}
276
+ </DropdownMenuContent>
277
+ )}
278
+ </DropdownMenu>
279
+ )}
280
+
281
+ {/* User Menu */}
282
+ {userMenu && (
283
+ <DropdownMenu>
284
+ <DropdownMenuTrigger asChild>
285
+ <Button variant="ghost" size="sm" className="gap-2">
286
+ <Avatar className="h-7 w-7">
287
+ {userMenu.avatar && (
288
+ <AvatarImage src={userMenu.avatar} alt={userMenu.name} />
289
+ )}
290
+ <AvatarFallback className="text-xs">
291
+ {userMenu.initials || userMenu.name.slice(0, 2).toUpperCase()}
292
+ </AvatarFallback>
293
+ </Avatar>
294
+ <ChevronDown className="h-4 w-4" />
295
+ </Button>
296
+ </DropdownMenuTrigger>
297
+ <DropdownMenuContent align="end" className="w-56">
298
+ <div className="p-2">
299
+ <p className="font-medium">{userMenu.name}</p>
300
+ {userMenu.email && (
301
+ <p className="text-sm text-muted-foreground">{userMenu.email}</p>
302
+ )}
303
+ </div>
304
+ <DropdownMenuSeparator />
305
+ {userMenu.items.map((item, index) =>
306
+ item.separator ? (
307
+ <DropdownMenuSeparator key={index} />
308
+ ) : (
309
+ <DropdownMenuItem key={index} onClick={item.onClick}>
310
+ {item.icon && <span className="mr-2">{item.icon}</span>}
311
+ {item.label}
312
+ </DropdownMenuItem>
313
+ )
314
+ )}
315
+ </DropdownMenuContent>
316
+ </DropdownMenu>
317
+ )}
318
+ </div>
319
+ </div>
320
+
321
+ {/* Filter Bar */}
322
+ {hasFilters && (
323
+ <div
324
+ className={cn(
325
+ "flex items-center gap-2 px-4 py-2 border-t bg-muted/30",
326
+ filterBarClassName
327
+ )}
328
+ >
329
+ {filters?.map((filter) => (
330
+ <Select
331
+ key={filter.id}
332
+ value={filter.value}
333
+ onValueChange={filter.onChange}
334
+ >
335
+ <SelectTrigger className="w-auto h-8 gap-2 bg-muted/50 border-0">
336
+ {filter.icon}
337
+ <SelectValue placeholder={filter.placeholder || filter.label} />
338
+ </SelectTrigger>
339
+ <SelectContent>
340
+ {filter.options.map((option) => (
341
+ <SelectItem key={option.value} value={option.value}>
342
+ {option.label}
343
+ </SelectItem>
344
+ ))}
345
+ </SelectContent>
346
+ </Select>
347
+ ))}
348
+
349
+ {/* Custom Filter Content */}
350
+ {filterContent}
351
+ </div>
352
+ )}
353
+ </header>
354
+ )
355
+ }
356
+
357
+ export default WakaHeader
@@ -0,0 +1,139 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "../../utils"
5
+ import { Button } from "../../components/button"
6
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../components/tabs"
7
+
8
+ export interface HeadtabItem {
9
+ id: string
10
+ label: string
11
+ href?: string
12
+ content?: React.ReactNode
13
+ disabled?: boolean
14
+ }
15
+
16
+ export interface HeadtabProps {
17
+ items: HeadtabItem[]
18
+ defaultActiveId?: string
19
+ variant?: "default" | "pills" | "underline"
20
+ size?: "sm" | "md" | "lg"
21
+ className?: string
22
+ onTabChange?: (activeId: string) => void
23
+ }
24
+
25
+ export function Headtab({
26
+ items,
27
+ defaultActiveId,
28
+ variant = "default",
29
+ size = "md",
30
+ className,
31
+ onTabChange,
32
+ }: HeadtabProps) {
33
+ const [activeId, setActiveId] = React.useState(
34
+ defaultActiveId || items[0]?.id || ""
35
+ )
36
+
37
+ const handleTabChange = (newActiveId: string) => {
38
+ setActiveId(newActiveId)
39
+ onTabChange?.(newActiveId)
40
+ }
41
+
42
+ const sizeClasses = {
43
+ sm: "h-8 px-3 text-sm",
44
+ md: "h-10 px-4 text-sm",
45
+ lg: "h-12 px-6 text-base",
46
+ }
47
+
48
+ const variantClasses = {
49
+ default: "bg-background",
50
+ pills: "bg-muted rounded-full",
51
+ underline: "bg-transparent border-b-2 border-transparent data-[state=active]:border-primary",
52
+ }
53
+
54
+ return (
55
+ <div className={cn("w-full", className)}>
56
+ <Tabs value={activeId} onValueChange={handleTabChange}>
57
+ <TabsList
58
+ className={cn(
59
+ "grid w-full",
60
+ variant === "pills" && "grid-cols-auto",
61
+ variant !== "pills" && `grid-cols-${items.length}`,
62
+ variantClasses[variant]
63
+ )}
64
+ >
65
+ {items.map((item) => (
66
+ <TabsTrigger
67
+ key={item.id}
68
+ value={item.id}
69
+ disabled={item.disabled}
70
+ className={cn(
71
+ sizeClasses[size],
72
+ variant === "underline" && "rounded-none border-b-2 border-transparent data-[state=active]:border-primary",
73
+ variant === "pills" && "rounded-full"
74
+ )}
75
+ >
76
+ {item.label}
77
+ </TabsTrigger>
78
+ ))}
79
+ </TabsList>
80
+
81
+ {items.map((item) => (
82
+ <TabsContent key={item.id} value={item.id} className="mt-6">
83
+ {item.content}
84
+ </TabsContent>
85
+ ))}
86
+ </Tabs>
87
+ </div>
88
+ )
89
+ }
90
+
91
+ export interface BreadcrumbItem {
92
+ label: string
93
+ href?: string
94
+ }
95
+
96
+ export interface BreadcrumbProps {
97
+ items: BreadcrumbItem[]
98
+ separator?: React.ReactNode
99
+ className?: string
100
+ }
101
+
102
+ export function Breadcrumb({
103
+ items,
104
+ separator = "/",
105
+ className,
106
+ }: BreadcrumbProps) {
107
+ return (
108
+ <nav className={cn("flex items-center space-x-1 text-sm text-muted-foreground", className)}>
109
+ {items.map((item, index) => (
110
+ <React.Fragment key={index}>
111
+ {index > 0 && (
112
+ <span className="mx-2 text-muted-foreground">
113
+ {separator}
114
+ </span>
115
+ )}
116
+ {item.href ? (
117
+ <a
118
+ href={item.href}
119
+ className="hover:text-foreground transition-colors"
120
+ >
121
+ {item.label}
122
+ </a>
123
+ ) : (
124
+ <span className="text-foreground font-medium">
125
+ {item.label}
126
+ </span>
127
+ )}
128
+ </React.Fragment>
129
+ ))}
130
+ </nav>
131
+ )
132
+ }
133
+
134
+
135
+
136
+
137
+
138
+
139
+