kelt-ui-kit-react 2.0.9 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/card/cardAction/CardAction.d.ts +2 -1
- package/dist/index.js +1995 -1980
- package/dist/overlayPanel/OverlayPanel.d.ts +1 -1
- package/dist/select/Select.d.ts +3 -1
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/card/cardAction/CardAction.tsx +2 -8
- package/src/dataTable/DataTable.tsx +7 -2
- package/src/dataTable/dataTable.css +101 -1
- package/src/dataTable/dataTableColumn/DataTableColumn.tsx +2 -2
- package/src/dataTable/useDataTableState.tsx +7 -1
- package/src/overlayPanel/OverlayPanel.tsx +6 -1
- package/src/select/Select.tsx +4 -2
package/package.json
CHANGED
|
@@ -4,17 +4,11 @@ import { Icon } from "../../icon/Icon";
|
|
|
4
4
|
import { IconSizeEnum } from "../../icon/iconSize.enum";
|
|
5
5
|
import { MenuInterface } from "../../menus/menu/menu.interface";
|
|
6
6
|
import { Menus } from "../../menus/Menus";
|
|
7
|
-
import { OverlayPanel } from "../../overlayPanel/OverlayPanel";
|
|
7
|
+
import { OverlayPanel, PositionOverlay } from "../../overlayPanel/OverlayPanel";
|
|
8
8
|
import { CardInterface } from "../card.interface";
|
|
9
9
|
import { CardActionInterface } from "../cardAction.interface";
|
|
10
10
|
import "./cardAction.css";
|
|
11
|
-
export type PositionOverlay
|
|
12
|
-
| "left"
|
|
13
|
-
| "right"
|
|
14
|
-
| "topLeft"
|
|
15
|
-
| "topRight"
|
|
16
|
-
| "bottomLeft"
|
|
17
|
-
| "bottomRight";
|
|
11
|
+
export type { PositionOverlay };
|
|
18
12
|
export type CardActionProps = {
|
|
19
13
|
actions: CardActionInterface[];
|
|
20
14
|
item?: CardInterface;
|
|
@@ -22,6 +22,8 @@ export type {
|
|
|
22
22
|
DataTableDateRangeFilterValue, DataTableFilterState, DataTableSortDirection,
|
|
23
23
|
DataTableSortState, FilterValue,
|
|
24
24
|
} from "./dataTable.utils";
|
|
25
|
+
const DEFAULT_FILTER_COLUMN_WIDTH = 100;
|
|
26
|
+
|
|
25
27
|
export type DataTableProps<T> = {
|
|
26
28
|
id: string;
|
|
27
29
|
name?: string;
|
|
@@ -641,10 +643,13 @@ export function DataTable<T>(props: DataTableProps<T>) {
|
|
|
641
643
|
{actions.length > 0 && <col style={{ width: actionsColumnWidth }} />}
|
|
642
644
|
</colgroup>
|
|
643
645
|
<thead>
|
|
644
|
-
{tableState.visibleFilters.size > 0 && <tr ref={filterRowRef}>
|
|
646
|
+
{tableState.visibleFilters.size > 0 && <tr className="data-table-filter-row" ref={filterRowRef}>
|
|
645
647
|
{onSelectionChange && <th />}
|
|
646
648
|
{columns.map((column) => <th className="filter-row-cell" key={column.id}
|
|
647
|
-
style={{ position: "sticky", top: 0, zIndex: 14, background: "#f9fbfc",
|
|
649
|
+
style={{ position: "sticky", top: 0, zIndex: 14, background: "#f9fbfc",
|
|
650
|
+
width: column.width ?? DEFAULT_FILTER_COLUMN_WIDTH,
|
|
651
|
+
minWidth: column.width ?? DEFAULT_FILTER_COLUMN_WIDTH,
|
|
652
|
+
maxWidth: column.width ?? DEFAULT_FILTER_COLUMN_WIDTH,
|
|
648
653
|
...(column.sticky ? { left: stickyOffsets.get(column.id) } : {}) }}>
|
|
649
654
|
{tableState.renderFilter(column)}
|
|
650
655
|
</th>)}
|
|
@@ -135,6 +135,102 @@
|
|
|
135
135
|
color: var(--tertiary-color);
|
|
136
136
|
min-width: 100px;
|
|
137
137
|
padding: .5rem;
|
|
138
|
+
|
|
139
|
+
.data-table-column-filter,
|
|
140
|
+
.data-table-column-sort {
|
|
141
|
+
visibility: hidden;
|
|
142
|
+
|
|
143
|
+
&.active {
|
|
144
|
+
visibility: visible;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.data-table-column-filter-active,
|
|
149
|
+
.data-table-column-sort-active {
|
|
150
|
+
color: var(--tertiary-color);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
&:hover,
|
|
154
|
+
&:focus-within {
|
|
155
|
+
.data-table-column-filter,
|
|
156
|
+
.data-table-column-sort {
|
|
157
|
+
visibility: visible;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.data-table-filter-row {
|
|
163
|
+
th {
|
|
164
|
+
padding-top: 6px;
|
|
165
|
+
padding-bottom: 6px;
|
|
166
|
+
overflow: visible;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.data-table-filter-select {
|
|
170
|
+
width: 100%;
|
|
171
|
+
max-width: 100%;
|
|
172
|
+
|
|
173
|
+
button {
|
|
174
|
+
width: 100%;
|
|
175
|
+
max-width: 100%;
|
|
176
|
+
overflow: hidden;
|
|
177
|
+
padding: 4px 6px;
|
|
178
|
+
border: 1px solid #dedede;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.select-container-value {
|
|
182
|
+
display: block;
|
|
183
|
+
min-width: 0;
|
|
184
|
+
overflow: hidden;
|
|
185
|
+
text-overflow: ellipsis;
|
|
186
|
+
white-space: nowrap;
|
|
187
|
+
font-size: 0.7rem;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.data-table-filter-input-wrapper {
|
|
192
|
+
width: 100%;
|
|
193
|
+
max-width: 100%;
|
|
194
|
+
overflow: visible;
|
|
195
|
+
box-sizing: border-box;
|
|
196
|
+
|
|
197
|
+
.input-clear-icon,
|
|
198
|
+
.input-clear-btn,
|
|
199
|
+
.clear-btn {
|
|
200
|
+
right: 5px;
|
|
201
|
+
|
|
202
|
+
.bi {
|
|
203
|
+
font-size: 0.8rem;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.input-container {
|
|
208
|
+
min-width: 0;
|
|
209
|
+
width: 100%;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.select-container,
|
|
213
|
+
.select-container-button {
|
|
214
|
+
max-width: 100%;
|
|
215
|
+
min-width: 0;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.data-table-filter-input {
|
|
220
|
+
width: 100%;
|
|
221
|
+
max-width: 100%;
|
|
222
|
+
min-width: 0;
|
|
223
|
+
box-sizing: border-box;
|
|
224
|
+
overflow: hidden;
|
|
225
|
+
text-overflow: ellipsis;
|
|
226
|
+
white-space: nowrap;
|
|
227
|
+
border: 1px solid #c9cfdb;
|
|
228
|
+
border-radius: 6px;
|
|
229
|
+
padding: 4px 6px;
|
|
230
|
+
font-size: 12px;
|
|
231
|
+
background-color: #fff;
|
|
232
|
+
color: #333;
|
|
233
|
+
}
|
|
138
234
|
}
|
|
139
235
|
}
|
|
140
236
|
|
|
@@ -214,7 +310,11 @@
|
|
|
214
310
|
.data-table-column-heading {
|
|
215
311
|
display: flex;
|
|
216
312
|
align-items: center;
|
|
217
|
-
gap:
|
|
313
|
+
gap: 4px;
|
|
314
|
+
|
|
315
|
+
> .flex-1 {
|
|
316
|
+
flex: 1;
|
|
317
|
+
}
|
|
218
318
|
}
|
|
219
319
|
.data-table-group-row th {
|
|
220
320
|
height: 40px;
|
|
@@ -39,9 +39,9 @@ export const DataTableColumn = ({
|
|
|
39
39
|
onClick={() => onColumnClick?.(column)}
|
|
40
40
|
>
|
|
41
41
|
<div className="data-table-column-heading">
|
|
42
|
-
<span>{column.label}</span>
|
|
43
|
-
{column.sortable && <DataTableColumnSort column={column} sortDirection={sortDirection} onToggleSort={onToggleSort} />}
|
|
42
|
+
<span className="flex-1">{column.label}</span>
|
|
44
43
|
{column.filterable && <DataTableColumnFilter column={column} isFilterVisible={isFilterVisible} onToggleVisibility={onToggleFilter} />}
|
|
44
|
+
{column.sortable && <DataTableColumnSort column={column} sortDirection={sortDirection} onToggleSort={onToggleSort} />}
|
|
45
45
|
</div>
|
|
46
46
|
</th>
|
|
47
47
|
);
|
|
@@ -60,6 +60,11 @@ export function useDataTableState<T>(
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
function renderFilter(column: dataTableColumnsInterface<T>) {
|
|
63
|
+
const control = renderFilterControl(column);
|
|
64
|
+
return control && <div className="data-table-filter-input-wrapper">{control}</div>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function renderFilterControl(column: dataTableColumnsInterface<T>) {
|
|
63
68
|
const key = getFilterKey(column);
|
|
64
69
|
if (!column.filterable || !visibleFilters.has(key)) return null;
|
|
65
70
|
const value = filters[key];
|
|
@@ -72,7 +77,7 @@ export function useDataTableState<T>(
|
|
|
72
77
|
}
|
|
73
78
|
if (column.filterType === TypeInputEnum.CHECKBOX || column.filterType === TypeInputEnum.RADIO) {
|
|
74
79
|
return <Select id={inputId} options={column.filterDataEnum ?? []} multiple
|
|
75
|
-
usePortal showOptions={focusKey === key}
|
|
80
|
+
className="data-table-filter-select" classNameOverlay="data-table-filter-select-overlay" usePortal showOptions={focusKey === key}
|
|
76
81
|
value={String(value ?? "").split(",").filter(Boolean)}
|
|
77
82
|
onChangeMultiple={(values) => updateFilter(key, values.join(","))}
|
|
78
83
|
placeholder={`Filtrer ${column.label}`} />;
|
|
@@ -81,6 +86,7 @@ export function useDataTableState<T>(
|
|
|
81
86
|
type={column.filterType === TypeInputEnum.DATE ? TypeInputEnum.DATE : TypeInputEnum.TEXT}
|
|
82
87
|
value={String(value ?? "")} autoFocus={focusKey === key}
|
|
83
88
|
disabledDebounce showClearButton placeholder={`Filtrer ${column.label}`}
|
|
89
|
+
className="data-table-filter-input"
|
|
84
90
|
onClick={(event) => event.stopPropagation()}
|
|
85
91
|
onChange={(event) => updateFilter(key, event.target.value)} />;
|
|
86
92
|
}
|
|
@@ -20,6 +20,7 @@ export type PositionOverlay =
|
|
|
20
20
|
| "right"
|
|
21
21
|
| "topLeft"
|
|
22
22
|
| "topRight"
|
|
23
|
+
| "bottom"
|
|
23
24
|
| "bottomLeft"
|
|
24
25
|
| "bottomRight";
|
|
25
26
|
|
|
@@ -107,6 +108,10 @@ export const OverlayPanel = forwardRef(
|
|
|
107
108
|
top: rect.bottom,
|
|
108
109
|
left: rect.left,
|
|
109
110
|
}),
|
|
111
|
+
bottom: () => ({
|
|
112
|
+
top: rect.bottom,
|
|
113
|
+
left: rect.left + rect.width / 2 - boxRect.width / 2,
|
|
114
|
+
}),
|
|
110
115
|
left: () => ({
|
|
111
116
|
top: rect.top + rect.height / 2 - boxRect.height / 2,
|
|
112
117
|
left: rect.left - boxRect.width,
|
|
@@ -122,7 +127,7 @@ export const OverlayPanel = forwardRef(
|
|
|
122
127
|
({ top, left } = positions[position]());
|
|
123
128
|
// Manque d'espace en bas → afficher au-dessus de l'élément
|
|
124
129
|
if (
|
|
125
|
-
(position === "bottomLeft" || position === "bottomRight") &&
|
|
130
|
+
(position === "bottom" || position === "bottomLeft" || position === "bottomRight") &&
|
|
126
131
|
top + boxRect.height > innerHeight &&
|
|
127
132
|
rect.top - boxRect.height >= 0
|
|
128
133
|
) {
|
package/src/select/Select.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { Icon } from "../icon/Icon";
|
|
3
3
|
|
|
4
|
-
import { OverlayPanel } from "../overlayPanel/OverlayPanel";
|
|
4
|
+
import { OverlayPanel, PositionOverlay } from "../overlayPanel/OverlayPanel";
|
|
5
5
|
import "./select.css";
|
|
6
6
|
import { SelectOptionInterface } from "./selectOption.interface";
|
|
7
7
|
|
|
@@ -26,6 +26,7 @@ export interface SelectProps {
|
|
|
26
26
|
onChange?: (value: string) => void;
|
|
27
27
|
placeholder?: string;
|
|
28
28
|
classNameOverlay?: string;
|
|
29
|
+
positionOverlay?: PositionOverlay;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
export const Select = ({
|
|
@@ -46,6 +47,7 @@ export const Select = ({
|
|
|
46
47
|
value,
|
|
47
48
|
placeholder,
|
|
48
49
|
classNameOverlay,
|
|
50
|
+
positionOverlay = "bottomLeft",
|
|
49
51
|
}: SelectProps): JSX.Element => {
|
|
50
52
|
const [showOverlay, setShowOverlay] = useState(false);
|
|
51
53
|
const [overlayRef, setOverlayRef] = useState<HTMLElement | null>(null);
|
|
@@ -175,7 +177,7 @@ export const Select = ({
|
|
|
175
177
|
{showOverlay && overlayRef && (
|
|
176
178
|
<OverlayPanel
|
|
177
179
|
show={showOverlay}
|
|
178
|
-
position=
|
|
180
|
+
position={positionOverlay}
|
|
179
181
|
className={classNameOverlay ?? ""}
|
|
180
182
|
closeOverlay={() => setShowOverlay(false)}
|
|
181
183
|
referenceElement={overlayRef}
|