@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
@@ -1,9 +0,0 @@
1
- "use strict";var j=Object.create;var C=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var K=Object.getPrototypeOf,F=Object.prototype.hasOwnProperty;var O=(f,n,w,l)=>{if(n&&typeof n=="object"||typeof n=="function")for(let h of X(n))!F.call(f,h)&&h!==w&&C(f,h,{get:()=>n[h],enumerable:!(l=D(n,h))||l.enumerable});return f};var g=(f,n,w)=>(w=f!=null?j(K(f)):{},O(n||!f||!f.__esModule?C(w,"default",{value:f,enumerable:!0}):w,f));const d=require("react");function R({data:f,columns:n,exportConfig:w}){const l=d.useMemo(()=>({formats:["csv","xlsx","json"],filename:"export",includeHeaders:!0,...w}),[w]),h=d.useCallback((e,s)=>{if(!e.length)return;const r=n.filter(a=>a.accessorKey||a.id).map(a=>a.header||a.accessorKey||a.id).join(","),c=e.map(a=>n.filter(o=>o.accessorKey||o.id).map(o=>{const m=o.accessorKey?a[o.accessorKey]:a[o.id],E=o.formatter?o.formatter(m):m,L=String(E||"");return L.includes(",")||L.includes('"')||L.includes(`
2
- `)?`"${L.replace(/"/g,'""')}"`:L}).join(",")),t=[r,...c].join(`
3
- `),u=new Blob([t],{type:"text/csv;charset=utf-8;"}),p=document.createElement("a");p.href=URL.createObjectURL(u),p.download=`${s||l.filename}.csv`,p.click(),URL.revokeObjectURL(p.href)},[n,l.filename]),x=d.useCallback((e,s)=>{const r=JSON.stringify(e,null,2),c=new Blob([r],{type:"application/json"}),t=document.createElement("a");t.href=URL.createObjectURL(c),t.download=`${s||l.filename}.json`,t.click(),URL.revokeObjectURL(t.href)},[l.filename]),k=d.useCallback(async(e,s)=>{try{if(typeof window>"u")throw new Error("XLSX export not available in server environment");const r=await import("xlsx"),t=[n.filter(a=>a.accessorKey||a.id).map(a=>a.header||a.accessorKey||a.id),...e.map(a=>n.filter(o=>o.accessorKey||o.id).map(o=>{const m=o.accessorKey?a[o.accessorKey]:a[o.id];return o.formatter?o.formatter(m):m}))],u=r.utils.aoa_to_sheet(t),p=r.utils.book_new();r.utils.book_append_sheet(p,u,"Sheet1"),r.writeFile(p,`${s||l.filename}.xlsx`)}catch(r){throw console.error("Erreur lors de l'export XLSX:",r),new Error("La librairie xlsx n'est pas disponible")}},[n,l.filename]),v=d.useCallback(async(e,s)=>{try{if(typeof window>"u")throw new Error("PDF export not available in server environment");const r=await import("jspdf"),c=await import("jspdf-autotable"),t=new r.default,u=n.filter(a=>a.accessorKey||a.id).map(a=>a.header||a.accessorKey||a.id),p=e.map(a=>n.filter(o=>o.accessorKey||o.id).map(o=>{const m=o.accessorKey?a[o.accessorKey]:a[o.id];return o.formatter?o.formatter(m):m}));t.autoTable({head:[u],body:p,startY:20,styles:{fontSize:8},headStyles:{fillColor:[66,139,202]}}),t.save(`${s||l.filename}.pdf`)}catch(r){throw console.error("Erreur lors de l'export PDF:",r),new Error("Les librairies jsPDF et jspdf-autotable ne sont pas disponibles")}},[n,l.filename]),y=d.useCallback((e,s)=>{const r=n.filter(p=>p.accessorKey||p.id).map(p=>p.accessorKey||p.id);let c=`<?xml version="1.0" encoding="UTF-8"?>
4
- <data>
5
- `;e.forEach((p,a)=>{c+=` <row id="${a}">
6
- `,r.forEach(o=>{const m=p[o],E=String(m||"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");c+=` <${o}>${E}</${o}>
7
- `}),c+=` </row>
8
- `}),c+="</data>";const t=new Blob([c],{type:"application/xml"}),u=document.createElement("a");u.href=URL.createObjectURL(t),u.download=`${s||l.filename}.xml`,u.click(),URL.revokeObjectURL(u.href)},[n,l.filename]),b=d.useCallback(async(e,s,r)=>{const c=s||f,t=r||l.filename;if(l.onExport){l.onExport(c,e);return}switch(e.toLowerCase()){case"csv":h(c,t);break;case"json":x(c,t);break;case"xlsx":await k(c,t);break;case"pdf":await v(c,t);break;case"xml":y(c,t);break;default:throw new Error(`Format d'export non supporté: ${e}`)}},[f,l,h,x,k,v,y]),S=d.useCallback(async e=>b(e),[b]),i=d.useCallback(async(e,s)=>b(e,s),[b]);return{exportData:b,exportAll:S,exportSelected:i,supportedFormats:l.formats,isExportSupported:e=>l.formats.includes(e)}}function U({importConfig:f}){const n=d.useMemo(()=>({accept:".csv,.xlsx,.json,.xml",...f}),[f]),w=d.useCallback((i,e=",")=>{const s=i.split(`
9
- `).filter(t=>t.trim());if(s.length===0)return[];const r=s[0].split(e).map(t=>t.trim().replace(/"/g,""));return s.slice(1).map(t=>{const u=t.split(e).map(a=>a.trim().replace(/"/g,"")),p={};return r.forEach((a,o)=>{p[a]=u[o]||""}),p})},[]),l=d.useCallback(i=>{try{const e=JSON.parse(i);return Array.isArray(e)?e:[e]}catch{throw new Error("Format JSON invalide")}},[]),h=d.useCallback(i=>{try{const r=new DOMParser().parseFromString(i,"text/xml").querySelectorAll("row");return Array.from(r).map(c=>{const t={};return Array.from(c.children).forEach(u=>{t[u.tagName]=u.textContent||""}),t})}catch{throw new Error("Format XML invalide")}},[]),x=d.useCallback(async i=>{try{if(typeof window>"u")throw new Error("XLSX parsing not available in server environment");const e=await import("xlsx"),s=await i.arrayBuffer(),r=e.read(s,{type:"array"}),c=r.SheetNames[0],t=r.Sheets[c],u=e.utils.sheet_to_json(t,{header:1});if(u.length===0)return[];const p=u[0];return u.slice(1).map(a=>{const o={};return p.forEach((m,E)=>{o[m]=a[E]||""}),o})}catch{throw new Error("Erreur lors du parsing du fichier XLSX")}},[]),k=d.useCallback(i=>n.validate?n.validate(i):Array.isArray(i)?i.length===0?{valid:!1,errors:["Aucune donnée trouvée"]}:{valid:!0,errors:[]}:{valid:!1,errors:["Les données doivent être un tableau"]},[n.validate]),v=d.useCallback(i=>n.columnMapping?i.map(e=>{const s={};return Object.entries(n.columnMapping).forEach(([r,c])=>{e[r]!==void 0&&(s[c]=e[r])}),s}):i,[n.columnMapping]),y=d.useCallback(async i=>{const e=i.name.split(".").pop()?.toLowerCase();let s=[];try{const r=await i.text();switch(e){case"csv":s=w(r,n.parseOptions?.csv?.delimiter);break;case"json":s=l(r);break;case"xml":s=h(r);break;case"xlsx":s=await x(i);break;default:throw new Error(`Format de fichier non supporté: ${e}`)}const c=k(s);if(!c.valid)throw new Error(`Données invalides: ${c.errors.join(", ")}`);const t=v(s);return n.onImport&&n.onImport(t),t}catch(r){throw new Error(`Erreur lors de l'import: ${r instanceof Error?r.message:"Erreur inconnue"}`)}},[n,w,l,h,x,k,v]),b=d.useCallback(()=>{const i=document.createElement("input");return i.type="file",i.accept=n.accept,i.multiple=!1,i},[n.accept]),S=d.useCallback(()=>new Promise((i,e)=>{const s=b();s.onchange=async r=>{const c=r.target.files?.[0];if(!c){e(new Error("Aucun fichier sélectionné"));return}try{const t=await y(c);i(t)}catch(t){e(t)}},s.click()}),[b,y]);return{importData:y,importWithUI:S,supportedFormats:n.accept?.split(",")||[],isFormatSupported:i=>{const e=i.split(".").pop()?.toLowerCase();return n.accept?.includes(e||"")||!1}}}exports.useDataTableExport=R;exports.useDataTableImport=U;
@@ -1,446 +0,0 @@
1
- # 📊 DataTable
2
-
3
- Composant de table de données ultra-complet basé sur **TanStack Table v8**, totalement configurable et typé.
4
-
5
- ## ✨ Fonctionnalités
6
-
7
- - ✅ **Tri multi-colonnes** (client & serveur)
8
- - ✅ **Filtrage global et par colonne**
9
- - ✅ **Pagination** (client & serveur)
10
- - ✅ **Sélection multiple** avec checkbox
11
- - ✅ **Export** (CSV, JSON)
12
- - ✅ **Import** (CSV)
13
- - ✅ **Layouts multiples** (standard, card, compact, split, infinite)
14
- - ✅ **Variants visuels** (bordered, minimal, striped, glass)
15
- - ✅ **Densité ajustable** (comfortable, compact)
16
- - ✅ **Toolbar personnalisable** avec actions
17
- - ✅ **Virtualisation** pour grandes données
18
- - ✅ **Thème clair/sombre** via TweakCN
19
- - ✅ **i18n** complet
20
- - ✅ **Responsive** (mobile-first)
21
- - ✅ **Accessibilité** (a11y)
22
- - ✅ **TypeScript** 100%
23
-
24
- ## 📦 Installation
25
-
26
- ```bash
27
- pnpm add @wakastart/ui @tanstack/react-table
28
- ```
29
-
30
- ## 🚀 Utilisation de base
31
-
32
- ```tsx
33
- import { DataTable } from "@wakastart/ui"
34
- import { ColumnDef } from "@tanstack/react-table"
35
-
36
- interface User {
37
- id: string
38
- name: string
39
- email: string
40
- }
41
-
42
- const columns: ColumnDef<User>[] = [
43
- {
44
- accessorKey: "name",
45
- header: "Name",
46
- },
47
- {
48
- accessorKey: "email",
49
- header: "Email",
50
- },
51
- ]
52
-
53
- const data: User[] = [
54
- { id: "1", name: "John", email: "john@example.com" },
55
- { id: "2", name: "Jane", email: "jane@example.com" },
56
- ]
57
-
58
- function MyTable() {
59
- return <DataTable data={data} columns={columns} />
60
- }
61
- ```
62
-
63
- ## 🎨 Exemples avancés
64
-
65
- ### Table avec sélection et actions
66
-
67
- ```tsx
68
- <DataTable
69
- data={users}
70
- columns={columns}
71
- selection
72
- toolbar={{
73
- showSearch: true,
74
- actions: [
75
- {
76
- id: "delete",
77
- label: "Delete",
78
- icon: <Trash />,
79
- onClick: (selectedRows) => console.log(selectedRows),
80
- requiresSelection: true,
81
- variant: "destructive",
82
- },
83
- ],
84
- }}
85
- onSelectionChange={(selectedRows) => console.log(selectedRows)}
86
- />
87
- ```
88
-
89
- ### Pagination serveur
90
-
91
- ```tsx
92
- <DataTable
93
- data={users}
94
- columns={columns}
95
- pagination={{
96
- mode: "server",
97
- currentPage: 0,
98
- totalItems: 1000,
99
- pageSize: 10,
100
- onPageChange: (page) => fetchPage(page),
101
- onPageSizeChange: (size) => setPageSize(size),
102
- }}
103
- />
104
- ```
105
-
106
- ### Export et Import
107
-
108
- ```tsx
109
- <DataTable
110
- data={users}
111
- columns={columns}
112
- enableExport
113
- enableImport
114
- />
115
- ```
116
-
117
- ### Layouts alternatifs
118
-
119
- ```tsx
120
- <DataTable
121
- data={users}
122
- columns={columns}
123
- layout="card" // ou "compact", "split", "infinite"
124
- variant="glass" // ou "bordered", "minimal", "striped"
125
- density="compact" // ou "comfortable"
126
- />
127
- ```
128
-
129
- ### Header sticky
130
-
131
- ```tsx
132
- <DataTable
133
- data={users}
134
- columns={columns}
135
- headerSticky
136
- virtualizationHeight={600}
137
- />
138
- ```
139
-
140
- ### Filtres avancés avec autocomplete
141
-
142
- ```tsx
143
- <DataTable
144
- data={users}
145
- columns={columns}
146
- filterPosition="right" // ou "left", "top", "bottom", "modal"
147
- filters={[
148
- {
149
- id: "name-filter",
150
- label: "Nom",
151
- type: "text",
152
- column: "name",
153
- placeholder: "Rechercher par nom...",
154
- },
155
- {
156
- id: "role-filter",
157
- label: "Rôle",
158
- type: "multiselect",
159
- column: "role",
160
- placeholder: "Sélectionner des rôles...",
161
- },
162
- {
163
- id: "status-filter",
164
- label: "Statut",
165
- type: "select",
166
- column: "status",
167
- options: [
168
- { label: "Actif", value: "active" },
169
- { label: "Inactif", value: "inactive" },
170
- ],
171
- },
172
- {
173
- id: "date-filter",
174
- label: "Date de création",
175
- type: "date",
176
- column: "createdAt",
177
- },
178
- {
179
- id: "age-filter",
180
- label: "Âge",
181
- type: "range",
182
- column: "age",
183
- },
184
- ]}
185
- onFiltersChange={(activeFilters) => console.log(activeFilters)}
186
- />
187
- ```
188
-
189
- **Caractéristiques des filtres** :
190
- - 🎯 **Bouton compact** : S'ouvre dans un panneau au clic (ne prend pas de place)
191
- - 🔍 **Autocomplete intelligent** : Suggestions automatiques basées sur les données de la colonne
192
- - 📝 **Types multiples** : text, select, multiselect, date, range
193
- - 📍 **Positions flexibles** :
194
- - `top`/`bottom` : Popover compact (400px)
195
- - `left`/`right` : Sheet latéral (400-540px)
196
- - `modal` : Popover modal
197
- - ✅ **Gestion des filtres actifs** : Affichage et suppression facile des filtres appliqués
198
- - 🔧 **Opérateurs multiples** : contains, equals, startsWith, endsWith, in, notIn, between, etc.
199
-
200
- ## 📚 Props
201
-
202
- ### DataTableProps<TData>
203
-
204
- | Prop | Type | Default | Description |
205
- |------|------|---------|-------------|
206
- | `data` | `TData[]` | **required** | Données à afficher |
207
- | `columns` | `ColumnDef<TData>[]` | **required** | Définition des colonnes |
208
- | `layout` | `DataTableLayout` | `"standard"` | Layout d'affichage |
209
- | `variant` | `DataTableVariant` | `"bordered"` | Variant visuel |
210
- | `density` | `DataTableDensity` | `"comfortable"` | Densité d'affichage |
211
- | `selection` | `boolean` | `false` | Activer la sélection |
212
- | `pagination` | `PaginationConfig` | `undefined` | Configuration pagination |
213
- | `toolbar` | `ToolbarConfig` | `undefined` | Configuration toolbar |
214
- | `filters` | `FilterConfig[]` | `undefined` | Configuration filtres |
215
- | `filterPosition` | `FilterPosition` | `"top"` | Position des filtres |
216
- | `loading` | `boolean` | `false` | État de chargement |
217
- | `error` | `string \| null` | `null` | Message d'erreur |
218
- | `emptyState` | `ReactNode` | `undefined` | État vide personnalisé |
219
- | `headerSticky` | `boolean` | `false` | Header fixe |
220
- | `enableExport` | `boolean \| ExportConfig` | `false` | Activer l'export |
221
- | `enableImport` | `boolean \| ImportConfig` | `false` | Activer l'import |
222
- | `enableVirtualization` | `boolean` | `false` | Activer virtualisation |
223
- | `onRowClick` | `(row: TData) => void` | `undefined` | Callback clic ligne |
224
- | `onSelectionChange` | `(rows: TData[]) => void` | `undefined` | Callback sélection |
225
- | `className` | `string` | `undefined` | Classe CSS |
226
- | `tableId` | `string` | `undefined` | ID pour persistance |
227
-
228
- ### PaginationConfig
229
-
230
- ```ts
231
- interface PaginationConfig {
232
- mode?: "client" | "server"
233
- pageSize?: number
234
- pageSizeOptions?: number[]
235
- currentPage?: number
236
- totalItems?: number
237
- onPageChange?: (page: number) => void
238
- onPageSizeChange?: (size: number) => void
239
- }
240
- ```
241
-
242
- ### ToolbarConfig
243
-
244
- ```ts
245
- interface ToolbarConfig {
246
- actions?: TableAction[]
247
- showSearch?: boolean
248
- showColumnToggle?: boolean
249
- showDensity?: boolean
250
- showRefresh?: boolean
251
- onRefresh?: () => void
252
- }
253
- ```
254
-
255
- ### TableAction
256
-
257
- ```ts
258
- interface TableAction {
259
- id: string
260
- label: string
261
- icon?: ReactNode
262
- onClick: (selectedRows: TData[]) => void
263
- requiresSelection?: boolean
264
- variant?: "default" | "destructive" | "outline" | "ghost"
265
- disabled?: boolean
266
- }
267
- ```
268
-
269
- ### FilterConfig
270
-
271
- ```ts
272
- interface FilterConfig {
273
- id: string
274
- label: string
275
- type: "text" | "select" | "multiselect" | "date" | "range"
276
- column?: string
277
- placeholder?: string
278
- defaultValue?: any
279
- options?: Array<{ label: string; value: string | number }>
280
- }
281
- ```
282
-
283
- **Types de filtres** :
284
- - `text` : Champ texte avec autocomplete basé sur les valeurs de la colonne
285
- - `select` : Liste déroulante simple
286
- - `multiselect` : Sélection multiple avec checkboxes
287
- - `date` : Sélecteur de date
288
- - `range` : Plage numérique (min/max)
289
-
290
- ## 🎛️ Hooks
291
-
292
- ### useDataTable
293
-
294
- Hook principal pour gérer la logique du DataTable.
295
-
296
- ```tsx
297
- const {
298
- table,
299
- sorting,
300
- setSorting,
301
- columnFilters,
302
- setColumnFilters,
303
- globalFilter,
304
- setGlobalFilter,
305
- selectedRows,
306
- resetFilters,
307
- exportData,
308
- } = useDataTable({
309
- data,
310
- columns,
311
- pagination,
312
- tableId,
313
- })
314
- ```
315
-
316
- ### useTableLayout
317
-
318
- Hook pour gérer le layout et la densité.
319
-
320
- ```tsx
321
- const {
322
- layout,
323
- setLayout,
324
- density,
325
- setDensity,
326
- toggleLayout,
327
- toggleDensity,
328
- isMobile,
329
- densityClasses,
330
- } = useTableLayout("standard", "comfortable")
331
- ```
332
-
333
- ## 🌍 Internationalisation
334
-
335
- Le composant supporte l'i18n via `react-i18next`. Toutes les clés sont sous le namespace `datatable` :
336
-
337
- ```json
338
- {
339
- "datatable": {
340
- "loading": "Chargement...",
341
- "noData": "Aucune donnée",
342
- "selectAll": "Tout sélectionner",
343
- "pagination": {
344
- "showing": "Affichage",
345
- "to": "à",
346
- "of": "sur",
347
- "results": "résultats",
348
- "rowsPerPage": "Lignes par page"
349
- },
350
- "toolbar": {
351
- "search": "Rechercher...",
352
- "selected": "sélectionnés",
353
- "clear": "Effacer",
354
- "export": "Exporter",
355
- "columns": "Colonnes"
356
- }
357
- }
358
- }
359
- ```
360
-
361
- ## 🎨 Personnalisation
362
-
363
- ### Styles personnalisés
364
-
365
- ```tsx
366
- <DataTable
367
- data={data}
368
- columns={columns}
369
- className="custom-table"
370
- />
371
- ```
372
-
373
- ### Variant personnalisé
374
-
375
- Le composant utilise Tailwind CSS. Vous pouvez personnaliser via les variants :
376
-
377
- - `bordered` : bordures et coins arrondis
378
- - `minimal` : sans bordures
379
- - `striped` : lignes alternées
380
- - `glass` : effet glassmorphism
381
-
382
- ## 🔧 Utilitaires
383
-
384
- ### Export
385
-
386
- ```ts
387
- import { exportToCSV, exportToJSON } from "@wakastart/ui"
388
-
389
- exportToCSV(data, "users.csv")
390
- exportToJSON(data, "users.json")
391
- ```
392
-
393
- ### Import
394
-
395
- ```ts
396
- import { parseCSV } from "@wakastart/ui"
397
-
398
- const data = await parseCSV(file)
399
- ```
400
-
401
- ### Persistance
402
-
403
- ```ts
404
- import { saveTableState, loadTableState } from "@wakastart/ui"
405
-
406
- saveTableState("my-table", state)
407
- const state = loadTableState("my-table")
408
- ```
409
-
410
- ## 🧪 Tests
411
-
412
- ```tsx
413
- import { render, screen } from "@testing-library/react"
414
- import { DataTable } from "@wakastart/ui"
415
-
416
- test("renders table with data", () => {
417
- render(<DataTable data={testData} columns={testColumns} />)
418
- expect(screen.getByText("John")).toBeInTheDocument()
419
- })
420
- ```
421
-
422
- ## 📖 Documentation complète
423
-
424
- - [TanStack Table](https://tanstack.com/table/v8)
425
- - [WakaStart UI](https://ui.wakastart.com)
426
- - [Exemples de démo](/demo/app/datatable)
427
-
428
- ## 📝 Changelog
429
-
430
- ### v1.0.0 (2024-10-15)
431
-
432
- - 🎉 Initial release
433
- - ✨ Support complet de TanStack Table v8
434
- - 🎨 Layouts multiples
435
- - 🌍 i18n complet
436
- - 📊 Export/Import
437
- - 🎯 TypeScript strict
438
-
439
- ## 🤝 Contribution
440
-
441
- Contributions bienvenues ! Voir [CONTRIBUTING.md](../../../CONTRIBUTING.md)
442
-
443
- ## 📄 License
444
-
445
- MIT © WakaStart
446
-