@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.
- package/README.md +71 -8
- package/dist/cli/commands/add.d.ts +7 -0
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/list.d.ts +5 -0
- package/dist/cli/commands/search.d.ts +1 -0
- package/dist/cli/index.cjs +6014 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/utils/config.d.ts +29 -0
- package/dist/cli/utils/logger.d.ts +20 -0
- package/dist/cli/utils/registry.d.ts +23 -0
- package/package.json +14 -3
- package/src/blocks/activity-timeline/index.tsx +586 -0
- package/src/blocks/calendar-view/index.tsx +756 -0
- package/src/blocks/chat/index.tsx +1018 -0
- package/src/blocks/chat/widget.tsx +504 -0
- package/src/blocks/dashboard/index.tsx +522 -0
- package/src/blocks/empty-states/index.tsx +452 -0
- package/src/blocks/error-pages/index.tsx +426 -0
- package/src/blocks/faq/index.tsx +479 -0
- package/src/blocks/file-manager/index.tsx +890 -0
- package/src/blocks/footer/index.tsx +133 -0
- package/src/blocks/header/index.tsx +357 -0
- package/src/blocks/headtab/index.tsx +139 -0
- package/src/blocks/i18n-editor/index.tsx +1016 -0
- package/src/blocks/index.ts +80 -0
- package/src/blocks/kanban-board/index.tsx +779 -0
- package/src/blocks/landing/index.tsx +677 -0
- package/src/blocks/language-selector/index.tsx +88 -0
- package/src/blocks/layout/index.tsx +159 -0
- package/src/blocks/login/index.tsx +339 -0
- package/src/blocks/login/types.ts +131 -0
- package/src/blocks/pricing/index.tsx +564 -0
- package/src/blocks/profile/index.tsx +746 -0
- package/src/blocks/settings/index.tsx +558 -0
- package/src/blocks/sidebar/index.tsx +713 -0
- package/src/blocks/theme-creator-block/index.tsx +835 -0
- package/src/blocks/user-management/index.tsx +1037 -0
- package/src/blocks/wizard/index.tsx +719 -0
- package/src/components/DataTable/DataTable.tsx +406 -0
- package/src/components/DataTable/DataTableAdvanced.tsx +720 -0
- package/src/components/DataTable/DataTableBody.tsx +216 -0
- package/src/components/DataTable/DataTableCell.tsx +172 -0
- package/src/components/DataTable/DataTableColumnResizer.tsx +62 -0
- package/src/components/DataTable/DataTableConflictResolver.tsx +478 -0
- package/src/components/DataTable/DataTableContextMenu.tsx +219 -0
- package/src/components/DataTable/DataTableEditCell.tsx +279 -0
- package/src/components/DataTable/DataTableFilterBuilder.tsx +519 -0
- package/src/components/DataTable/DataTableFilters.tsx +535 -0
- package/src/components/DataTable/DataTableGrouping.tsx +147 -0
- package/src/components/DataTable/DataTableHeader.tsx +172 -0
- package/src/components/DataTable/DataTablePagination.tsx +125 -0
- package/src/components/DataTable/DataTableSelection.tsx +269 -0
- package/src/components/DataTable/DataTableSyncStatus.tsx +281 -0
- package/src/components/DataTable/DataTableToolbar.tsx +262 -0
- package/src/components/DataTable/README.md +446 -0
- package/src/components/DataTable/__tests__/DataTableAdvanced.test.tsx +426 -0
- package/src/components/DataTable/__tests__/DataTableEdit.test.tsx +329 -0
- package/src/components/DataTable/__tests__/useDataTableAdvanced.test.ts +455 -0
- package/src/components/DataTable/examples/EditExample.tsx +166 -0
- package/src/components/DataTable/formatters/index.ts +335 -0
- package/src/components/DataTable/hooks/__tests__/useDataTableEdit.test.ts +239 -0
- package/src/components/DataTable/hooks/useDataTable.ts +145 -0
- package/src/components/DataTable/hooks/useDataTableAdvanced.ts +342 -0
- package/src/components/DataTable/hooks/useDataTableAdvancedFilters.ts +637 -0
- package/src/components/DataTable/hooks/useDataTableColumnTemplates.ts +186 -0
- package/src/components/DataTable/hooks/useDataTableEdit.ts +167 -0
- package/src/components/DataTable/hooks/useDataTableExport.ts +227 -0
- package/src/components/DataTable/hooks/useDataTableImport.ts +216 -0
- package/src/components/DataTable/hooks/useDataTableOffline.ts +481 -0
- package/src/components/DataTable/hooks/useDataTableTheme.ts +213 -0
- package/src/components/DataTable/hooks/useDataTableVirtualization.ts +99 -0
- package/src/components/DataTable/hooks/useTableLayout.ts +85 -0
- package/src/components/DataTable/index.ts +81 -0
- package/src/components/DataTable/services/IndexedDBService.ts +504 -0
- package/src/components/DataTable/templates/index.tsx +803 -0
- package/src/components/DataTable/types.ts +504 -0
- package/src/components/DataTable/utils.ts +164 -0
- package/src/components/DataTable/workers/exportWorker.ts +213 -0
- package/src/components/accordion/index.tsx +61 -0
- package/src/components/alert/index.tsx +61 -0
- package/src/components/alert-dialog/index.tsx +146 -0
- package/src/components/aspect-ratio/index.tsx +12 -0
- package/src/components/avatar/index.tsx +54 -0
- package/src/components/badge/Badge.stories.tsx +64 -0
- package/src/components/badge/index.tsx +38 -0
- package/src/components/button/Button.stories.tsx +173 -0
- package/src/components/button/index.tsx +56 -0
- package/src/components/calendar/index.tsx +73 -0
- package/src/components/card/index.tsx +78 -0
- package/src/components/checkbox/index.tsx +34 -0
- package/src/components/code/index.tsx +229 -0
- package/src/components/collapsible/index.tsx +16 -0
- package/src/components/command/index.tsx +162 -0
- package/src/components/context-menu/index.tsx +204 -0
- package/src/components/dialog/index.tsx +126 -0
- package/src/components/dropdown-menu/index.tsx +204 -0
- package/src/components/error-boundary/ErrorBoundary.tsx +281 -0
- package/src/components/error-boundary/index.ts +7 -0
- package/src/components/form/index.tsx +183 -0
- package/src/components/hover-card/index.tsx +33 -0
- package/src/components/index.ts +368 -0
- package/src/components/input/Input.stories.tsx +100 -0
- package/src/components/input/index.tsx +27 -0
- package/src/components/input-otp/index.tsx +277 -0
- package/src/components/label/index.tsx +30 -0
- package/src/components/language-selector/index.tsx +341 -0
- package/src/components/menubar/index.tsx +240 -0
- package/src/components/navigation-menu/index.tsx +134 -0
- package/src/components/popover/index.tsx +35 -0
- package/src/components/progress/index.tsx +32 -0
- package/src/components/radio-group/index.tsx +48 -0
- package/src/components/scroll-area/index.tsx +52 -0
- package/src/components/select/index.tsx +164 -0
- package/src/components/separator/index.tsx +35 -0
- package/src/components/sheet/index.tsx +147 -0
- package/src/components/skeleton/index.tsx +22 -0
- package/src/components/slider/index.tsx +32 -0
- package/src/components/switch/index.tsx +33 -0
- package/src/components/table/index.tsx +117 -0
- package/src/components/tabs/index.tsx +59 -0
- package/src/components/textarea/index.tsx +30 -0
- package/src/components/theme-selector/index.tsx +327 -0
- package/src/components/toast/index.tsx +133 -0
- package/src/components/toaster/index.tsx +34 -0
- package/src/components/toggle/index.tsx +49 -0
- package/src/components/tooltip/index.tsx +34 -0
- package/src/components/typography/index.tsx +276 -0
- package/src/components/waka-3d-pie-chart/index.tsx +486 -0
- package/src/components/waka-achievement-unlock/index.tsx +716 -0
- package/src/components/waka-activity-feed/index.tsx +686 -0
- package/src/components/waka-address-autocomplete/index.tsx +1202 -0
- package/src/components/waka-admincrumb/index.tsx +349 -0
- package/src/components/waka-alert-stack/index.tsx +827 -0
- package/src/components/waka-allocation-matrix/index.tsx +1278 -0
- package/src/components/waka-approval-chain/index.tsx +766 -0
- package/src/components/waka-audit-log/index.tsx +1475 -0
- package/src/components/waka-autocomplete/index.tsx +358 -0
- package/src/components/waka-badge-showcase/index.tsx +704 -0
- package/src/components/waka-barcode/index.tsx +260 -0
- package/src/components/waka-biometric-prompt/index.tsx +765 -0
- package/src/components/waka-bottom-sheet/index.tsx +495 -0
- package/src/components/waka-breadcrumb/index.tsx +376 -0
- package/src/components/waka-breadcrumb-path/index.tsx +513 -0
- package/src/components/waka-budget-burn/index.tsx +1234 -0
- package/src/components/waka-capacity-planner/index.tsx +1107 -0
- package/src/components/waka-carousel/index.tsx +893 -0
- package/src/components/waka-cart-summary/index.tsx +1055 -0
- package/src/components/waka-challenge-timer/index.tsx +1044 -0
- package/src/components/waka-charts/WakaAreaChart.tsx +251 -0
- package/src/components/waka-charts/WakaBarChart.tsx +222 -0
- package/src/components/waka-charts/WakaChart.tsx +124 -0
- package/src/components/waka-charts/WakaLineChart.tsx +219 -0
- package/src/components/waka-charts/WakaMiniChart.tsx +133 -0
- package/src/components/waka-charts/WakaPieChart.tsx +214 -0
- package/src/components/waka-charts/WakaSparkline.tsx +229 -0
- package/src/components/waka-charts/dataTableHelpers.ts +109 -0
- package/src/components/waka-charts/hooks/useChartTheme.ts +123 -0
- package/src/components/waka-charts/hooks/useRechartsLoader.ts +234 -0
- package/src/components/waka-charts/index.ts +90 -0
- package/src/components/waka-charts/types.ts +330 -0
- package/src/components/waka-chat-bubble/index.tsx +1060 -0
- package/src/components/waka-checklist/index.tsx +1067 -0
- package/src/components/waka-checkout-stepper/index.tsx +976 -0
- package/src/components/waka-cohort-table/index.tsx +1011 -0
- package/src/components/waka-color-picker/index.tsx +447 -0
- package/src/components/waka-combo-counter/index.tsx +864 -0
- package/src/components/waka-combobox/index.tsx +497 -0
- package/src/components/waka-command-bar/index.tsx +403 -0
- package/src/components/waka-compare-period/index.tsx +1230 -0
- package/src/components/waka-connection-matrix/index.tsx +1053 -0
- package/src/components/waka-contribution-graph/index.tsx +552 -0
- package/src/components/waka-cost-breakdown/index.tsx +1065 -0
- package/src/components/waka-coupon-input/index.tsx +592 -0
- package/src/components/waka-credit-card-input/index.tsx +982 -0
- package/src/components/waka-daily-reward/index.tsx +762 -0
- package/src/components/waka-date-range-picker/index.tsx +378 -0
- package/src/components/waka-datetime-picker/index.tsx +793 -0
- package/src/components/waka-datetime-picker.form-integration/index.tsx +402 -0
- package/src/components/waka-deployment-lane/index.tsx +673 -0
- package/src/components/waka-device-trust/index.tsx +1259 -0
- package/src/components/waka-dock/index.tsx +285 -0
- package/src/components/waka-drawer/index.tsx +319 -0
- package/src/components/waka-empty-state/index.tsx +545 -0
- package/src/components/waka-error-shake/index.tsx +398 -0
- package/src/components/waka-feature-announcement/index.tsx +991 -0
- package/src/components/waka-file-upload/index.tsx +437 -0
- package/src/components/waka-floating-nav/index.tsx +413 -0
- package/src/components/waka-flow-diagram/index.tsx +508 -0
- package/src/components/waka-funnel-chart/index.tsx +823 -0
- package/src/components/waka-glow-card/index.tsx +246 -0
- package/src/components/waka-goal-progress/index.tsx +1025 -0
- package/src/components/waka-haptic-button/index.tsx +388 -0
- package/src/components/waka-health-pulse/index.tsx +451 -0
- package/src/components/waka-heatmap/index.tsx +1026 -0
- package/src/components/waka-hotspot/index.tsx +682 -0
- package/src/components/waka-image/index.tsx +373 -0
- package/src/components/waka-incident-timeline/index.tsx +686 -0
- package/src/components/waka-invoice-preview/index.tsx +829 -0
- package/src/components/waka-kanban/index.tsx +646 -0
- package/src/components/waka-kpi-dashboard/index.tsx +755 -0
- package/src/components/waka-leaderboard/index.tsx +746 -0
- package/src/components/waka-level-progress/index.tsx +665 -0
- package/src/components/waka-liquid-button/index.tsx +520 -0
- package/src/components/waka-loading-orbit/index.tsx +478 -0
- package/src/components/waka-loot-box/index.tsx +1091 -0
- package/src/components/waka-magic-link/index.tsx +321 -0
- package/src/components/waka-magnetic-button/index.tsx +567 -0
- package/src/components/waka-mention-input/index.tsx +953 -0
- package/src/components/waka-metric-sparkline/index.tsx +627 -0
- package/src/components/waka-milestone-road/index.tsx +1064 -0
- package/src/components/waka-modal/index.tsx +374 -0
- package/src/components/waka-morph-button/index.tsx +495 -0
- package/src/components/waka-network-topology/index.tsx +801 -0
- package/src/components/waka-notifications/index.tsx +414 -0
- package/src/components/waka-number-input/index.tsx +373 -0
- package/src/components/waka-orbital-menu/index.tsx +445 -0
- package/src/components/waka-order-tracker/index.tsx +1041 -0
- package/src/components/waka-pagination/index.tsx +393 -0
- package/src/components/waka-password-strength/index.tsx +824 -0
- package/src/components/waka-payment-method-picker/index.tsx +715 -0
- package/src/components/waka-permission-matrix/index.tsx +1302 -0
- package/src/components/waka-phone-input/index.tsx +801 -0
- package/src/components/waka-pipeline-view/index.tsx +604 -0
- package/src/components/waka-player-card/index.tsx +691 -0
- package/src/components/waka-points-popup/index.tsx +366 -0
- package/src/components/waka-power-up/index.tsx +1155 -0
- package/src/components/waka-presence-indicator/index.tsx +1181 -0
- package/src/components/waka-pricing-table/index.tsx +755 -0
- package/src/components/waka-product-card/index.tsx +786 -0
- package/src/components/waka-progress-onboarding/index.tsx +878 -0
- package/src/components/waka-pull-to-refresh/index.tsx +451 -0
- package/src/components/waka-qrcode/index.tsx +232 -0
- package/src/components/waka-quest-card/index.tsx +1275 -0
- package/src/components/waka-quota-bar/index.tsx +693 -0
- package/src/components/waka-radar-score/index.tsx +512 -0
- package/src/components/waka-rank-badge/index.tsx +813 -0
- package/src/components/waka-rating-input/index.tsx +560 -0
- package/src/components/waka-reaction-picker/index.tsx +1062 -0
- package/src/components/waka-region-map/index.tsx +730 -0
- package/src/components/waka-resource-gauge/index.tsx +654 -0
- package/src/components/waka-resource-pool/index.tsx +1035 -0
- package/src/components/waka-rich-text-editor/index.tsx +594 -0
- package/src/components/waka-rollback-slider/index.tsx +891 -0
- package/src/components/waka-sankey-diagram/index.tsx +1032 -0
- package/src/components/waka-schedule-picker/index.tsx +1060 -0
- package/src/components/waka-scratch-card/index.tsx +914 -0
- package/src/components/waka-season-pass/index.tsx +886 -0
- package/src/components/waka-security-score/index.tsx +1126 -0
- package/src/components/waka-segmented-control/index.tsx +238 -0
- package/src/components/waka-server-rack/index.tsx +764 -0
- package/src/components/waka-session-manager/index.tsx +815 -0
- package/src/components/waka-signature-pad/index.tsx +744 -0
- package/src/components/waka-skeleton-wave/index.tsx +454 -0
- package/src/components/waka-skill-tree/index.tsx +1031 -0
- package/src/components/waka-sla-tracker/index.tsx +798 -0
- package/src/components/waka-slider-range/index.tsx +765 -0
- package/src/components/waka-spin-wheel/index.tsx +671 -0
- package/src/components/waka-spinner/index.tsx +284 -0
- package/src/components/waka-spotlight/index.tsx +410 -0
- package/src/components/waka-stat/index.tsx +428 -0
- package/src/components/waka-stats-hexagon/index.tsx +824 -0
- package/src/components/waka-status-matrix/index.tsx +565 -0
- package/src/components/waka-stepper/index.tsx +489 -0
- package/src/components/waka-streak-counter/index.tsx +334 -0
- package/src/components/waka-success-explosion/index.tsx +453 -0
- package/src/components/waka-swipe-card/index.tsx +574 -0
- package/src/components/waka-tabs-morph/index.tsx +509 -0
- package/src/components/waka-tag-input/index.tsx +877 -0
- package/src/components/waka-team-banner/index.tsx +1183 -0
- package/src/components/waka-terminal-output/index.tsx +836 -0
- package/src/components/waka-theme-creator/index.tsx +762 -0
- package/src/components/waka-theme-manager/index.tsx +654 -0
- package/src/components/waka-thread-view/index.tsx +874 -0
- package/src/components/waka-tilt-card/index.tsx +250 -0
- package/src/components/waka-time-picker/index.tsx +479 -0
- package/src/components/waka-timeline/index.tsx +385 -0
- package/src/components/waka-tooltip-tour/index.tsx +855 -0
- package/src/components/waka-tour-guide/index.tsx +920 -0
- package/src/components/waka-tournament-bracket/index.tsx +1276 -0
- package/src/components/waka-tree/index.tsx +557 -0
- package/src/components/waka-treemap-chart/index.tsx +1031 -0
- package/src/components/waka-two-factor-setup/index.tsx +995 -0
- package/src/components/waka-typewriter/index.tsx +566 -0
- package/src/components/waka-typing-indicator/index.tsx +649 -0
- package/src/components/waka-versus-card/index.tsx +1026 -0
- package/src/components/waka-video/index.tsx +557 -0
- package/src/components/waka-video-call/index.tsx +1087 -0
- package/src/components/waka-virtual-list/index.tsx +327 -0
- package/src/components/waka-voice-message/index.tsx +1019 -0
- package/src/components/waka-welcome-modal/index.tsx +790 -0
- package/src/components/waka-xp-bar/index.tsx +799 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
import { ColumnDef, PaginationState, SortingState, ColumnFiltersState, VisibilityState, ColumnOrderState, ExpandedState, GroupingState } from "@tanstack/react-table"
|
|
2
|
+
import { ReactNode } from "react"
|
|
3
|
+
import { EditCellConfig } from "./DataTableEditCell"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Layout variants pour le DataTable
|
|
7
|
+
*/
|
|
8
|
+
export type DataTableLayout = "standard" | "card" | "compact" | "split" | "infinite"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Variantes visuelles
|
|
12
|
+
*/
|
|
13
|
+
export type DataTableVariant = "bordered" | "minimal" | "striped" | "glass"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Densité d'affichage
|
|
17
|
+
*/
|
|
18
|
+
export type DataTableDensity = "comfortable" | "compact" | "spacious"
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Mode de sélection
|
|
22
|
+
*/
|
|
23
|
+
export type SelectionMode = "single" | "multiple" | "range"
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Mode de tri
|
|
27
|
+
*/
|
|
28
|
+
export type SortMode = "single" | "multiple"
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Type de virtualisation
|
|
32
|
+
*/
|
|
33
|
+
export type VirtualizationType = "none" | "fixed" | "dynamic"
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Position des filtres
|
|
37
|
+
*/
|
|
38
|
+
export type FilterPosition = "top" | "bottom" | "left" | "right" | "modal"
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Configuration de pagination
|
|
42
|
+
*/
|
|
43
|
+
export interface PaginationConfig {
|
|
44
|
+
/** Mode de pagination */
|
|
45
|
+
mode?: "client" | "server"
|
|
46
|
+
/** Taille de page par défaut */
|
|
47
|
+
pageSize?: number
|
|
48
|
+
/** Options de tailles de page */
|
|
49
|
+
pageSizeOptions?: number[]
|
|
50
|
+
/** Page courante (mode serveur) */
|
|
51
|
+
currentPage?: number
|
|
52
|
+
/** Total d'items (mode serveur) */
|
|
53
|
+
totalItems?: number
|
|
54
|
+
/** Callback de changement de page */
|
|
55
|
+
onPageChange?: (page: number) => void
|
|
56
|
+
/** Callback de changement de taille */
|
|
57
|
+
onPageSizeChange?: (size: number) => void
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Configuration d'un filtre
|
|
62
|
+
*/
|
|
63
|
+
export interface FilterConfig {
|
|
64
|
+
/** ID unique du filtre */
|
|
65
|
+
id: string
|
|
66
|
+
/** Libellé du filtre */
|
|
67
|
+
label: string
|
|
68
|
+
/** Type de filtre */
|
|
69
|
+
type: "text" | "select" | "range" | "date" | "daterange" | "multiselect" | "checkbox" | "number" | "boolean"
|
|
70
|
+
/** Options pour select/multiselect */
|
|
71
|
+
options?: Array<{ label: string; value: string | number }>
|
|
72
|
+
/** Placeholder */
|
|
73
|
+
placeholder?: string
|
|
74
|
+
/** Valeur par défaut */
|
|
75
|
+
defaultValue?: any
|
|
76
|
+
/** Colonne associée */
|
|
77
|
+
column?: string
|
|
78
|
+
/** Fonction de filtrage personnalisée */
|
|
79
|
+
filterFn?: (row: any, columnId: string, filterValue: any) => boolean
|
|
80
|
+
/** Validation du filtre */
|
|
81
|
+
validate?: (value: any) => string | null
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Configuration de groupement
|
|
86
|
+
*/
|
|
87
|
+
export interface GroupingConfig {
|
|
88
|
+
/** Colonnes de groupement */
|
|
89
|
+
columns?: string[]
|
|
90
|
+
/** Fonction d'agrégation personnalisée */
|
|
91
|
+
aggregations?: Record<string, (values: any[]) => any>
|
|
92
|
+
/** Affichage des totaux */
|
|
93
|
+
showTotals?: boolean
|
|
94
|
+
/** Position des totaux */
|
|
95
|
+
totalsPosition?: "top" | "bottom" | "both"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Configuration de virtualisation
|
|
100
|
+
*/
|
|
101
|
+
export interface VirtualizationConfig {
|
|
102
|
+
/** Type de virtualisation */
|
|
103
|
+
type: VirtualizationType
|
|
104
|
+
/** Hauteur fixe des lignes */
|
|
105
|
+
itemHeight?: number
|
|
106
|
+
/** Hauteur estimée pour la virtualisation dynamique */
|
|
107
|
+
estimatedItemHeight?: number
|
|
108
|
+
/** Nombre d'éléments à pré-rendre */
|
|
109
|
+
overscan?: number
|
|
110
|
+
/** Hauteur du conteneur */
|
|
111
|
+
containerHeight?: number
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Configuration de redimensionnement des colonnes
|
|
116
|
+
*/
|
|
117
|
+
export interface ColumnResizeConfig {
|
|
118
|
+
/** Mode de redimensionnement */
|
|
119
|
+
mode?: "onChange" | "onEnd"
|
|
120
|
+
/** Colonnes redimensionnables */
|
|
121
|
+
resizable?: boolean
|
|
122
|
+
/** Largeur minimale */
|
|
123
|
+
minSize?: number
|
|
124
|
+
/** Largeur maximale */
|
|
125
|
+
maxSize?: number
|
|
126
|
+
/** Largeur par défaut */
|
|
127
|
+
defaultSize?: number
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Configuration de réordonnancement
|
|
132
|
+
*/
|
|
133
|
+
export interface ColumnOrderConfig {
|
|
134
|
+
/** Activer le réordonnancement */
|
|
135
|
+
enabled?: boolean
|
|
136
|
+
/** Colonnes non réordonnables */
|
|
137
|
+
disabled?: string[]
|
|
138
|
+
/** Callback de changement d'ordre */
|
|
139
|
+
onOrderChange?: (newOrder: string[]) => void
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Configuration d'expansion des lignes
|
|
144
|
+
*/
|
|
145
|
+
export interface RowExpansionConfig {
|
|
146
|
+
/** Activer l'expansion */
|
|
147
|
+
enabled?: boolean
|
|
148
|
+
/** Colonne d'expansion */
|
|
149
|
+
columnId?: string
|
|
150
|
+
/** Fonction de rendu du contenu étendu */
|
|
151
|
+
renderExpanded?: (row: any) => ReactNode
|
|
152
|
+
/** État d'expansion initial */
|
|
153
|
+
initialExpanded?: Record<string, boolean>
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Action de la toolbar
|
|
158
|
+
*/
|
|
159
|
+
export interface TableAction {
|
|
160
|
+
/** ID unique */
|
|
161
|
+
id: string
|
|
162
|
+
/** Libellé */
|
|
163
|
+
label: string
|
|
164
|
+
/** Icône (composant React) */
|
|
165
|
+
icon?: ReactNode
|
|
166
|
+
/** Callback */
|
|
167
|
+
onClick: (selectedRows: any[]) => void
|
|
168
|
+
/** Visible seulement si sélection */
|
|
169
|
+
requiresSelection?: boolean
|
|
170
|
+
/** Variant du bouton */
|
|
171
|
+
variant?: "default" | "destructive" | "outline" | "ghost"
|
|
172
|
+
/** Désactivé */
|
|
173
|
+
disabled?: boolean
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Configuration de la toolbar
|
|
178
|
+
*/
|
|
179
|
+
export interface ToolbarConfig {
|
|
180
|
+
/** Actions personnalisées */
|
|
181
|
+
actions?: TableAction[]
|
|
182
|
+
/** Afficher la recherche globale */
|
|
183
|
+
showSearch?: boolean
|
|
184
|
+
/** Afficher le sélecteur de colonnes */
|
|
185
|
+
showColumnToggle?: boolean
|
|
186
|
+
/** Afficher le changement de densité */
|
|
187
|
+
showDensity?: boolean
|
|
188
|
+
/** Afficher le bouton de refresh */
|
|
189
|
+
showRefresh?: boolean
|
|
190
|
+
/** Callback de refresh */
|
|
191
|
+
onRefresh?: () => void
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Configuration d'export
|
|
196
|
+
*/
|
|
197
|
+
export interface ExportConfig {
|
|
198
|
+
/** Formats supportés */
|
|
199
|
+
formats?: Array<"csv" | "xlsx" | "json" | "pdf" | "xml">
|
|
200
|
+
/** Nom du fichier */
|
|
201
|
+
filename?: string
|
|
202
|
+
/** Callback personnalisé */
|
|
203
|
+
onExport?: (data: any[], format: string) => void
|
|
204
|
+
/** Colonnes à exporter */
|
|
205
|
+
columns?: string[]
|
|
206
|
+
/** Inclure les en-têtes */
|
|
207
|
+
includeHeaders?: boolean
|
|
208
|
+
/** Formatage personnalisé */
|
|
209
|
+
formatters?: Record<string, (value: any) => string>
|
|
210
|
+
/** Options spécifiques par format */
|
|
211
|
+
options?: {
|
|
212
|
+
csv?: { delimiter?: string; encoding?: string }
|
|
213
|
+
xlsx?: { sheetName?: string; includeStyles?: boolean }
|
|
214
|
+
pdf?: { orientation?: "portrait" | "landscape"; pageSize?: string }
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Configuration d'import
|
|
220
|
+
*/
|
|
221
|
+
export interface ImportConfig {
|
|
222
|
+
/** Formats acceptés */
|
|
223
|
+
accept?: string
|
|
224
|
+
/** Callback de traitement */
|
|
225
|
+
onImport?: (data: any[]) => void
|
|
226
|
+
/** Validation des données */
|
|
227
|
+
validate?: (data: any[]) => { valid: boolean; errors: string[] }
|
|
228
|
+
/** Mapping des colonnes */
|
|
229
|
+
columnMapping?: Record<string, string>
|
|
230
|
+
/** Options de parsing */
|
|
231
|
+
parseOptions?: {
|
|
232
|
+
csv?: { delimiter?: string; skipEmptyLines?: boolean }
|
|
233
|
+
xlsx?: { sheetIndex?: number; headerRow?: number }
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* État de sélection
|
|
239
|
+
*/
|
|
240
|
+
export interface SelectionState {
|
|
241
|
+
/** IDs sélectionnés */
|
|
242
|
+
selectedIds: Set<string>
|
|
243
|
+
/** Tout sélectionné */
|
|
244
|
+
selectAll: boolean
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Props principales du DataTable
|
|
249
|
+
*/
|
|
250
|
+
export interface DataTableProps<TData> {
|
|
251
|
+
/** Données à afficher */
|
|
252
|
+
data: TData[]
|
|
253
|
+
|
|
254
|
+
/** Définition des colonnes */
|
|
255
|
+
columns: ColumnDef<TData, any>[]
|
|
256
|
+
|
|
257
|
+
/** Layout d'affichage */
|
|
258
|
+
layout?: DataTableLayout
|
|
259
|
+
|
|
260
|
+
/** Variant visuel */
|
|
261
|
+
variant?: DataTableVariant
|
|
262
|
+
|
|
263
|
+
/** Densité */
|
|
264
|
+
density?: DataTableDensity
|
|
265
|
+
|
|
266
|
+
/** Configuration des filtres */
|
|
267
|
+
filters?: FilterConfig[]
|
|
268
|
+
|
|
269
|
+
/** Position des filtres */
|
|
270
|
+
filterPosition?: FilterPosition
|
|
271
|
+
|
|
272
|
+
/** Configuration de la toolbar */
|
|
273
|
+
toolbar?: ToolbarConfig
|
|
274
|
+
|
|
275
|
+
/** Configuration de la pagination */
|
|
276
|
+
pagination?: PaginationConfig
|
|
277
|
+
|
|
278
|
+
/** Mode de sélection */
|
|
279
|
+
selection?: SelectionMode | boolean
|
|
280
|
+
|
|
281
|
+
/** Actions sur les lignes */
|
|
282
|
+
actions?: TableAction[]
|
|
283
|
+
|
|
284
|
+
/** Namespace i18n */
|
|
285
|
+
i18nNamespace?: string
|
|
286
|
+
|
|
287
|
+
/** État de chargement */
|
|
288
|
+
loading?: boolean
|
|
289
|
+
|
|
290
|
+
/** Message d'erreur */
|
|
291
|
+
error?: string | null
|
|
292
|
+
|
|
293
|
+
/** État vide personnalisé */
|
|
294
|
+
emptyState?: ReactNode
|
|
295
|
+
|
|
296
|
+
/** Header sticky */
|
|
297
|
+
headerSticky?: boolean
|
|
298
|
+
|
|
299
|
+
/** Toggle de visibilité des colonnes */
|
|
300
|
+
columnVisibilityToggle?: boolean
|
|
301
|
+
|
|
302
|
+
/** Configuration de redimensionnement des colonnes */
|
|
303
|
+
columnResize?: boolean | ColumnResizeConfig
|
|
304
|
+
|
|
305
|
+
/** Configuration de réordonnancement */
|
|
306
|
+
columnOrder?: ColumnOrderConfig
|
|
307
|
+
|
|
308
|
+
/** Configuration de groupement */
|
|
309
|
+
grouping?: GroupingConfig
|
|
310
|
+
|
|
311
|
+
/** Configuration d'expansion des lignes */
|
|
312
|
+
rowExpansion?: RowExpansionConfig
|
|
313
|
+
|
|
314
|
+
/** Configuration de virtualisation */
|
|
315
|
+
virtualization?: VirtualizationConfig
|
|
316
|
+
|
|
317
|
+
/** Mode de tri */
|
|
318
|
+
sortMode?: SortMode
|
|
319
|
+
|
|
320
|
+
/** Activer l'export */
|
|
321
|
+
enableExport?: boolean | ExportConfig
|
|
322
|
+
|
|
323
|
+
/** Activer l'import */
|
|
324
|
+
enableImport?: boolean | ImportConfig
|
|
325
|
+
|
|
326
|
+
/** Activer le réordonnancement */
|
|
327
|
+
enableReorder?: boolean
|
|
328
|
+
|
|
329
|
+
/** Menu contextuel */
|
|
330
|
+
enableContextMenu?: boolean
|
|
331
|
+
|
|
332
|
+
/** Callback de clic sur ligne */
|
|
333
|
+
onRowClick?: (row: TData) => void
|
|
334
|
+
|
|
335
|
+
/** Callback de double-clic */
|
|
336
|
+
onRowDoubleClick?: (row: TData) => void
|
|
337
|
+
|
|
338
|
+
/** Callback de changement de tri */
|
|
339
|
+
onSortingChange?: (sorting: SortingState) => void
|
|
340
|
+
|
|
341
|
+
/** Callback de changement de filtres */
|
|
342
|
+
onFiltersChange?: (filters: ColumnFiltersState) => void
|
|
343
|
+
|
|
344
|
+
/** Callback de changement de sélection */
|
|
345
|
+
onSelectionChange?: (selectedRows: TData[]) => void
|
|
346
|
+
|
|
347
|
+
/** Callback de changement d'ordre des colonnes */
|
|
348
|
+
onColumnOrderChange?: (order: ColumnOrderState) => void
|
|
349
|
+
|
|
350
|
+
/** Callback de changement d'expansion */
|
|
351
|
+
onExpandedChange?: (expanded: ExpandedState) => void
|
|
352
|
+
|
|
353
|
+
/** Callback de changement de groupement */
|
|
354
|
+
onGroupingChange?: (grouping: GroupingState) => void
|
|
355
|
+
|
|
356
|
+
/** Classe CSS personnalisée */
|
|
357
|
+
className?: string
|
|
358
|
+
|
|
359
|
+
/** ID unique pour la persistance */
|
|
360
|
+
tableId?: string
|
|
361
|
+
|
|
362
|
+
/** Configuration d'édition */
|
|
363
|
+
edit?: EditConfig<TData>
|
|
364
|
+
|
|
365
|
+
/** Thème personnalisé */
|
|
366
|
+
theme?: {
|
|
367
|
+
colors?: Record<string, string>
|
|
368
|
+
spacing?: Record<string, string>
|
|
369
|
+
typography?: Record<string, any>
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** Options de performance */
|
|
373
|
+
performance?: {
|
|
374
|
+
/** Désactiver les animations */
|
|
375
|
+
disableAnimations?: boolean
|
|
376
|
+
/** Limite de rendu */
|
|
377
|
+
renderLimit?: number
|
|
378
|
+
/** Délai de debounce pour les filtres */
|
|
379
|
+
filterDebounceMs?: number
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Configuration d'édition pour une colonne
|
|
385
|
+
*/
|
|
386
|
+
export interface ColumnEditConfig<TData> {
|
|
387
|
+
/** Champ éditable */
|
|
388
|
+
field: keyof TData
|
|
389
|
+
/** Configuration de la cellule d'édition */
|
|
390
|
+
config: EditCellConfig
|
|
391
|
+
/** Validation personnalisée */
|
|
392
|
+
validate?: (value: any, row: TData) => string | null
|
|
393
|
+
/** Callback de changement */
|
|
394
|
+
onChange?: (value: any, row: TData) => void
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Configuration d'édition du DataTable
|
|
399
|
+
*/
|
|
400
|
+
export interface EditConfig<TData> {
|
|
401
|
+
/** Colonnes éditables */
|
|
402
|
+
editableColumns?: ColumnEditConfig<TData>[]
|
|
403
|
+
/** Mode d'édition */
|
|
404
|
+
mode?: "inline" | "modal" | "row"
|
|
405
|
+
/** Auto-save */
|
|
406
|
+
autoSave?: boolean
|
|
407
|
+
/** Délai d'auto-save en ms */
|
|
408
|
+
autoSaveDelay?: number
|
|
409
|
+
/** Callback de sauvegarde */
|
|
410
|
+
onSave?: (rowId: string, data: Partial<TData>) => Promise<void>
|
|
411
|
+
/** Callback d'annulation */
|
|
412
|
+
onCancel?: (rowId: string, originalData: TData) => void
|
|
413
|
+
/** Validation globale */
|
|
414
|
+
validate?: (data: Partial<TData>, row: TData) => Record<string, string>
|
|
415
|
+
/** Boutons d'action personnalisés */
|
|
416
|
+
actionButtons?: {
|
|
417
|
+
save?: ReactNode
|
|
418
|
+
cancel?: ReactNode
|
|
419
|
+
edit?: ReactNode
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* État interne du DataTable
|
|
425
|
+
*/
|
|
426
|
+
export interface DataTableState {
|
|
427
|
+
sorting: SortingState
|
|
428
|
+
columnFilters: ColumnFiltersState
|
|
429
|
+
columnVisibility: VisibilityState
|
|
430
|
+
columnOrder: ColumnOrderState
|
|
431
|
+
expanded: ExpandedState
|
|
432
|
+
grouping: GroupingState
|
|
433
|
+
pagination: PaginationState
|
|
434
|
+
globalFilter: string
|
|
435
|
+
density: DataTableDensity
|
|
436
|
+
layout: DataTableLayout
|
|
437
|
+
rowSelection: Record<string, boolean>
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Configuration de thème personnalisé
|
|
442
|
+
*/
|
|
443
|
+
export interface DataTableTheme {
|
|
444
|
+
/** Couleurs personnalisées */
|
|
445
|
+
colors?: {
|
|
446
|
+
primary?: string
|
|
447
|
+
secondary?: string
|
|
448
|
+
accent?: string
|
|
449
|
+
background?: string
|
|
450
|
+
surface?: string
|
|
451
|
+
text?: string
|
|
452
|
+
textSecondary?: string
|
|
453
|
+
border?: string
|
|
454
|
+
hover?: string
|
|
455
|
+
selected?: string
|
|
456
|
+
disabled?: string
|
|
457
|
+
}
|
|
458
|
+
/** Espacement personnalisé */
|
|
459
|
+
spacing?: {
|
|
460
|
+
xs?: string
|
|
461
|
+
sm?: string
|
|
462
|
+
md?: string
|
|
463
|
+
lg?: string
|
|
464
|
+
xl?: string
|
|
465
|
+
}
|
|
466
|
+
/** Typographie personnalisée */
|
|
467
|
+
typography?: {
|
|
468
|
+
fontFamily?: string
|
|
469
|
+
fontSize?: {
|
|
470
|
+
xs?: string
|
|
471
|
+
sm?: string
|
|
472
|
+
md?: string
|
|
473
|
+
lg?: string
|
|
474
|
+
xl?: string
|
|
475
|
+
}
|
|
476
|
+
fontWeight?: {
|
|
477
|
+
normal?: string
|
|
478
|
+
medium?: string
|
|
479
|
+
semibold?: string
|
|
480
|
+
bold?: string
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
/** Bordures personnalisées */
|
|
484
|
+
borders?: {
|
|
485
|
+
radius?: {
|
|
486
|
+
sm?: string
|
|
487
|
+
md?: string
|
|
488
|
+
lg?: string
|
|
489
|
+
}
|
|
490
|
+
width?: {
|
|
491
|
+
thin?: string
|
|
492
|
+
medium?: string
|
|
493
|
+
thick?: string
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
/** Ombres personnalisées */
|
|
497
|
+
shadows?: {
|
|
498
|
+
sm?: string
|
|
499
|
+
md?: string
|
|
500
|
+
lg?: string
|
|
501
|
+
xl?: string
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { clsx, type ClassValue } from "clsx"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Utilitaire pour merger les classes CSS
|
|
5
|
+
*/
|
|
6
|
+
export function cn(...inputs: ClassValue[]) {
|
|
7
|
+
return clsx(inputs)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Export des données en CSV
|
|
12
|
+
*/
|
|
13
|
+
export function exportToCSV<T extends Record<string, any>>(
|
|
14
|
+
data: T[],
|
|
15
|
+
filename: string = "export.csv"
|
|
16
|
+
): void {
|
|
17
|
+
if (!data || data.length === 0) return
|
|
18
|
+
|
|
19
|
+
// Extraire les en-têtes
|
|
20
|
+
const headers = Object.keys(data[0])
|
|
21
|
+
|
|
22
|
+
// Créer les lignes CSV
|
|
23
|
+
const csvContent = [
|
|
24
|
+
headers.join(","),
|
|
25
|
+
...data.map((row) =>
|
|
26
|
+
headers
|
|
27
|
+
.map((header) => {
|
|
28
|
+
const value = row[header]
|
|
29
|
+
// Échapper les guillemets et entourer de guillemets si nécessaire
|
|
30
|
+
if (typeof value === "string" && (value.includes(",") || value.includes('"') || value.includes("\n"))) {
|
|
31
|
+
return `"${value.replace(/"/g, '""')}"`
|
|
32
|
+
}
|
|
33
|
+
return value
|
|
34
|
+
})
|
|
35
|
+
.join(",")
|
|
36
|
+
),
|
|
37
|
+
].join("\n")
|
|
38
|
+
|
|
39
|
+
// Télécharger le fichier
|
|
40
|
+
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" })
|
|
41
|
+
const link = document.createElement("a")
|
|
42
|
+
link.href = URL.createObjectURL(blob)
|
|
43
|
+
link.download = filename
|
|
44
|
+
link.click()
|
|
45
|
+
URL.revokeObjectURL(link.href)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Export des données en JSON
|
|
50
|
+
*/
|
|
51
|
+
export function exportToJSON<T>(data: T[], filename: string = "export.json"): void {
|
|
52
|
+
const jsonContent = JSON.stringify(data, null, 2)
|
|
53
|
+
const blob = new Blob([jsonContent], { type: "application/json;charset=utf-8;" })
|
|
54
|
+
const link = document.createElement("a")
|
|
55
|
+
link.href = URL.createObjectURL(blob)
|
|
56
|
+
link.download = filename
|
|
57
|
+
link.click()
|
|
58
|
+
URL.revokeObjectURL(link.href)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Parse un fichier CSV
|
|
63
|
+
*/
|
|
64
|
+
export async function parseCSV(file: File): Promise<any[]> {
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
const reader = new FileReader()
|
|
67
|
+
|
|
68
|
+
reader.onload = (e) => {
|
|
69
|
+
try {
|
|
70
|
+
const text = e.target?.result as string
|
|
71
|
+
const lines = text.split("\n").filter((line) => line.trim())
|
|
72
|
+
|
|
73
|
+
if (lines.length === 0) {
|
|
74
|
+
resolve([])
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Première ligne = en-têtes
|
|
79
|
+
const headers = lines[0].split(",").map((h) => h.trim().replace(/^"|"$/g, ""))
|
|
80
|
+
|
|
81
|
+
// Lignes suivantes = données
|
|
82
|
+
const data = lines.slice(1).map((line) => {
|
|
83
|
+
const values = line.split(",").map((v) => v.trim().replace(/^"|"$/g, ""))
|
|
84
|
+
const row: any = {}
|
|
85
|
+
headers.forEach((header, index) => {
|
|
86
|
+
row[header] = values[index] || ""
|
|
87
|
+
})
|
|
88
|
+
return row
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
resolve(data)
|
|
92
|
+
} catch (error) {
|
|
93
|
+
reject(error)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
reader.onerror = () => reject(reader.error)
|
|
98
|
+
reader.readAsText(file)
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Sauvegarde de l'état dans localStorage
|
|
104
|
+
*/
|
|
105
|
+
export function saveTableState(tableId: string, state: any): void {
|
|
106
|
+
try {
|
|
107
|
+
localStorage.setItem(`datatable_${tableId}`, JSON.stringify(state))
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.warn("[DataTable] Failed to save state:", error)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Chargement de l'état depuis localStorage
|
|
115
|
+
*/
|
|
116
|
+
export function loadTableState(tableId: string): any | null {
|
|
117
|
+
try {
|
|
118
|
+
const saved = localStorage.getItem(`datatable_${tableId}`)
|
|
119
|
+
return saved ? JSON.parse(saved) : null
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.warn("[DataTable] Failed to load state:", error)
|
|
122
|
+
return null
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Génère un ID unique
|
|
128
|
+
*/
|
|
129
|
+
export function generateId(): string {
|
|
130
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Debounce une fonction
|
|
135
|
+
*/
|
|
136
|
+
export function debounce<T extends (...args: any[]) => any>(
|
|
137
|
+
func: T,
|
|
138
|
+
wait: number
|
|
139
|
+
): (...args: Parameters<T>) => void {
|
|
140
|
+
let timeout: NodeJS.Timeout | null = null
|
|
141
|
+
|
|
142
|
+
return function (...args: Parameters<T>) {
|
|
143
|
+
if (timeout) clearTimeout(timeout)
|
|
144
|
+
timeout = setTimeout(() => func(...args), wait)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Filtre global sur les données
|
|
150
|
+
*/
|
|
151
|
+
export function globalFilterFn<T extends Record<string, any>>(
|
|
152
|
+
row: T,
|
|
153
|
+
columnId: string,
|
|
154
|
+
filterValue: string
|
|
155
|
+
): boolean {
|
|
156
|
+
const searchValue = filterValue.toLowerCase()
|
|
157
|
+
|
|
158
|
+
// Rechercher dans toutes les valeurs de la ligne
|
|
159
|
+
return Object.values(row).some((value) => {
|
|
160
|
+
if (value == null) return false
|
|
161
|
+
return String(value).toLowerCase().includes(searchValue)
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
|