kelt-ui-kit-react 2.0.2 → 2.0.3

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 (127) hide show
  1. package/README.md +0 -26
  2. package/dist/_core/type/generiqueType.d.ts +4 -0
  3. package/dist/badge/Badge.d.ts +3 -1
  4. package/dist/button/Button.d.ts +1 -1
  5. package/dist/button/button.interface.d.ts +1 -2
  6. package/dist/dataTable/DataTable.d.ts +17 -14
  7. package/dist/dataTable/dataTable.interface.d.ts +24 -19
  8. package/dist/dataTable/dataTableActions/DataTableAction.d.ts +3 -5
  9. package/dist/dataTable/dataTableColumn/DataTableColumn.d.ts +13 -7
  10. package/dist/dataTable/dataTableColumn/dataTableColumnFilter/DataTableColumnFilter.d.ts +10 -0
  11. package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDate/DataTableColumnFilterDate.d.ts +9 -0
  12. package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDateRange/dataTableColumnFilterDateRange.d.ts +9 -0
  13. package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterEnum/DataTableColumnFilterEnum.d.ts +13 -0
  14. package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterString/DataTableColumnFilterString.d.ts +9 -0
  15. package/dist/dataTable/dataTableColumn/dataTableColumnSort/DataTableColumnSort.d.ts +11 -0
  16. package/dist/dataTable/dataTableFilters/DataTableFilters.d.ts +7 -0
  17. package/dist/dataTable/dataTableLoading/DataTableLoading.d.ts +1 -3
  18. package/dist/dataTable/dataTableRow/DataTableRow.d.ts +5 -6
  19. package/dist/dataTable/dataTableRow/dataTableRowOverlay/DataTableRowOverlay.d.ts +12 -0
  20. package/dist/dataTable/dataTableRow/dataTableRowValue/DataTableRowValue.d.ts +11 -0
  21. package/dist/expands/expand/expand.d.ts +1 -1
  22. package/dist/form/Form.d.ts +2 -4
  23. package/dist/form/form.enum.d.ts +2 -3
  24. package/dist/form/form.interface.d.ts +2 -19
  25. package/dist/form/input/Input.d.ts +3 -0
  26. package/dist/form/inputNumber/InputNumber.d.ts +0 -2
  27. package/dist/grid/col/Col.d.ts +6 -3
  28. package/dist/grid/col/colStyled/ColStyled.d.ts +5 -7
  29. package/dist/grid/grid.interface.d.ts +5 -9
  30. package/dist/header/Header.d.ts +1 -1
  31. package/dist/header/header.interface.d.ts +1 -2
  32. package/dist/icon/Icon.d.ts +1 -1
  33. package/dist/icon/icon.interface.d.ts +1 -0
  34. package/dist/index.d.ts +1 -5
  35. package/dist/index.js +3606 -3543
  36. package/dist/menus/menu/Menu.d.ts +0 -1
  37. package/dist/overlayPanel/OverlayPanel.d.ts +4 -2
  38. package/dist/overlayPanel/overlayPanelStyled/OverlayPanelStyled.d.ts +2 -0
  39. package/dist/select/Select.d.ts +6 -2
  40. package/dist/select/selectOption.interface.d.ts +1 -0
  41. package/dist/style.css +1 -1
  42. package/dist/tabs/Tabs.d.ts +2 -1
  43. package/dist/toaster/store/useToasterStore.d.ts +0 -1
  44. package/index.html +2 -1
  45. package/package/package.json +56 -0
  46. package/package/src/sidebar/Sidebar.tsx +208 -0
  47. package/package/src/sidebar/sidebar.css +104 -0
  48. package/package.json +1 -1
  49. package/src/App.menu.tsx +0 -8
  50. package/src/_core/type/generiqueType.tsx +4 -0
  51. package/src/badge/Badge.tsx +9 -1
  52. package/src/badge/badge.css +4 -0
  53. package/src/button/Button.tsx +1 -3
  54. package/src/button/button.css +2 -2
  55. package/src/button/button.interface.tsx +1 -2
  56. package/src/card/card.css +25 -5
  57. package/src/card/cardAction/CardAction.tsx +4 -4
  58. package/src/damier/Damier.tsx +7 -16
  59. package/src/damier/damier.css +4 -11
  60. package/src/dataTable/DataTable.tsx +685 -542
  61. package/src/dataTable/DataTable.view.tsx +48 -24
  62. package/src/dataTable/dataTable.css +134 -159
  63. package/src/dataTable/dataTable.interface.ts +25 -19
  64. package/src/dataTable/dataTableActions/DataTableAction.tsx +14 -25
  65. package/src/dataTable/dataTableColumn/DataTableColumn.tsx +64 -14
  66. package/src/dataTable/dataTableColumn/dataTableColumnFilter/DataTableColumnFilter.tsx +36 -0
  67. package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilter.css +0 -0
  68. package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDate/DataTableColumnFilterDate.tsx +39 -0
  69. package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDateRange/dataTableColumnFilterDateRange.tsx +80 -0
  70. package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterEnum/DataTableColumnFilterEnum.tsx +89 -0
  71. package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterString/DataTableColumnFilterString.tsx +37 -0
  72. package/src/dataTable/dataTableColumn/dataTableColumnSort/DataTableColumnSort.tsx +42 -0
  73. package/src/dataTable/dataTableFilters/DataTableFilters.tsx +91 -0
  74. package/src/dataTable/dataTableFilters/dataTableFilters.css +16 -0
  75. package/src/dataTable/dataTableLoading/DataTableLoading.tsx +4 -15
  76. package/src/dataTable/dataTableRow/DataTableRow.tsx +64 -180
  77. package/src/dataTable/dataTableRow/dataTableRowOverlay/DataTableRowOverlay.tsx +80 -0
  78. package/src/dataTable/dataTableRow/dataTableRowValue/DataTableRowValue.tsx +123 -0
  79. package/src/expands/Expands.tsx +2 -16
  80. package/src/expands/expand/expand.tsx +5 -122
  81. package/src/expands/expands.css +3 -8
  82. package/src/form/Form.tsx +93 -258
  83. package/src/form/Form.view.tsx +1 -9
  84. package/src/form/form.css +1 -51
  85. package/src/form/form.enum.ts +1 -2
  86. package/src/form/form.interface.tsx +2 -28
  87. package/src/form/input/Input.tsx +61 -7
  88. package/src/form/input/input.css +23 -1
  89. package/src/form/inputNumber/InputNumber.tsx +6 -11
  90. package/src/form/inputPrice/InputPrice.tsx +2 -4
  91. package/src/grid/col/Col.tsx +7 -5
  92. package/src/grid/col/colStyled/ColStyled.tsx +7 -21
  93. package/src/grid/grid.interface.tsx +5 -11
  94. package/src/grid/row/row.css +2 -2
  95. package/src/header/Header.tsx +2 -4
  96. package/src/header/header.css +0 -17
  97. package/src/header/header.interface.tsx +1 -2
  98. package/src/icon/Icon.tsx +6 -2
  99. package/src/icon/icon.interface.tsx +1 -0
  100. package/src/index.css +12 -58
  101. package/src/index.ts +2 -12
  102. package/src/menus/Menus.tsx +0 -1
  103. package/src/menus/menu/Menu.tsx +1 -2
  104. package/src/overlayPanel/OverlayPanel.tsx +71 -18
  105. package/src/overlayPanel/overlay.context.tsx +6 -4
  106. package/src/overlayPanel/overlayPanel.css +10 -1
  107. package/src/overlayPanel/overlayPanelStyled/OverlayPanelStyled.tsx +7 -2
  108. package/src/select/Select.tsx +178 -41
  109. package/src/select/select.css +94 -13
  110. package/src/select/selectOption.interface.ts +1 -0
  111. package/src/sidebar/Sidebar.tsx +5 -107
  112. package/src/sidebar/sidebar.css +1 -18
  113. package/src/tabs/Tabs.tsx +20 -1
  114. package/src/tabs/tabs.css +3 -9
  115. package/src/toaster/Toaster.tsx +2 -7
  116. package/src/toaster/Toaster.view.tsx +0 -1
  117. package/src/toaster/store/useToasterStore.tsx +0 -2
  118. package/src/toaster/toaster.css +2 -7
  119. package/dist/addressSearch/AddressSearch.d.ts +0 -20
  120. package/dist/addressSearch/AddressSearch.view.d.ts +0 -1
  121. package/dist/geocoding/GeocodingService.d.ts +0 -13
  122. package/dist/geocoding/geocoding.interface.d.ts +0 -20
  123. package/src/addressSearch/AddressSearch.tsx +0 -246
  124. package/src/addressSearch/AddressSearch.view.tsx +0 -52
  125. package/src/addressSearch/addressSearch.css +0 -133
  126. package/src/geocoding/GeocodingService.ts +0 -89
  127. package/src/geocoding/geocoding.interface.ts +0 -25
@@ -1,208 +1,92 @@
1
- import { Icon } from "../..";
2
- import { Select } from "../../select/Select";
3
- import { dataTableColumnsInterface } from "../dataTable.interface";
1
+ import { useRef, useState } from "react";
2
+ import { DataTableColumnsInterface } from "../dataTable.interface";
3
+ import { DataTableRowOverlay } from "./dataTableRowOverlay/DataTableRowOverlay";
4
+ import { DataTableRowValue } from "./dataTableRowValue/DataTableRowValue";
4
5
 
5
6
  type DataTableRowProps = {
6
- column: dataTableColumnsInterface<any>;
7
+ column: DataTableColumnsInterface<any>;
7
8
  idx: number;
8
- rowIndex: number;
9
9
  row: any;
10
- container?: "cell" | "card";
11
- onEnterNextColumn?: (columnIndex: number, rowIndex: number) => void;
10
+ onEditColumnByOverlay?: (row: any) => void;
11
+ stickyLeft?: number;
12
12
  };
13
13
  export const DataTableRow = ({
14
14
  column,
15
15
  idx,
16
- rowIndex,
17
16
  row,
18
- container = "cell",
19
- onEnterNextColumn,
17
+ onEditColumnByOverlay,
18
+ stickyLeft,
20
19
  }: DataTableRowProps) => {
21
20
  const value = (row as any)[column.id]; // On utilise [column.id] pour accéder aux bonnes propriétés
22
21
  const style = column.onRowStyle ? column.onRowStyle(row) : {};
23
22
  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;
23
+ const isSticky = stickyLeft !== undefined;
24
+ const [openClickCell, setOpenClickCell] = useState(false);
25
+ const refRow = useRef<HTMLTableCellElement>(null);
26
+ const onClickRenderCell = (e: React.MouseEvent<HTMLTableCellElement>) => {
27
+ if (isDisabled) {
28
+ return;
48
29
  }
49
- newNum = Math.round(newNum * 1000) / 1000;
50
- if (column.onEdit) {
51
- column.onEdit(newNum, row);
30
+ console.log("Cell clicked with value:", value, "in row:", row);
31
+ if (column.openClickCell) {
32
+ if (column.handleClickCell) {
33
+ column.handleClickCell(e, row);
34
+ }
35
+ e.stopPropagation();
36
+ setOpenClickCell((prev) => !prev);
52
37
  }
53
38
  };
54
-
55
- const Container = container === "card" ? "div" : "td";
56
-
57
39
  return (
58
- <Container
59
- className={`${isDisabled ? "disabled" : ""}`}
60
- data-column-index={idx}
61
- data-row-index={rowIndex}
40
+ <td
41
+ ref={refRow}
62
42
  style={{
63
43
  minWidth: column.minWidth,
64
- textAlign: column.align || "left",
44
+ textAlign: column.alignText ? column.alignText : column.align || "left",
65
45
  maxWidth: column.maxWidth,
66
46
  width: column.width,
47
+ ...(!isDisabled &&
48
+ (column.openClickCell || column.renderClickCellComponent)
49
+ ? { cursor: "pointer" }
50
+ : {}),
51
+ ...(isSticky
52
+ ? {
53
+ position: "sticky",
54
+ left: stickyLeft,
55
+ zIndex: 2,
56
+ backgroundColor: "#fff",
57
+ }
58
+ : {}),
67
59
  ...style,
68
60
  }}
61
+ onClick={onClickRenderCell}
69
62
  key={`row-${column.id}-${idx}`}
63
+ className={isSticky ? "data-table-sticky-cell" : ""}
70
64
  >
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
65
+ {column.renderComponent ? column.renderComponent(value, row) : null}
66
+ {!column.renderComponent && (
67
+ <DataTableRowValue
68
+ editable={
69
+ !isDisabled &&
70
+ (column.onEditable?.(value, row) ?? column.editable ?? false)
71
+ }
72
+ column={column}
73
+ value={value}
74
+ row={row}
75
+ />
205
76
  )}
206
- </Container>
77
+ {openClickCell &&
78
+ !isDisabled &&
79
+ column.displayOverlay &&
80
+ refRow.current && (
81
+ <DataTableRowOverlay
82
+ refRow={refRow}
83
+ column={column}
84
+ row={row}
85
+ value={value}
86
+ onEditColumnByOverlay={onEditColumnByOverlay}
87
+ onClose={() => setOpenClickCell(false)}
88
+ />
89
+ )}
90
+ </td>
207
91
  );
208
92
  };
@@ -0,0 +1,80 @@
1
+ import { useRef, useState } from "react";
2
+ import { Button } from "../../../button/Button";
3
+ import { OverlayPanel } from "../../../overlayPanel/OverlayPanel";
4
+ import { DataTableColumnsInterface } from "../../dataTable.interface";
5
+ import { DataTableRowValue } from "../dataTableRowValue/DataTableRowValue";
6
+
7
+ type DataTableRowOverlayProps = {
8
+ row: any;
9
+ column: DataTableColumnsInterface<any>;
10
+ value: string;
11
+ refRow: React.RefObject<HTMLTableCellElement>;
12
+ onClose?: (close: boolean) => void;
13
+ onEditColumnByOverlay?: (newRow: any) => void;
14
+ };
15
+ export const DataTableRowOverlay = ({
16
+ row,
17
+ refRow,
18
+ value,
19
+ onClose,
20
+ column,
21
+ onEditColumnByOverlay,
22
+ }: DataTableRowOverlayProps) => {
23
+ const [inputValue, setInputValue] = useState(value);
24
+ const formRef = useRef<HTMLFormElement>(null);
25
+
26
+ const onChange = (newValue: any) => {
27
+ setInputValue(newValue);
28
+ };
29
+
30
+ const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
31
+ e.preventDefault();
32
+ if (onEditColumnByOverlay) {
33
+ const newRow = { ...row, [column.id]: inputValue };
34
+ onEditColumnByOverlay(newRow);
35
+ }
36
+ if (onClose) {
37
+ onClose(true);
38
+ }
39
+ };
40
+
41
+ const handleButtonClick = (
42
+ e: React.MouseEvent<HTMLButtonElement, MouseEvent>,
43
+ ) => {
44
+ e.preventDefault();
45
+ formRef.current?.requestSubmit();
46
+ };
47
+
48
+ const handleClose = () => {
49
+ if (onClose) {
50
+ onClose(true);
51
+ }
52
+ };
53
+
54
+ return (
55
+ <OverlayPanel
56
+ show={true}
57
+ position="bottomLeft"
58
+ closeOverlay={handleClose}
59
+ referenceElement={refRow?.current ?? undefined}
60
+ children={
61
+ <div className="d-flex flex-column pt-3">
62
+ <form onSubmit={onSubmit} ref={formRef}>
63
+ <DataTableRowValue
64
+ editable={true}
65
+ column={column}
66
+ value={inputValue}
67
+ row={row}
68
+ onChange={onChange}
69
+ />
70
+ {onEditColumnByOverlay && (
71
+ <div className="d-flex justify-content-end mt-2">
72
+ <Button title="Valider" onClick={handleButtonClick} />
73
+ </div>
74
+ )}
75
+ </form>
76
+ </div>
77
+ }
78
+ />
79
+ );
80
+ };
@@ -0,0 +1,123 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { Select } from "../../../select/Select";
3
+ import { DataTableColumnsInterface } from "../../dataTable.interface";
4
+
5
+ type DataTableRowValueProps = {
6
+ column: DataTableColumnsInterface<any>;
7
+ value: any;
8
+ row: any;
9
+ editable?: boolean;
10
+ onChange?: (value: any) => void;
11
+ };
12
+ export const DataTableRowValue = ({
13
+ column,
14
+ row,
15
+ value,
16
+ editable,
17
+ onChange,
18
+ }: DataTableRowValueProps) => {
19
+ const [draftValue, setDraftValue] = useState(value ?? "");
20
+ const editOnEnter = column.onEditTrigger === "enter";
21
+ const skipNextBlurCommit = useRef(false);
22
+ const inputRef = useRef<HTMLInputElement>(null);
23
+ const wasEditableRef = useRef(false);
24
+
25
+ const selectInputText = () => {
26
+ try {
27
+ inputRef.current?.select();
28
+ } catch {
29
+ // Some input types (e.g. date) may not support text selection.
30
+ }
31
+ };
32
+
33
+ const commitValue = (nextValue: any) => {
34
+ if (column.onEdit) {
35
+ column.onEdit(nextValue, row);
36
+ }
37
+ };
38
+
39
+ useEffect(() => {
40
+ setDraftValue(value ?? "");
41
+ }, [value]);
42
+
43
+ useEffect(() => {
44
+ if (editable && !wasEditableRef.current) {
45
+ inputRef.current?.focus();
46
+ selectInputText();
47
+ }
48
+ wasEditableRef.current = !!editable;
49
+ }, [editable]);
50
+
51
+ return (
52
+ <>
53
+ {editable ? (
54
+ column.type === "select" ? (
55
+ <Select
56
+ options={column.options ?? []}
57
+ value={value}
58
+ onChange={(e) => {
59
+ if (onChange) {
60
+ onChange(e);
61
+ }
62
+ if (column.onChange) {
63
+ column.onChange(e, row);
64
+ }
65
+ if (column.onEdit) {
66
+ column.onEdit(e, row);
67
+ }
68
+ }}
69
+ />
70
+ ) : (
71
+ <input
72
+ ref={inputRef}
73
+ type={column.type}
74
+ value={editOnEnter ? draftValue : value}
75
+ step="0.01"
76
+ style={{
77
+ textAlign: column.alignText
78
+ ? column.alignText
79
+ : column.align || "left",
80
+ }}
81
+ onFocus={selectInputText}
82
+ onChange={(e) => {
83
+ const nextValue = e.target.value;
84
+ if (onChange) {
85
+ onChange(nextValue);
86
+ }
87
+ if (column.onChange) {
88
+ column.onChange(nextValue, row);
89
+ }
90
+ if (editOnEnter) {
91
+ setDraftValue(nextValue);
92
+ return;
93
+ }
94
+ commitValue(nextValue);
95
+ }}
96
+ onKeyDown={(e) => {
97
+ if (editOnEnter && e.key === "Enter") {
98
+ skipNextBlurCommit.current = true;
99
+ commitValue(draftValue);
100
+ }
101
+ }}
102
+ onBlur={() => {
103
+ if (!editOnEnter) {
104
+ return;
105
+ }
106
+ if (skipNextBlurCommit.current) {
107
+ skipNextBlurCommit.current = false;
108
+ return;
109
+ }
110
+ if (draftValue !== value) {
111
+ commitValue(draftValue);
112
+ }
113
+ }}
114
+ />
115
+ )
116
+ ) : column.format ? (
117
+ column.format(value)
118
+ ) : (
119
+ value
120
+ )}
121
+ </>
122
+ );
123
+ };
@@ -1,4 +1,3 @@
1
- import { useCallback, useEffect, useState } from "react";
2
1
  import { Expand } from "./expand/expand";
3
2
  import { ExpandInterface } from "./expand/expand.interface";
4
3
  import "./expands.css";
@@ -12,19 +11,6 @@ type ExpandProps = {
12
11
  };
13
12
 
14
13
  export const Expands = (props: ExpandProps) => {
15
- const [currentExpand, setCurrentExpand] = useState<ExpandInterface>();
16
- const onChangeExpand = useCallback(
17
- (item: ExpandInterface) => {
18
- if (props.onChange) {
19
- props.onChange(item);
20
- }
21
- setCurrentExpand(item);
22
- },
23
- [setCurrentExpand, props.onChange]
24
- );
25
- useEffect(() => {
26
- setCurrentExpand(props.currentItem);
27
- }, [props.currentItem, setCurrentExpand, document.activeElement]);
28
14
  return (
29
15
  <div className={`expands ${props.className || ""}`}>
30
16
  {props.items.map((item: ExpandInterface) => (
@@ -32,8 +18,8 @@ export const Expands = (props: ExpandProps) => {
32
18
  key={item.id}
33
19
  item={item}
34
20
  showArrow={props.showArrow}
35
- onChange={onChangeExpand}
36
- currentExpand={currentExpand}
21
+ onChange={props.onChange}
22
+ currentExpand={props.currentItem}
37
23
  />
38
24
  ))}
39
25
  </div>
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useRef, useState } from "react";
1
+ import { useCallback } from "react";
2
2
  import { Icon } from "../../icon/Icon";
3
3
  import { ExpandInterface } from "./expand.interface";
4
4
 
@@ -7,7 +7,7 @@ export type ExpandProps = {
7
7
  item: ExpandInterface;
8
8
  className?: string;
9
9
  showArrow?: boolean;
10
- onChange: (item: ExpandInterface) => void;
10
+ onChange?: (item: ExpandInterface) => void;
11
11
  };
12
12
  export const Expand = ({
13
13
  currentExpand,
@@ -16,128 +16,13 @@ export const Expand = ({
16
16
  showArrow = true,
17
17
  onChange,
18
18
  }: ExpandProps): JSX.Element => {
19
- const [active, setActive] = useState<boolean>(false);
20
- const expandRef = useRef<HTMLDivElement>(null);
21
-
22
- useEffect(() => {
23
- if (item && currentExpand) {
24
- if (currentExpand.id === item.id) {
25
- if (!active) {
26
- setActive(true);
27
- }
28
- } else {
29
- setActive(false);
30
- }
31
- } else {
32
- setActive(false);
33
- }
34
- }, [currentExpand, setActive, item, active]);
35
-
36
- const scrollToHeader = useCallback(() => {
37
- const expandElement = expandRef.current;
38
- if (!expandElement) return;
39
-
40
- let scrollParent: HTMLElement | null = expandElement.parentElement;
41
- while (scrollParent) {
42
- const style = window.getComputedStyle(scrollParent);
43
- const isScrollable =
44
- /(auto|scroll)/.test(style.overflow + style.overflowY) &&
45
- scrollParent.scrollHeight > scrollParent.clientHeight;
46
-
47
- if (isScrollable) {
48
- const parentRect = scrollParent.getBoundingClientRect();
49
- const targetRect = expandElement.getBoundingClientRect();
50
- const offsetTop =
51
- targetRect.top - parentRect.top + scrollParent.scrollTop;
52
-
53
- scrollParent.scrollTo({
54
- top: offsetTop,
55
- behavior: "smooth",
56
- });
57
- return;
58
- }
59
- scrollParent = scrollParent.parentElement;
60
- }
61
-
62
- const header =
63
- expandElement.querySelector<HTMLElement>(".expand-header") ||
64
- expandElement;
65
- header.scrollIntoView({ behavior: "smooth", block: "start" });
66
- }, []);
67
-
68
- useEffect(() => {
69
- if (active) {
70
- const timer1 = setTimeout(() => {
71
- scrollToHeader();
72
- }, 100);
73
- const timer2 = setTimeout(() => {
74
- scrollToHeader();
75
- }, 350);
76
- return () => {
77
- clearTimeout(timer1);
78
- clearTimeout(timer2);
79
- };
80
- }
81
- }, [active, scrollToHeader]);
82
-
83
- const handleFocusCapture = useCallback(
84
- (e: React.FocusEvent<HTMLDivElement>) => {
85
- const target = e.target as HTMLElement;
86
- if (
87
- active &&
88
- (target.tagName === "INPUT" ||
89
- target.tagName === "TEXTAREA" ||
90
- target.tagName === "SELECT")
91
- ) {
92
- const expandElement = expandRef.current;
93
- if (!expandElement) return;
94
-
95
- const performScroll = () => {
96
- let scrollParent: HTMLElement | null = expandElement.parentElement;
97
- while (scrollParent) {
98
- const style = window.getComputedStyle(scrollParent);
99
- const isScrollable =
100
- /(auto|scroll)/.test(style.overflow + style.overflowY) &&
101
- scrollParent.scrollHeight > scrollParent.clientHeight;
102
-
103
- if (isScrollable) {
104
- const parentRect = scrollParent.getBoundingClientRect();
105
- const headerRect = expandElement.getBoundingClientRect();
106
- const headerOffsetTop =
107
- headerRect.top - parentRect.top + scrollParent.scrollTop;
108
-
109
- // Si on a déjà scrollé vers ou au-delà du header, on ne remonte JAMAIS au header
110
- if (scrollParent.scrollTop >= headerOffsetTop - 10) {
111
- const targetRect = target.getBoundingClientRect();
112
- if (targetRect.bottom > parentRect.bottom) {
113
- target.scrollIntoView({ behavior: "smooth", block: "nearest" });
114
- }
115
- return;
116
- }
117
-
118
- // Si on n'a pas encore scrollé jusqu'au header, on y va
119
- scrollParent.scrollTo({
120
- top: headerOffsetTop,
121
- behavior: "smooth",
122
- });
123
- return;
124
- }
125
- scrollParent = scrollParent.parentElement;
126
- }
127
- };
128
-
129
- performScroll();
130
- // Répéter après l'ouverture du clavier virtuel (spécifique tablettes / mobiles Android)
131
- setTimeout(performScroll, 300);
132
- }
133
- },
134
- [active],
135
- );
136
-
19
+ const active = currentExpand?.id === item.id;
20
+ console.log("render expand", item.title, "active", active);
137
21
  const handleChange = useCallback(
138
22
  (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
139
23
  e.stopPropagation();
140
24
  if (onChange) {
25
+ console.log("expand", item);
141
26
  onChange(item);
142
27
  }
143
28
  },
@@ -145,9 +30,7 @@ export const Expand = ({
145
30
  );
146
31
  return (
147
32
  <div
148
- ref={expandRef}
149
33
  onClick={handleChange}
150
- onFocusCapture={handleFocusCapture}
151
34
  className={`expand ${active ? "expand--active" : ""} ${className ?? ""}`}
152
35
  >
153
36
  <div className={`expand-header`}>