kelt-ui-kit-react 2.0.8 → 2.0.9

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 (319) hide show
  1. package/.github/workflows/publish.yml +40 -31
  2. package/README.md +124 -72
  3. package/dist/App.d.ts +2 -3
  4. package/dist/App.menu.d.ts +10 -10
  5. package/dist/App.routes.d.ts +1 -1
  6. package/dist/_core/hooks/HistoryProvider.d.ts +5 -5
  7. package/dist/_core/hooks/ImageChecker.d.ts +5 -6
  8. package/dist/_core/hooks/imageExist.d.ts +5 -6
  9. package/dist/_core/hooks/isEAN13.d.ts +1 -1
  10. package/dist/_core/hooks/objectToQueryParams.d.ts +1 -1
  11. package/dist/_core/hooks/useCurrency.d.ts +3 -3
  12. package/dist/_core/hooks/useDateutils.d.ts +4 -4
  13. package/dist/_core/hooks/useIsMobile.d.ts +1 -1
  14. package/dist/_core/hooks/useToken.d.ts +3 -3
  15. package/dist/_core/hooks/useValidate.d.ts +5 -5
  16. package/dist/_core/hooks/widgetSupport.d.ts +1 -1
  17. package/dist/_core/type/generiqueType.d.ts +4 -0
  18. package/dist/action/Action.view.d.ts +1 -1
  19. package/dist/action/ButtonAction.d.ts +8 -9
  20. package/dist/addressSearch/AddressSearch.d.ts +18 -19
  21. package/dist/addressSearch/AddressSearch.view.d.ts +1 -1
  22. package/dist/badge/Badge.d.ts +10 -9
  23. package/dist/badge/Badge.view.d.ts +1 -1
  24. package/dist/button/Button.d.ts +1 -2
  25. package/dist/button/Button.view.d.ts +1 -1
  26. package/dist/button/button.interface.d.ts +19 -20
  27. package/dist/button/buttonActions/ButtonActions.d.ts +11 -12
  28. package/dist/button/buttonFile/ButtonFile.d.ts +9 -9
  29. package/dist/button/buttonFile/ButtonFile.view.d.ts +1 -1
  30. package/dist/button/buttonFilters/ButtonFilters.d.ts +16 -17
  31. package/dist/card/Card.d.ts +14 -15
  32. package/dist/card/Card.view.d.ts +1 -1
  33. package/dist/card/card.interface.d.ts +10 -10
  34. package/dist/card/cardAction/CardAction.d.ts +13 -14
  35. package/dist/card/cardAction.interface.d.ts +8 -9
  36. package/dist/card/hook/useCardInteractions.d.ts +8 -8
  37. package/dist/carousel/Carousel.d.ts +14 -15
  38. package/dist/carousel/Carousel.view.d.ts +1 -1
  39. package/dist/damier/Damier.d.ts +9 -10
  40. package/dist/damier/Damier.view.d.ts +1 -1
  41. package/dist/damier/damierCell/DamierCell.d.ts +6 -7
  42. package/dist/damier/damierCell/damierCell.interface.d.ts +6 -6
  43. package/dist/dataTable/DataTable.d.ts +37 -33
  44. package/dist/dataTable/DataTable.view.d.ts +1 -1
  45. package/dist/dataTable/dataTable.interface.d.ts +70 -47
  46. package/dist/dataTable/dataTable.utils.d.ts +17 -0
  47. package/dist/dataTable/dataTableActions/DataTableAction.d.ts +9 -10
  48. package/dist/dataTable/dataTableColumn/DataTableColumn.d.ts +14 -8
  49. package/dist/dataTable/dataTableColumn/dataTableColumnFilter/DataTableColumnFilter.d.ts +9 -0
  50. package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDate/DataTableColumnFilterDate.d.ts +9 -0
  51. package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDateRange/dataTableColumnFilterDateRange.d.ts +9 -0
  52. package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterEnum/DataTableColumnFilterEnum.d.ts +12 -0
  53. package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterString/DataTableColumnFilterString.d.ts +9 -0
  54. package/dist/dataTable/dataTableColumn/dataTableColumnSort/DataTableColumnSort.d.ts +10 -0
  55. package/dist/dataTable/dataTableFilters/DataTableFilters.d.ts +6 -0
  56. package/dist/dataTable/dataTableLoading/DataTableLoading.d.ts +8 -7
  57. package/dist/dataTable/dataTableRow/DataTableRow.d.ts +12 -11
  58. package/dist/dataTable/useDataTableState.d.ts +13 -0
  59. package/dist/datePicker/DatePicker.d.ts +7 -8
  60. package/dist/datePicker/DatePicker.view.d.ts +1 -1
  61. package/dist/docs/ComponentDocs.d.ts +6 -0
  62. package/dist/docs/catalog.d.ts +8 -0
  63. package/dist/docs/documentation.types.d.ts +21 -0
  64. package/dist/expands/Expands.d.ts +11 -12
  65. package/dist/expands/Expands.view.d.ts +1 -1
  66. package/dist/expands/expand/expand.d.ts +10 -11
  67. package/dist/expands/expand/expand.interface.d.ts +9 -9
  68. package/dist/filAriane/FilAriane.d.ts +8 -9
  69. package/dist/filAriane/FilAriane.view.d.ts +1 -1
  70. package/dist/filAriane/filAriane.interface.d.ts +6 -6
  71. package/dist/form/Form.d.ts +35 -36
  72. package/dist/form/Form.view.d.ts +1 -1
  73. package/dist/form/form.enum.d.ts +16 -15
  74. package/dist/form/form.interface.d.ts +53 -54
  75. package/dist/form/input/Input.d.ts +27 -25
  76. package/dist/form/inputNumber/InputNumber.d.ts +21 -22
  77. package/dist/form/inputNumber/InputNumber.view.d.ts +1 -1
  78. package/dist/form/inputPrice/InputPrice.d.ts +14 -15
  79. package/dist/form/inputPrice/InputPrice.view.d.ts +1 -1
  80. package/dist/form/textArea/TextArea.d.ts +14 -15
  81. package/dist/form/textArea/TextArea.view.d.ts +1 -1
  82. package/dist/geocoding/GeocodingService.d.ts +11 -12
  83. package/dist/geocoding/geocoding.interface.d.ts +20 -20
  84. package/dist/grid/Grid.d.ts +9 -10
  85. package/dist/grid/Grid.view.d.ts +1 -1
  86. package/dist/grid/col/Col.d.ts +5 -6
  87. package/dist/grid/col/colStyled/ColStyled.d.ts +10 -11
  88. package/dist/grid/container/Container.d.ts +5 -6
  89. package/dist/grid/grid.interface.d.ts +23 -23
  90. package/dist/grid/row/Row.d.ts +13 -14
  91. package/dist/header/Header.d.ts +1 -2
  92. package/dist/header/Header.view.d.ts +1 -1
  93. package/dist/header/header.interface.d.ts +12 -12
  94. package/dist/home/Home.d.ts +1 -1
  95. package/dist/icon/Icon.d.ts +1 -2
  96. package/dist/icon/Icons.view.d.ts +1 -1
  97. package/dist/icon/icon.interface.d.ts +5 -5
  98. package/dist/icon/iconSize.enum.d.ts +7 -7
  99. package/dist/index.d.ts +56 -54
  100. package/dist/index.html +18 -18
  101. package/dist/index.js +4001 -3510
  102. package/dist/loader/Loader.d.ts +7 -8
  103. package/dist/loader/Loader.view.d.ts +1 -1
  104. package/dist/main.d.ts +0 -1
  105. package/dist/manifest.json +25 -25
  106. package/dist/menus/Menus.d.ts +5 -6
  107. package/dist/menus/Menus.view.d.ts +1 -1
  108. package/dist/menus/menu/Menu.d.ts +7 -8
  109. package/dist/menus/menu/menu.interface.d.ts +10 -10
  110. package/dist/message/Message.d.ts +6 -7
  111. package/dist/message/Message.view.d.ts +1 -1
  112. package/dist/modal/Modal.d.ts +13 -14
  113. package/dist/modal/Modal.view.d.ts +1 -1
  114. package/dist/notFound/NotFound.d.ts +1 -1
  115. package/dist/overlayPanel/OverlayPanel.d.ts +22 -23
  116. package/dist/overlayPanel/OverlayPanel.view.d.ts +1 -1
  117. package/dist/overlayPanel/overlay.context.d.ts +9 -10
  118. package/dist/overlayPanel/overlayPanelStyled/OverlayPanelStyled.d.ts +9 -9
  119. package/dist/pdfViewer/PdfViewer.d.ts +12 -12
  120. package/dist/pdfViewer/PdfViewer.view.d.ts +1 -1
  121. package/dist/quantity/Quantity.d.ts +10 -11
  122. package/dist/robots.txt +3 -3
  123. package/dist/search/Search.d.ts +21 -22
  124. package/dist/search/Search.view.d.ts +1 -1
  125. package/dist/select/Select.d.ts +23 -24
  126. package/dist/select/Select.view.d.ts +1 -1
  127. package/dist/select/selectOption.interface.d.ts +5 -5
  128. package/dist/sidebar/Sidebar.d.ts +12 -13
  129. package/dist/sidebar/Sidebar.view.d.ts +1 -1
  130. package/dist/sidebarData/SidebarData.d.ts +6 -7
  131. package/dist/sidebarData/SidebarData.view.d.ts +1 -1
  132. package/dist/style.css +1 -1
  133. package/dist/tabs/Tabs.d.ts +17 -17
  134. package/dist/tabs/Tabs.view.d.ts +1 -1
  135. package/dist/toaster/Toaster.d.ts +1 -2
  136. package/dist/toaster/Toaster.view.d.ts +1 -1
  137. package/dist/toaster/store/useToasterStore.d.ts +24 -24
  138. package/docs.plugin.ts +223 -0
  139. package/index.html +20 -18
  140. package/package.json +64 -56
  141. package/public/index.html +18 -18
  142. package/public/manifest.json +25 -25
  143. package/public/robots.txt +3 -3
  144. package/src/App.css +178 -11
  145. package/src/App.menu.tsx +277 -257
  146. package/src/App.routes.tsx +21 -16
  147. package/src/App.tsx +31 -30
  148. package/src/_core/hooks/HistoryProvider.tsx +25 -25
  149. package/src/_core/hooks/ImageChecker.tsx +26 -26
  150. package/src/_core/hooks/imageExist.tsx +9 -9
  151. package/src/_core/hooks/isEAN13.tsx +16 -16
  152. package/src/_core/hooks/objectToQueryParams.tsx +32 -32
  153. package/src/_core/hooks/useCurrency.tsx +18 -18
  154. package/src/_core/hooks/useDateutils.ts +64 -64
  155. package/src/_core/hooks/useIsMobile.ts +18 -18
  156. package/src/_core/hooks/useToken.tsx +19 -19
  157. package/src/_core/hooks/useValidate.tsx +18 -18
  158. package/src/_core/hooks/widgetSupport.tsx +39 -39
  159. package/src/_core/type/generiqueType.tsx +4 -0
  160. package/src/action/Action.view.tsx +21 -21
  161. package/src/action/ButtonAction.tsx +32 -32
  162. package/src/action/action.css +20 -20
  163. package/src/addressSearch/AddressSearch.tsx +246 -246
  164. package/src/addressSearch/AddressSearch.view.tsx +52 -52
  165. package/src/addressSearch/addressSearch.css +132 -132
  166. package/src/badge/Badge.tsx +41 -34
  167. package/src/badge/Badge.view.tsx +15 -15
  168. package/src/badge/badge.css +63 -55
  169. package/src/button/Button.tsx +48 -48
  170. package/src/button/Button.view.tsx +85 -85
  171. package/src/button/button.css +53 -53
  172. package/src/button/button.interface.tsx +22 -22
  173. package/src/button/buttonActions/ButtonActions.tsx +104 -104
  174. package/src/button/buttonFile/ButtonFile.tsx +59 -59
  175. package/src/button/buttonFile/ButtonFile.view.tsx +70 -70
  176. package/src/button/buttonFilters/ButtonFilters.tsx +102 -102
  177. package/src/button/buttonFilters/buttonFilters.css +22 -22
  178. package/src/card/Card.tsx +151 -151
  179. package/src/card/Card.view.tsx +73 -73
  180. package/src/card/card.css +144 -144
  181. package/src/card/card.interface.tsx +9 -9
  182. package/src/card/cardAction/CardAction.tsx +135 -135
  183. package/src/card/cardAction/cardAction.css +10 -10
  184. package/src/card/cardAction.interface.tsx +10 -10
  185. package/src/card/hook/useCardInteractions.tsx +30 -30
  186. package/src/carousel/Carousel.css +44 -44
  187. package/src/carousel/Carousel.tsx +115 -115
  188. package/src/carousel/Carousel.view.tsx +13 -13
  189. package/src/damier/Damier.tsx +64 -64
  190. package/src/damier/Damier.view.tsx +31 -31
  191. package/src/damier/damier.css +50 -50
  192. package/src/damier/damierCell/DamierCell.tsx +18 -18
  193. package/src/damier/damierCell/damierCell.interface.tsx +5 -5
  194. package/src/dataTable/DataTable.tsx +840 -746
  195. package/src/dataTable/DataTable.view.tsx +105 -71
  196. package/src/dataTable/dataTable.css +233 -208
  197. package/src/dataTable/dataTable.interface.ts +66 -45
  198. package/src/dataTable/dataTable.utils.ts +45 -0
  199. package/src/dataTable/dataTableActions/DataTableAction.tsx +82 -65
  200. package/src/dataTable/dataTableColumn/DataTableColumn.tsx +48 -27
  201. package/src/dataTable/dataTableColumn/dataTableColumnFilter/DataTableColumnFilter.tsx +36 -0
  202. package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilter.css +0 -0
  203. package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDate/DataTableColumnFilterDate.tsx +39 -0
  204. package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDateRange/dataTableColumnFilterDateRange.tsx +80 -0
  205. package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterEnum/DataTableColumnFilterEnum.tsx +89 -0
  206. package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterString/DataTableColumnFilterString.tsx +37 -0
  207. package/src/dataTable/dataTableColumn/dataTableColumnSort/DataTableColumnSort.tsx +42 -0
  208. package/src/dataTable/dataTableFilters/DataTableFilters.tsx +91 -0
  209. package/src/dataTable/dataTableFilters/dataTableFilters.css +16 -0
  210. package/src/dataTable/dataTableLoading/DataTableLoading.tsx +23 -21
  211. package/src/dataTable/dataTableRow/DataTableRow.tsx +155 -208
  212. package/src/dataTable/useDataTableState.tsx +89 -0
  213. package/src/datePicker/DatePicker.tsx +110 -110
  214. package/src/datePicker/DatePicker.view.tsx +9 -9
  215. package/src/datePicker/datePicker.css +77 -77
  216. package/src/docs/ComponentDocs.tsx +156 -0
  217. package/src/docs/catalog.ts +40 -0
  218. package/src/docs/documentation.types.ts +20 -0
  219. package/src/docs/virtual.d.ts +7 -0
  220. package/src/expands/Expands.tsx +46 -46
  221. package/src/expands/Expands.view.tsx +90 -90
  222. package/src/expands/expand/expand.interface.tsx +8 -8
  223. package/src/expands/expand/expand.tsx +191 -191
  224. package/src/expands/expands.css +101 -101
  225. package/src/filAriane/FilAriane.tsx +57 -57
  226. package/src/filAriane/FilAriane.view.tsx +28 -28
  227. package/src/filAriane/filAriane.css +23 -23
  228. package/src/filAriane/filAriane.interface.tsx +6 -6
  229. package/src/form/Form.tsx +477 -477
  230. package/src/form/Form.view.tsx +67 -67
  231. package/src/form/form.css +135 -135
  232. package/src/form/form.enum.ts +16 -15
  233. package/src/form/form.interface.tsx +67 -67
  234. package/src/form/input/Input.tsx +146 -106
  235. package/src/form/input/input.css +39 -29
  236. package/src/form/inputNumber/InputNumber.tsx +132 -132
  237. package/src/form/inputNumber/InputNumber.view.tsx +15 -15
  238. package/src/form/inputPrice/InputPrice.tsx +42 -42
  239. package/src/form/inputPrice/InputPrice.view.tsx +15 -15
  240. package/src/form/textArea/TextArea.tsx +59 -59
  241. package/src/form/textArea/TextArea.view.tsx +34 -34
  242. package/src/form/textArea/textArea.css +9 -9
  243. package/src/geocoding/GeocodingService.ts +89 -89
  244. package/src/geocoding/geocoding.interface.ts +25 -25
  245. package/src/grid/Grid.tsx +34 -34
  246. package/src/grid/Grid.view.tsx +24 -24
  247. package/src/grid/col/Col.tsx +24 -24
  248. package/src/grid/col/col.css +3 -3
  249. package/src/grid/col/colStyled/ColStyled.tsx +59 -59
  250. package/src/grid/container/Container.tsx +8 -8
  251. package/src/grid/container/container.css +4 -4
  252. package/src/grid/grid.interface.tsx +27 -27
  253. package/src/grid/row/Row.tsx +49 -49
  254. package/src/grid/row/row.css +25 -25
  255. package/src/header/Header.tsx +64 -64
  256. package/src/header/Header.view.tsx +5 -5
  257. package/src/header/header.css +43 -43
  258. package/src/header/header.interface.tsx +11 -11
  259. package/src/home/Home.tsx +40 -3
  260. package/src/icon/Icon.tsx +6 -6
  261. package/src/icon/Icons.view.tsx +29 -29
  262. package/src/icon/icon.css +20 -20
  263. package/src/icon/icon.interface.tsx +7 -6
  264. package/src/icon/iconSize.enum.ts +7 -7
  265. package/src/index.css +547 -547
  266. package/src/index.ts +76 -70
  267. package/src/loader/Loader.tsx +37 -37
  268. package/src/loader/Loader.view.tsx +20 -20
  269. package/src/loader/loader.css +30 -30
  270. package/src/main.tsx +10 -10
  271. package/src/menus/Menus.tsx +43 -43
  272. package/src/menus/Menus.view.tsx +39 -39
  273. package/src/menus/menu/Menu.tsx +18 -18
  274. package/src/menus/menu/menu.interface.tsx +9 -9
  275. package/src/menus/menus.css +47 -47
  276. package/src/message/Message.tsx +30 -30
  277. package/src/message/Message.view.tsx +22 -22
  278. package/src/message/message.css +29 -29
  279. package/src/modal/Modal.tsx +59 -59
  280. package/src/modal/Modal.view.tsx +26 -26
  281. package/src/modal/modal.css +71 -71
  282. package/src/notFound/NotFound.tsx +3 -3
  283. package/src/overlayPanel/OverlayPanel.tsx +260 -255
  284. package/src/overlayPanel/OverlayPanel.view.tsx +25 -25
  285. package/src/overlayPanel/overlay.context.tsx +30 -30
  286. package/src/overlayPanel/overlayPanel.css +43 -43
  287. package/src/overlayPanel/overlayPanelStyled/OverlayPanelStyled.tsx +23 -23
  288. package/src/pdfViewer/PdfViewer.tsx +73 -73
  289. package/src/pdfViewer/PdfViewer.view.tsx +5 -5
  290. package/src/quantity/Quantity.tsx +103 -103
  291. package/src/quantity/quantity.css +26 -26
  292. package/src/search/Search.tsx +161 -161
  293. package/src/search/Search.view.tsx +14 -14
  294. package/src/search/search.css +59 -59
  295. package/src/select/Select.tsx +245 -245
  296. package/src/select/Select.view.tsx +71 -71
  297. package/src/select/select.css +150 -150
  298. package/src/select/selectOption.interface.ts +5 -5
  299. package/src/sidebar/Sidebar.tsx +213 -213
  300. package/src/sidebar/Sidebar.view.tsx +17 -17
  301. package/src/sidebar/sidebar.css +103 -103
  302. package/src/sidebarData/SidebarData.tsx +19 -19
  303. package/src/sidebarData/SidebarData.view.tsx +19 -19
  304. package/src/sidebarData/sidebarData.css +27 -27
  305. package/src/tabs/Tabs.tsx +101 -90
  306. package/src/tabs/Tabs.view.tsx +20 -20
  307. package/src/tabs/tabs.css +29 -29
  308. package/src/toaster/Toaster.tsx +61 -61
  309. package/src/toaster/Toaster.view.tsx +25 -25
  310. package/src/toaster/store/useToasterStore.tsx +54 -54
  311. package/src/toaster/toaster.css +105 -105
  312. package/tests/dataTable.test.mjs +93 -0
  313. package/tests/documentation.test.mjs +75 -0
  314. package/tsconfig.docs.json +10 -0
  315. package/tsconfig.json +28 -28
  316. package/vite.config.ts +26 -20
  317. package/vite.config.ts.timestamp-1733262892554-a13dfef6e8a29.mjs +24 -24
  318. package/vite.config.ts.timestamp-1757847121745-e5a5bf54b81b.mjs +28 -28
  319. package/vite.config.ts.timestamp-1759742478362-4ac5c5a7db34b.mjs +28 -28
@@ -0,0 +1,42 @@
1
+ import { Icon } from "../../../icon/Icon";
2
+ import { DataTableSortDirection } from "../../DataTable";
3
+ import { DataTableColumnsInterface } from "../../dataTable.interface";
4
+
5
+ type DataTableColumnSortProps<T> = {
6
+ className?: string;
7
+ column: DataTableColumnsInterface<T>;
8
+ sortDirection?: DataTableSortDirection | null;
9
+ onToggleSort?: (column: DataTableColumnsInterface<T>) => void;
10
+ };
11
+
12
+ export const DataTableColumnSort = <T,>({
13
+ className,
14
+ column,
15
+ sortDirection,
16
+ onToggleSort,
17
+ }: DataTableColumnSortProps<T>) => {
18
+ const iconClass =
19
+ sortDirection === "asc"
20
+ ? "bi-sort-up"
21
+ : sortDirection === "desc"
22
+ ? "bi-sort-down"
23
+ : "bi-arrow-down-up";
24
+
25
+ return (
26
+ <div
27
+ className={`data-table-column-sort ${sortDirection ? "active" : ""} ${className ?? ""}`}
28
+ >
29
+ <span>
30
+ <Icon
31
+ onClick={(e) => {
32
+ e.stopPropagation();
33
+ onToggleSort?.(column);
34
+ }}
35
+ classIcon={`${iconClass} cursor-pointer ${
36
+ sortDirection ? "data-table-column-sort-active" : ""
37
+ }`}
38
+ />
39
+ </span>
40
+ </div>
41
+ );
42
+ };
@@ -0,0 +1,91 @@
1
+ import { Badge } from "../../badge/Badge";
2
+ import { Icon } from "../../icon/Icon";
3
+ import {
4
+ DataTableDateRangeFilterValue,
5
+ DataTableFilterState,
6
+ } from "../DataTable";
7
+ import "./dataTableFilters.css";
8
+ export type DataTableFiltersProps = {
9
+ currentFilters: DataTableFilterState;
10
+ setCurrentFilters: React.Dispatch<React.SetStateAction<DataTableFilterState>>;
11
+ };
12
+ export const DataTableFilters = ({
13
+ currentFilters,
14
+ setCurrentFilters,
15
+ }: DataTableFiltersProps) => {
16
+ const isDateRangeFilterValue = (
17
+ value: DataTableFilterState[string],
18
+ ): value is DataTableDateRangeFilterValue => {
19
+ return (
20
+ typeof value === "object" &&
21
+ value !== null &&
22
+ "startDate" in value &&
23
+ "endDate" in value
24
+ );
25
+ };
26
+
27
+ const getDisplayValue = (value: DataTableFilterState[string]) => {
28
+ if (isDateRangeFilterValue(value)) {
29
+ if (value.startDate && value.endDate) {
30
+ return `${value.startDate} - ${value.endDate}`;
31
+ }
32
+
33
+ if (value.startDate) {
34
+ return `a partir de ${value.startDate}`;
35
+ }
36
+
37
+ if (value.endDate) {
38
+ return `jusqu'au ${value.endDate}`;
39
+ }
40
+
41
+ return "";
42
+ }
43
+
44
+ return String(value ?? "");
45
+ };
46
+
47
+ const generateColor = (str: string): string => {
48
+ let hash = 0;
49
+ for (let i = 0; i < str.length; i++) {
50
+ hash = str.charCodeAt(i) + ((hash << 5) - hash);
51
+ }
52
+
53
+ const hue = hash % 360;
54
+ return `hsl(${hue}, 80%, 30%)`;
55
+ };
56
+
57
+ const removeFilters = (key: string) => {
58
+ setCurrentFilters((prev: any) => {
59
+ const { [key]: _removed, ...rest } = prev;
60
+ return rest;
61
+ });
62
+ };
63
+ if (!currentFilters || Object.keys(currentFilters).length === 0) {
64
+ return null;
65
+ }
66
+
67
+ return (
68
+ <div className="badge-filters">
69
+ {Object.keys(currentFilters).map((key) => {
70
+ const value = getDisplayValue(currentFilters[key]);
71
+ const displayValue =
72
+ value.length > 20 ? value.substring(0, 20) + "..." : value;
73
+
74
+ return (
75
+ <Badge
76
+ onRemove={() => removeFilters(key)}
77
+ className="mr-2"
78
+ title={`${key} : ${displayValue}`}
79
+ color={generateColor(key)}
80
+ key={key}
81
+ />
82
+ );
83
+ })}
84
+
85
+ <Icon
86
+ classIcon="bi-x badge-filters-clear"
87
+ onClick={() => setCurrentFilters({})}
88
+ />
89
+ </div>
90
+ );
91
+ };
@@ -0,0 +1,16 @@
1
+ .badge-filters {
2
+ border-radius: 4px;
3
+ padding: 0.25rem;
4
+ border: 1px solid #dedede;
5
+ width: fit-content;
6
+ display: flex;
7
+ align-items: center;
8
+ position: sticky;
9
+ left: 0;
10
+ .badge-filters-clear {
11
+ padding: 0.05rem;
12
+ border: 1px solid #dedede;
13
+ border-radius: 4px;
14
+ cursor: pointer;
15
+ }
16
+ }
@@ -1,21 +1,23 @@
1
- type DataTableLoadingProps = {
2
- columns: any[];
3
- actions: any[];
4
- emptyMessage?: string;
5
- };
6
- export const DataTableLoading = ({
7
- columns,
8
- actions,
9
- emptyMessage,
10
- }: DataTableLoadingProps) => {
11
- return (
12
- <tr>
13
- <td
14
- align="center"
15
- colSpan={columns.length + (actions.length > 0 ? 1 : 0)}
16
- >
17
- <div className="mt-3">{emptyMessage || "Aucune donnée disponible"}</div>
18
- </td>
19
- </tr>
20
- );
21
- };
1
+ type DataTableLoadingProps = {
2
+ columns: any[];
3
+ actions: any[];
4
+ emptyMessage?: string;
5
+ hasSelection?: boolean;
6
+ };
7
+ export const DataTableLoading = ({
8
+ columns,
9
+ actions,
10
+ emptyMessage,
11
+ hasSelection = false,
12
+ }: DataTableLoadingProps) => {
13
+ return (
14
+ <tr>
15
+ <td
16
+ align="center"
17
+ colSpan={columns.length + (actions.length > 0 ? 1 : 0) + (hasSelection ? 1 : 0)}
18
+ >
19
+ <div className="mt-3">{emptyMessage || "Aucune donnée disponible"}</div>
20
+ </td>
21
+ </tr>
22
+ );
23
+ };
@@ -1,208 +1,155 @@
1
- import { Icon } from "../..";
2
- import { Select } from "../../select/Select";
3
- import { dataTableColumnsInterface } from "../dataTable.interface";
4
-
5
- type DataTableRowProps = {
6
- column: dataTableColumnsInterface<any>;
7
- idx: number;
8
- rowIndex: number;
9
- row: any;
10
- container?: "cell" | "card";
11
- onEnterNextColumn?: (columnIndex: number, rowIndex: number) => void;
12
- };
13
- export const DataTableRow = ({
14
- column,
15
- idx,
16
- rowIndex,
17
- row,
18
- container = "cell",
19
- onEnterNextColumn,
20
- }: DataTableRowProps) => {
21
- const value = (row as any)[column.id]; // On utilise [column.id] pour accéder aux bonnes propriétés
22
- const style = column.onRowStyle ? column.onRowStyle(row) : {};
23
- const isDisabled = column.onDisable?.(row) ?? false;
24
-
25
- const hasStepButtons = Boolean(
26
- typeof column.showStepButtons === "function"
27
- ? column.showStepButtons(row)
28
- : (column.showStepButtons ??
29
- (typeof column.stepControls === "function"
30
- ? column.stepControls(row)
31
- : (column.stepControls ??
32
- (typeof column.withStepControls === "function"
33
- ? column.withStepControls(row)
34
- : column.withStepControls)))),
35
- );
36
-
37
- const handleStep = (direction: "plus" | "minus", e: React.MouseEvent) => {
38
- e.stopPropagation();
39
- if (isDisabled) return;
40
- const currentNum = Number(value) || 0;
41
- const step = column.step ?? 1;
42
- let newNum = direction === "plus" ? currentNum + step : currentNum - step;
43
- if (column.min !== undefined && newNum < column.min) {
44
- newNum = column.min;
45
- }
46
- if (column.max !== undefined && newNum > column.max) {
47
- newNum = column.max;
48
- }
49
- newNum = Math.round(newNum * 1000) / 1000;
50
- if (column.onEdit) {
51
- column.onEdit(newNum, row);
52
- }
53
- };
54
-
55
- const Container = container === "card" ? "div" : "td";
56
-
57
- return (
58
- <Container
59
- className={`${isDisabled ? "disabled" : ""}`}
60
- data-column-index={idx}
61
- data-row-index={rowIndex}
62
- style={{
63
- minWidth: column.minWidth,
64
- textAlign: column.align || "left",
65
- maxWidth: column.maxWidth,
66
- width: column.width,
67
- ...style,
68
- }}
69
- key={`row-${column.id}-${idx}`}
70
- >
71
- {column.type === "image" ? (
72
- value ? (
73
- <img
74
- src={column.imageSrc ? column.imageSrc(row) : ""}
75
- alt={column.imageAlt ? column.imageAlt(row) : ""}
76
- style={column.imageStyle}
77
- />
78
- ) : (
79
- <Icon classIcon="bi-image" />
80
- )
81
- ) : column.editable ? (
82
- column.type === "select" ? (
83
- <div onClick={(e) => e.stopPropagation()}>
84
- <Select
85
- style={{
86
- minWidth: column.minWidth,
87
- maxWidth: column.maxWidth,
88
- width: column.width,
89
- }}
90
- options={column.options ?? []}
91
- value={value}
92
- onChange={(e) => {
93
- if (column.onEdit) {
94
- column.onEdit(e, row);
95
- }
96
- }}
97
- />
98
- </div>
99
- ) : (
100
- hasStepButtons ? (
101
- <div
102
- className="data-table-input-number-wrapper"
103
- style={{
104
- display: "inline-flex",
105
- alignItems: "center",
106
- gap: "4px",
107
- justifyContent:
108
- column.align === "right"
109
- ? "flex-end"
110
- : column.align === "center"
111
- ? "center"
112
- : "flex-start",
113
- }}
114
- onClick={(e) => e.stopPropagation()}
115
- >
116
- <button
117
- type="button"
118
- className="data-table-step-btn data-table-step-btn--minus"
119
- disabled={
120
- isDisabled ||
121
- (column.min !== undefined && Number(value) <= column.min)
122
- }
123
- onClick={(e) => handleStep("minus", e)}
124
- >
125
- <Icon classIcon="bi-dash-lg" />
126
- </button>
127
- <input
128
- type={column.type}
129
- value={value}
130
- step={column.step ?? "0.01"}
131
- min={column.min}
132
- max={column.max}
133
- disabled={isDisabled}
134
- style={{
135
- textAlign: column.align || "center",
136
- minWidth: column.minWidth,
137
- maxWidth: column.maxWidth,
138
- width: column.width,
139
- }}
140
- onClick={(e) => e.stopPropagation()}
141
- onKeyDown={(e) => {
142
- if (e.key === "Enter") {
143
- if (column.onEnter) {
144
- column.onEnter(e.currentTarget.value, row);
145
- }
146
- if (column.enterToNextColumn) {
147
- e.preventDefault();
148
- onEnterNextColumn?.(idx, rowIndex);
149
- }
150
- }
151
- }}
152
- onChange={(e) => {
153
- if (column.onEdit) {
154
- column.onEdit(e.target.value, row);
155
- }
156
- }}
157
- />
158
- <button
159
- type="button"
160
- className="data-table-step-btn data-table-step-btn--plus"
161
- disabled={
162
- isDisabled ||
163
- (column.max !== undefined && Number(value) >= column.max)
164
- }
165
- onClick={(e) => handleStep("plus", e)}
166
- >
167
- <Icon classIcon="bi-plus-lg" />
168
- </button>
169
- </div>
170
- ) : (
171
- <input
172
- type={column.type}
173
- value={value}
174
- step="0.01"
175
- style={{
176
- textAlign: column.align || "left",
177
- minWidth: column.minWidth,
178
- maxWidth: column.maxWidth,
179
- width: column.width,
180
- }}
181
- onClick={(e) => e.stopPropagation()}
182
- onKeyDown={(e) => {
183
- if (e.key === "Enter") {
184
- if (column.onEnter) {
185
- column.onEnter(e.currentTarget.value, row);
186
- }
187
- if (column.enterToNextColumn) {
188
- e.preventDefault();
189
- onEnterNextColumn?.(idx, rowIndex);
190
- }
191
- }
192
- }}
193
- onChange={(e) => {
194
- if (column.onEdit) {
195
- column.onEdit(e.target.value, row);
196
- }
197
- }}
198
- />
199
- )
200
- )
201
- ) : column.format ? (
202
- column.format(value)
203
- ) : (
204
- value
205
- )}
206
- </Container>
207
- );
208
- };
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { Icon } from "../../icon/Icon";
3
+ import { OverlayPanel } from "../../overlayPanel/OverlayPanel";
4
+ import { Select } from "../../select/Select";
5
+ import { dataTableColumnsInterface } from "../dataTable.interface";
6
+ import { getColumnValue } from "../dataTable.utils";
7
+
8
+ type DataTableRowProps<T> = {
9
+ column: dataTableColumnsInterface<T>;
10
+ idx: number;
11
+ rowIndex: number;
12
+ row: T;
13
+ container?: "cell" | "card";
14
+ stickyLeft?: number;
15
+ onEnterNextColumn?: (columnIndex: number, rowIndex: number) => void;
16
+ onEditColumnByOverlay?: (row: T) => void;
17
+ };
18
+
19
+ export const DataTableRow = <T,>({
20
+ column, idx, rowIndex, row, container = "cell", stickyLeft,
21
+ onEnterNextColumn, onEditColumnByOverlay,
22
+ }: DataTableRowProps<T>) => {
23
+ const value = getColumnValue(row, column);
24
+ const stringValue = value == null ? "" : String(value);
25
+ const [draft, setDraft] = useState(stringValue);
26
+ const [overlayOpen, setOverlayOpen] = useState(false);
27
+ const [overlayValue, setOverlayValue] = useState(stringValue);
28
+ const cellRef = useRef<HTMLTableCellElement & HTMLDivElement>(null);
29
+ const inputRef = useRef<HTMLInputElement>(null);
30
+ const skipBlurCommit = useRef(false);
31
+ const isDisabled = column.onDisable?.(row) ?? false;
32
+ const editable = column.onEditable?.(value, row) ?? column.editable ?? false;
33
+ const enterCommit = column.onEditTrigger === "enter";
34
+ const align = column.alignText ?? column.align ?? "left";
35
+ useEffect(() => { setDraft(stringValue); }, [stringValue]);
36
+ useEffect(() => { if (editable && column.openClickCell && !isDisabled) inputRef.current?.focus(); }, [editable, column.openClickCell, isDisabled]);
37
+
38
+ const hasStepButtons = [column.showStepButtons, column.stepControls, column.withStepControls]
39
+ .map((setting) => typeof setting === "function" ? setting(row) : setting)
40
+ .find((setting) => setting !== undefined) ?? false;
41
+
42
+ function commit(next: string | number | boolean) {
43
+ if (isDisabled) return;
44
+ column.onEdit?.(next, row);
45
+ }
46
+
47
+ function handleStep(direction: number) {
48
+ const current = Number(enterCommit ? draft : value) || 0;
49
+ const next = Math.round(Math.min(column.max ?? Infinity,
50
+ Math.max(column.min ?? -Infinity, current + direction * (column.step ?? 1))) * 1000) / 1000;
51
+ setDraft(String(next));
52
+ column.onChange?.(next, row);
53
+ commit(next);
54
+ }
55
+
56
+ function handleInput(next: string | boolean) {
57
+ if (isDisabled) return;
58
+ skipBlurCommit.current = false;
59
+ setDraft(String(next));
60
+ column.onChange?.(next, row);
61
+ if (!enterCommit) commit(next);
62
+ }
63
+
64
+ const editor = column.type === "select" ? (
65
+ <Select options={column.options ?? []} value={enterCommit ? draft : stringValue}
66
+ disabled={isDisabled} usePortal onChange={(next) => {
67
+ column.onChange?.(next, row);
68
+ commit(next);
69
+ }}
70
+ style={{ minWidth: column.minWidth, maxWidth: column.maxWidth, width: column.width }} />
71
+ ) : (
72
+ <input ref={inputRef} type={column.type === "image" ? "text" : column.type}
73
+ value={enterCommit ? draft : stringValue}
74
+ checked={column.type === "checkbox" || column.type === "radio" ? Boolean(value) : undefined}
75
+ autoComplete={column.autoComplete} disabled={isDisabled}
76
+ step={column.step ?? "0.01"} min={column.min} max={column.max}
77
+ style={{ textAlign: align, minWidth: column.minWidth, maxWidth: column.maxWidth, width: column.width }}
78
+ onClick={(event) => event.stopPropagation()}
79
+ onChange={(event) => handleInput(column.type === "checkbox" ? event.target.checked : event.target.value)}
80
+ onBlur={() => {
81
+ if (!enterCommit) return;
82
+ if (skipBlurCommit.current) { skipBlurCommit.current = false; return; }
83
+ if (draft !== stringValue) commit(draft);
84
+ }}
85
+ onKeyDown={(event) => {
86
+ if (event.key === "Escape") {
87
+ setDraft(stringValue);
88
+ skipBlurCommit.current = true;
89
+ }
90
+ if (event.key !== "Enter") return;
91
+ if (enterCommit) {
92
+ event.preventDefault();
93
+ skipBlurCommit.current = true;
94
+ commit(event.currentTarget.value);
95
+ }
96
+ column.onEnter?.(event.currentTarget.value, row);
97
+ if (column.enterToNextColumn) {
98
+ event.preventDefault();
99
+ onEnterNextColumn?.(idx, rowIndex);
100
+ }
101
+ }} />
102
+ );
103
+ const Container = container === "card" ? "div" : "td";
104
+ return (
105
+ <Container ref={cellRef} className={isDisabled ? "disabled" : ""}
106
+ data-column-index={idx} data-row-index={rowIndex}
107
+ style={{ minWidth: column.minWidth, maxWidth: column.maxWidth, width: column.width,
108
+ textAlign: align, ...column.onRowStyle?.(row),
109
+ ...(!isDisabled && column.openClickCell ? { cursor: "pointer" } : {}),
110
+ ...(stickyLeft !== undefined ? { position: "sticky", left: stickyLeft, zIndex: 2, background: "inherit" } : {}) }}
111
+ onClick={(event) => {
112
+ if (isDisabled || !column.openClickCell) return;
113
+ event.stopPropagation();
114
+ if (event.currentTarget instanceof HTMLTableCellElement) column.handleClickCell?.(event as React.MouseEvent<HTMLTableCellElement>, row);
115
+ if (column.displayOverlay || column.renderClickCellComponent) {
116
+ setOverlayValue(stringValue);
117
+ setOverlayOpen(true);
118
+ }
119
+ }}>
120
+ {column.renderComponent ? column.renderComponent(value, row) :
121
+ column.type === "image" ? value ? (
122
+ <img src={column.imageSrc?.(row) ?? ""} alt={column.imageAlt?.(row) ?? ""} style={column.imageStyle} />
123
+ ) : <Icon classIcon="bi-image" /> :
124
+ editable ? hasStepButtons ? (
125
+ <div className="data-table-input-number-wrapper" onClick={(event) => event.stopPropagation()}>
126
+ <button type="button" className="data-table-step-btn data-table-step-btn--minus"
127
+ disabled={isDisabled || (column.min !== undefined && Number(value) <= column.min)}
128
+ onClick={() => handleStep(-1)}><Icon classIcon="bi-dash-lg" /></button>
129
+ {editor}
130
+ <button type="button" className="data-table-step-btn data-table-step-btn--plus"
131
+ disabled={isDisabled || (column.max !== undefined && Number(value) >= column.max)}
132
+ onClick={() => handleStep(1)}><Icon classIcon="bi-plus-lg" /></button>
133
+ </div>
134
+ ) : editor : column.format ? column.format(value) : stringValue}
135
+ {overlayOpen && !isDisabled && cellRef.current && (
136
+ <OverlayPanel show referenceElement={cellRef.current} position="bottomLeft" usePortal
137
+ closeOverlay={() => setOverlayOpen(false)}>
138
+ {column.renderClickCellComponent ? column.renderClickCellComponent(value, row) : (
139
+ <form onSubmit={(event) => {
140
+ event.preventDefault();
141
+ if (column.onEditByOverlay) column.onEditByOverlay(overlayValue, row);
142
+ else if (!onEditColumnByOverlay) commit(overlayValue);
143
+ onEditColumnByOverlay?.({ ...row, [column.id]: overlayValue });
144
+ setOverlayOpen(false);
145
+ }}>
146
+ {column.type === "select" ? <Select usePortal options={column.options ?? []} value={overlayValue} onChange={setOverlayValue} /> :
147
+ <input autoFocus type={column.type === "image" ? "text" : column.type} value={overlayValue} onChange={(event) => setOverlayValue(event.target.value)} />}
148
+ <button type="submit">Valider</button>
149
+ </form>
150
+ )}
151
+ </OverlayPanel>
152
+ )}
153
+ </Container>
154
+ );
155
+ };
@@ -0,0 +1,89 @@
1
+ import { useDeferredValue, useEffect, useMemo, useRef, useState } from "react";
2
+ import { TypeInputEnum } from "../form/form.enum";
3
+ import { Input } from "../form/input/Input";
4
+ import { Select } from "../select/Select";
5
+ import { dataTableColumnsInterface } from "./dataTable.interface";
6
+ import { DataTableColumnFilterDateRange } from "./dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDateRange/dataTableColumnFilterDateRange";
7
+ import {
8
+ DataTableFilterState, DataTableSortState, FilterValue,
9
+ flattenColumns, getFilterKey, sortRows,
10
+ } from "./dataTable.utils";
11
+
12
+ export function useDataTableState<T>(
13
+ id: string,
14
+ columns: dataTableColumnsInterface<T>[],
15
+ data: T[],
16
+ onFiltersChange?: (next: DataTableFilterState) => void,
17
+ onSortChange?: (next: DataTableSortState | null) => void,
18
+ ) {
19
+ const [filters, setFilters] = useState<DataTableFilterState>({});
20
+ const [visibleFilters, setVisibleFilters] = useState<Set<string>>(new Set());
21
+ const [sort, setSort] = useState<DataTableSortState | null>(null);
22
+ const [focusKey, setFocusKey] = useState<string | null>(null);
23
+ const deferredFilters = useDeferredValue(filters);
24
+ const callbacks = useRef({ onFiltersChange, onSortChange });
25
+ useEffect(() => { callbacks.current = { onFiltersChange, onSortChange }; }, [onFiltersChange, onSortChange]);
26
+ useEffect(() => { callbacks.current.onFiltersChange?.(deferredFilters); }, [deferredFilters]);
27
+ useEffect(() => { callbacks.current.onSortChange?.(sort); }, [sort]);
28
+ const flatColumns = useMemo(() => flattenColumns(columns), [columns]);
29
+ const sortedData = useMemo(() => sortRows(data, flatColumns, sort), [data, flatColumns, sort]);
30
+
31
+ function toggleFilter(column: dataTableColumnsInterface<T>) {
32
+ const key = getFilterKey(column);
33
+ setFocusKey(visibleFilters.has(key) ? null : key);
34
+ setVisibleFilters((previous) => {
35
+ const next = new Set(previous);
36
+ if (next.has(key)) next.delete(key); else next.add(key);
37
+ return next;
38
+ });
39
+ }
40
+
41
+ function toggleSort(column: dataTableColumnsInterface<T>) {
42
+ const key = getFilterKey(column);
43
+ setSort((previous) => previous?.key !== key ? { key, direction: "asc" } :
44
+ previous.direction === "asc" ? { key, direction: "desc" } : null);
45
+ }
46
+
47
+ function updateFilter(key: string, value: FilterValue) {
48
+ setFilters((previous) => {
49
+ const empty = value === "" || (Array.isArray(value) && value.length === 0) ||
50
+ (typeof value === "object" && value !== null && "startDate" in value && !value.startDate && !value.endDate);
51
+ if (empty) {
52
+ if (!(key in previous)) return previous;
53
+ const next = { ...previous };
54
+ delete next[key];
55
+ return next;
56
+ }
57
+ if (JSON.stringify(previous[key]) === JSON.stringify(value)) return previous;
58
+ return { ...previous, [key]: value };
59
+ });
60
+ }
61
+
62
+ function renderFilter(column: dataTableColumnsInterface<T>) {
63
+ const key = getFilterKey(column);
64
+ if (!column.filterable || !visibleFilters.has(key)) return null;
65
+ const value = filters[key];
66
+ const range = typeof value === "object" && value !== null && "startDate" in value ? value : { startDate: "", endDate: "" };
67
+ const inputId = `${id}-filter-${column.id}`;
68
+ if (column.filterType === TypeInputEnum.DATERANGE) {
69
+ return <DataTableColumnFilterDateRange id={inputId} name={inputId}
70
+ currentStartValue={range.startDate} currentEndValue={range.endDate}
71
+ onChange={(startDate, endDate) => updateFilter(key, { startDate, endDate })} />;
72
+ }
73
+ if (column.filterType === TypeInputEnum.CHECKBOX || column.filterType === TypeInputEnum.RADIO) {
74
+ return <Select id={inputId} options={column.filterDataEnum ?? []} multiple
75
+ usePortal showOptions={focusKey === key}
76
+ value={String(value ?? "").split(",").filter(Boolean)}
77
+ onChangeMultiple={(values) => updateFilter(key, values.join(","))}
78
+ placeholder={`Filtrer ${column.label}`} />;
79
+ }
80
+ return <Input id={inputId} name={inputId}
81
+ type={column.filterType === TypeInputEnum.DATE ? TypeInputEnum.DATE : TypeInputEnum.TEXT}
82
+ value={String(value ?? "")} autoFocus={focusKey === key}
83
+ disabledDebounce showClearButton placeholder={`Filtrer ${column.label}`}
84
+ onClick={(event) => event.stopPropagation()}
85
+ onChange={(event) => updateFilter(key, event.target.value)} />;
86
+ }
87
+
88
+ return { filters, setFilters, visibleFilters, sort, flatColumns, sortedData, toggleFilter, toggleSort, renderFilter };
89
+ }