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.
- package/README.md +0 -26
- package/dist/_core/type/generiqueType.d.ts +4 -0
- package/dist/badge/Badge.d.ts +3 -1
- package/dist/button/Button.d.ts +1 -1
- package/dist/button/button.interface.d.ts +1 -2
- package/dist/dataTable/DataTable.d.ts +17 -14
- package/dist/dataTable/dataTable.interface.d.ts +24 -19
- package/dist/dataTable/dataTableActions/DataTableAction.d.ts +3 -5
- package/dist/dataTable/dataTableColumn/DataTableColumn.d.ts +13 -7
- package/dist/dataTable/dataTableColumn/dataTableColumnFilter/DataTableColumnFilter.d.ts +10 -0
- package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDate/DataTableColumnFilterDate.d.ts +9 -0
- package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDateRange/dataTableColumnFilterDateRange.d.ts +9 -0
- package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterEnum/DataTableColumnFilterEnum.d.ts +13 -0
- package/dist/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterString/DataTableColumnFilterString.d.ts +9 -0
- package/dist/dataTable/dataTableColumn/dataTableColumnSort/DataTableColumnSort.d.ts +11 -0
- package/dist/dataTable/dataTableFilters/DataTableFilters.d.ts +7 -0
- package/dist/dataTable/dataTableLoading/DataTableLoading.d.ts +1 -3
- package/dist/dataTable/dataTableRow/DataTableRow.d.ts +5 -6
- package/dist/dataTable/dataTableRow/dataTableRowOverlay/DataTableRowOverlay.d.ts +12 -0
- package/dist/dataTable/dataTableRow/dataTableRowValue/DataTableRowValue.d.ts +11 -0
- package/dist/expands/expand/expand.d.ts +1 -1
- package/dist/form/Form.d.ts +2 -4
- package/dist/form/form.enum.d.ts +2 -3
- package/dist/form/form.interface.d.ts +2 -19
- package/dist/form/input/Input.d.ts +3 -0
- package/dist/form/inputNumber/InputNumber.d.ts +0 -2
- package/dist/grid/col/Col.d.ts +6 -3
- package/dist/grid/col/colStyled/ColStyled.d.ts +5 -7
- package/dist/grid/grid.interface.d.ts +5 -9
- package/dist/header/Header.d.ts +1 -1
- package/dist/header/header.interface.d.ts +1 -2
- package/dist/icon/Icon.d.ts +1 -1
- package/dist/icon/icon.interface.d.ts +1 -0
- package/dist/index.d.ts +1 -5
- package/dist/index.js +3606 -3543
- package/dist/menus/menu/Menu.d.ts +0 -1
- package/dist/overlayPanel/OverlayPanel.d.ts +4 -2
- package/dist/overlayPanel/overlayPanelStyled/OverlayPanelStyled.d.ts +2 -0
- package/dist/select/Select.d.ts +6 -2
- package/dist/select/selectOption.interface.d.ts +1 -0
- package/dist/style.css +1 -1
- package/dist/tabs/Tabs.d.ts +2 -1
- package/dist/toaster/store/useToasterStore.d.ts +0 -1
- package/index.html +2 -1
- package/package/package.json +56 -0
- package/package/src/sidebar/Sidebar.tsx +208 -0
- package/package/src/sidebar/sidebar.css +104 -0
- package/package.json +1 -1
- package/src/App.menu.tsx +0 -8
- package/src/_core/type/generiqueType.tsx +4 -0
- package/src/badge/Badge.tsx +9 -1
- package/src/badge/badge.css +4 -0
- package/src/button/Button.tsx +1 -3
- package/src/button/button.css +2 -2
- package/src/button/button.interface.tsx +1 -2
- package/src/card/card.css +25 -5
- package/src/card/cardAction/CardAction.tsx +4 -4
- package/src/damier/Damier.tsx +7 -16
- package/src/damier/damier.css +4 -11
- package/src/dataTable/DataTable.tsx +685 -542
- package/src/dataTable/DataTable.view.tsx +48 -24
- package/src/dataTable/dataTable.css +134 -159
- package/src/dataTable/dataTable.interface.ts +25 -19
- package/src/dataTable/dataTableActions/DataTableAction.tsx +14 -25
- package/src/dataTable/dataTableColumn/DataTableColumn.tsx +64 -14
- package/src/dataTable/dataTableColumn/dataTableColumnFilter/DataTableColumnFilter.tsx +36 -0
- package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilter.css +0 -0
- package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDate/DataTableColumnFilterDate.tsx +39 -0
- package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterDateRange/dataTableColumnFilterDateRange.tsx +80 -0
- package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterEnum/DataTableColumnFilterEnum.tsx +89 -0
- package/src/dataTable/dataTableColumn/dataTableColumnFilter/dataTableColumnFilterString/DataTableColumnFilterString.tsx +37 -0
- package/src/dataTable/dataTableColumn/dataTableColumnSort/DataTableColumnSort.tsx +42 -0
- package/src/dataTable/dataTableFilters/DataTableFilters.tsx +91 -0
- package/src/dataTable/dataTableFilters/dataTableFilters.css +16 -0
- package/src/dataTable/dataTableLoading/DataTableLoading.tsx +4 -15
- package/src/dataTable/dataTableRow/DataTableRow.tsx +64 -180
- package/src/dataTable/dataTableRow/dataTableRowOverlay/DataTableRowOverlay.tsx +80 -0
- package/src/dataTable/dataTableRow/dataTableRowValue/DataTableRowValue.tsx +123 -0
- package/src/expands/Expands.tsx +2 -16
- package/src/expands/expand/expand.tsx +5 -122
- package/src/expands/expands.css +3 -8
- package/src/form/Form.tsx +93 -258
- package/src/form/Form.view.tsx +1 -9
- package/src/form/form.css +1 -51
- package/src/form/form.enum.ts +1 -2
- package/src/form/form.interface.tsx +2 -28
- package/src/form/input/Input.tsx +61 -7
- package/src/form/input/input.css +23 -1
- package/src/form/inputNumber/InputNumber.tsx +6 -11
- package/src/form/inputPrice/InputPrice.tsx +2 -4
- package/src/grid/col/Col.tsx +7 -5
- package/src/grid/col/colStyled/ColStyled.tsx +7 -21
- package/src/grid/grid.interface.tsx +5 -11
- package/src/grid/row/row.css +2 -2
- package/src/header/Header.tsx +2 -4
- package/src/header/header.css +0 -17
- package/src/header/header.interface.tsx +1 -2
- package/src/icon/Icon.tsx +6 -2
- package/src/icon/icon.interface.tsx +1 -0
- package/src/index.css +12 -58
- package/src/index.ts +2 -12
- package/src/menus/Menus.tsx +0 -1
- package/src/menus/menu/Menu.tsx +1 -2
- package/src/overlayPanel/OverlayPanel.tsx +71 -18
- package/src/overlayPanel/overlay.context.tsx +6 -4
- package/src/overlayPanel/overlayPanel.css +10 -1
- package/src/overlayPanel/overlayPanelStyled/OverlayPanelStyled.tsx +7 -2
- package/src/select/Select.tsx +178 -41
- package/src/select/select.css +94 -13
- package/src/select/selectOption.interface.ts +1 -0
- package/src/sidebar/Sidebar.tsx +5 -107
- package/src/sidebar/sidebar.css +1 -18
- package/src/tabs/Tabs.tsx +20 -1
- package/src/tabs/tabs.css +3 -9
- package/src/toaster/Toaster.tsx +2 -7
- package/src/toaster/Toaster.view.tsx +0 -1
- package/src/toaster/store/useToasterStore.tsx +0 -2
- package/src/toaster/toaster.css +2 -7
- package/dist/addressSearch/AddressSearch.d.ts +0 -20
- package/dist/addressSearch/AddressSearch.view.d.ts +0 -1
- package/dist/geocoding/GeocodingService.d.ts +0 -13
- package/dist/geocoding/geocoding.interface.d.ts +0 -20
- package/src/addressSearch/AddressSearch.tsx +0 -246
- package/src/addressSearch/AddressSearch.view.tsx +0 -52
- package/src/addressSearch/addressSearch.css +0 -133
- package/src/geocoding/GeocodingService.ts +0 -89
- package/src/geocoding/geocoding.interface.ts +0 -25
package/src/index.css
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* variables couleur */
|
|
2
2
|
:root {
|
|
3
|
-
--primary-color: #
|
|
4
|
-
--secondary-color: #
|
|
5
|
-
--tertiary-color: #
|
|
6
|
-
--quaternary-color: #
|
|
3
|
+
--primary-color: #004aad;
|
|
4
|
+
--secondary-color: #ff914d;
|
|
5
|
+
--tertiary-color: #00ada1;
|
|
6
|
+
--quaternary-color: #0082ad;
|
|
7
7
|
--success-color: #28a745;
|
|
8
8
|
--info-color: #17a2b8;
|
|
9
9
|
--warning-color: #ec942c;
|
|
@@ -17,10 +17,7 @@
|
|
|
17
17
|
html,
|
|
18
18
|
body {
|
|
19
19
|
margin: 0;
|
|
20
|
-
font-family: "
|
|
21
|
-
font-optical-sizing: auto;
|
|
22
|
-
font-style: normal;
|
|
23
|
-
font-size: 18px;
|
|
20
|
+
font-family: "Raleway", sans-serif !important;
|
|
24
21
|
-webkit-font-smoothing: antialiased;
|
|
25
22
|
-moz-osx-font-smoothing: grayscale;
|
|
26
23
|
height: 100%;
|
|
@@ -31,48 +28,38 @@ body {
|
|
|
31
28
|
width: 100%;
|
|
32
29
|
background-color: #fff;
|
|
33
30
|
}
|
|
34
|
-
|
|
35
31
|
.app {
|
|
36
32
|
container: app-container/ inline-size;
|
|
37
33
|
}
|
|
38
34
|
|
|
39
35
|
input[type="number"]::-webkit-outer-spin-button,
|
|
40
36
|
input[type="number"]::-webkit-inner-spin-button {
|
|
41
|
-
-webkit-appearance: none;
|
|
42
|
-
/* Chrome, Safari, Edge */
|
|
37
|
+
-webkit-appearance: none; /* Chrome, Safari, Edge */
|
|
43
38
|
margin: 0;
|
|
44
39
|
}
|
|
45
|
-
|
|
46
40
|
/* flex properties */
|
|
47
41
|
|
|
48
42
|
.d-flex {
|
|
49
43
|
display: flex;
|
|
50
44
|
}
|
|
51
|
-
|
|
52
45
|
.justify-content-start {
|
|
53
46
|
justify-content: start;
|
|
54
47
|
}
|
|
55
|
-
|
|
56
48
|
.justify-content-end {
|
|
57
49
|
justify-content: end;
|
|
58
50
|
}
|
|
59
|
-
|
|
60
51
|
.justify-content-center {
|
|
61
52
|
justify-content: center;
|
|
62
53
|
}
|
|
63
|
-
|
|
64
54
|
.justify-content-between {
|
|
65
55
|
justify-content: space-between;
|
|
66
56
|
}
|
|
67
|
-
|
|
68
57
|
.justify-content-around {
|
|
69
58
|
justify-content: space-around;
|
|
70
59
|
}
|
|
71
|
-
|
|
72
60
|
.justify-content-evenly {
|
|
73
61
|
justify-content: space-evenly;
|
|
74
62
|
}
|
|
75
|
-
|
|
76
63
|
.align-items-start {
|
|
77
64
|
align-items: start;
|
|
78
65
|
}
|
|
@@ -323,83 +310,63 @@ a {
|
|
|
323
310
|
.mb-3 {
|
|
324
311
|
margin-bottom: 1rem;
|
|
325
312
|
}
|
|
326
|
-
|
|
327
313
|
.pb-0 {
|
|
328
314
|
padding-bottom: 0;
|
|
329
315
|
}
|
|
330
|
-
|
|
331
316
|
.pb-1 {
|
|
332
317
|
padding-bottom: 0.25rem;
|
|
333
318
|
}
|
|
334
|
-
|
|
335
319
|
.pb-2 {
|
|
336
320
|
padding-bottom: 0.5rem;
|
|
337
321
|
}
|
|
338
|
-
|
|
339
322
|
.pb-3 {
|
|
340
323
|
padding-bottom: 1rem;
|
|
341
324
|
}
|
|
342
|
-
|
|
343
325
|
.pt-0 {
|
|
344
326
|
padding-top: 0;
|
|
345
327
|
}
|
|
346
|
-
|
|
347
328
|
.pt-1 {
|
|
348
329
|
padding-top: 0.25rem;
|
|
349
330
|
}
|
|
350
|
-
|
|
351
331
|
.pt-2 {
|
|
352
332
|
padding-top: 0.5rem;
|
|
353
333
|
}
|
|
354
|
-
|
|
355
334
|
.pt-3 {
|
|
356
335
|
padding-top: 1rem;
|
|
357
336
|
}
|
|
358
|
-
|
|
359
337
|
.pl-0 {
|
|
360
338
|
padding-left: 0;
|
|
361
339
|
}
|
|
362
|
-
|
|
363
340
|
.pl-1 {
|
|
364
341
|
padding-left: 0.25rem;
|
|
365
342
|
}
|
|
366
|
-
|
|
367
343
|
.pl-2 {
|
|
368
344
|
padding-left: 0.5rem;
|
|
369
345
|
}
|
|
370
|
-
|
|
371
346
|
.pl-3 {
|
|
372
347
|
padding-left: 1rem;
|
|
373
348
|
}
|
|
374
|
-
|
|
375
349
|
.pr-0 {
|
|
376
350
|
padding-right: 0;
|
|
377
351
|
}
|
|
378
|
-
|
|
379
352
|
.pr-1 {
|
|
380
353
|
padding-right: 0.25rem;
|
|
381
354
|
}
|
|
382
|
-
|
|
383
355
|
.pr-2 {
|
|
384
356
|
padding-right: 0.5rem;
|
|
385
357
|
}
|
|
386
|
-
|
|
387
358
|
.pr-3 {
|
|
388
359
|
padding-right: 1rem;
|
|
389
360
|
}
|
|
390
|
-
|
|
391
361
|
.p-0 {
|
|
392
362
|
padding: 0;
|
|
393
363
|
}
|
|
394
|
-
|
|
395
364
|
.p-1 {
|
|
396
365
|
padding: 0.25rem;
|
|
397
366
|
}
|
|
398
|
-
|
|
399
367
|
.p-2 {
|
|
400
368
|
padding: 0.5rem;
|
|
401
369
|
}
|
|
402
|
-
|
|
403
370
|
.p-3 {
|
|
404
371
|
padding: 1rem;
|
|
405
372
|
}
|
|
@@ -408,32 +375,25 @@ a {
|
|
|
408
375
|
.border-bottom {
|
|
409
376
|
border-bottom: 1px solid #cfbdbd;
|
|
410
377
|
}
|
|
411
|
-
|
|
412
378
|
.border-top {
|
|
413
379
|
border-top: 1px solid #cfbdbd;
|
|
414
380
|
}
|
|
415
|
-
|
|
416
381
|
.border-left {
|
|
417
382
|
border-left: 1px solid #cfbdbd;
|
|
418
383
|
}
|
|
419
|
-
|
|
420
384
|
.border-right {
|
|
421
385
|
border-right: 1px solid #cfbdbd;
|
|
422
386
|
}
|
|
423
|
-
|
|
424
387
|
/* fonts */
|
|
425
388
|
.font-weight-bold {
|
|
426
389
|
font-weight: 600;
|
|
427
390
|
}
|
|
428
|
-
|
|
429
391
|
.font-weight-light {
|
|
430
392
|
font-weight: 300;
|
|
431
393
|
}
|
|
432
|
-
|
|
433
394
|
.font-weight-normal {
|
|
434
395
|
font-weight: 400;
|
|
435
396
|
}
|
|
436
|
-
|
|
437
397
|
.font-weight-italic {
|
|
438
398
|
font-style: italic;
|
|
439
399
|
}
|
|
@@ -442,41 +402,32 @@ a {
|
|
|
442
402
|
.visible {
|
|
443
403
|
visibility: visible;
|
|
444
404
|
}
|
|
445
|
-
|
|
446
405
|
.hidden {
|
|
447
406
|
visibility: hidden;
|
|
448
407
|
}
|
|
449
|
-
|
|
450
408
|
.position-relative {
|
|
451
409
|
position: relative;
|
|
452
410
|
}
|
|
453
|
-
|
|
454
411
|
.position-absolute {
|
|
455
412
|
position: absolute;
|
|
456
413
|
}
|
|
457
|
-
|
|
458
414
|
.cursor-pointer {
|
|
459
415
|
cursor: pointer;
|
|
460
416
|
}
|
|
461
|
-
|
|
462
417
|
.w-100 {
|
|
463
418
|
width: 100%;
|
|
464
419
|
}
|
|
465
|
-
|
|
466
420
|
.min-width-auto {
|
|
467
421
|
min-width: auto;
|
|
468
422
|
}
|
|
469
|
-
|
|
470
423
|
.disabled {
|
|
471
424
|
opacity: 0.5;
|
|
472
425
|
cursor: not-allowed;
|
|
473
426
|
pointer-events: none;
|
|
474
427
|
}
|
|
475
|
-
|
|
476
428
|
.overflow-auto {
|
|
477
429
|
overflow: auto;
|
|
478
430
|
}
|
|
479
|
-
|
|
480
431
|
.toggle-btn {
|
|
481
432
|
display: flex;
|
|
482
433
|
width: 100%;
|
|
@@ -541,8 +492,11 @@ a {
|
|
|
541
492
|
/* Couleurs : gris pour la barre, transparent pour le fond */
|
|
542
493
|
}
|
|
543
494
|
|
|
544
|
-
@media (min-width: 576px) {
|
|
495
|
+
@media (min-width: 576px) {
|
|
496
|
+
}
|
|
545
497
|
|
|
546
|
-
@media (min-width: 768px) {
|
|
498
|
+
@media (min-width: 768px) {
|
|
499
|
+
}
|
|
547
500
|
|
|
548
|
-
@media (min-width: 992px) {
|
|
501
|
+
@media (min-width: 992px) {
|
|
502
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -19,13 +19,13 @@ export { useIsMobile } from "./_core/hooks/useIsMobile";
|
|
|
19
19
|
export { useToken } from "./_core/hooks/useToken";
|
|
20
20
|
export { useValidate } from "./_core/hooks/useValidate";
|
|
21
21
|
export { WidgetSupport } from "./_core/hooks/widgetSupport";
|
|
22
|
+
|
|
22
23
|
export { ButtonAction } from "./action/ButtonAction";
|
|
23
|
-
export { AddressSearch } from "./addressSearch/AddressSearch";
|
|
24
|
-
export type { AddressSearchProps } from "./addressSearch/AddressSearch";
|
|
25
24
|
export { Badge } from "./badge/Badge";
|
|
26
25
|
export { Button } from "./button/Button";
|
|
27
26
|
export { ButtonActions } from "./button/buttonActions/ButtonActions";
|
|
28
27
|
export { ButtonFile } from "./button/buttonFile/ButtonFile";
|
|
28
|
+
export { ButtonFilters } from "./button/buttonFilters/ButtonFilters";
|
|
29
29
|
export { Card } from "./card/Card";
|
|
30
30
|
export { Carousel } from "./carousel/Carousel";
|
|
31
31
|
export { Damier } from "./damier/Damier";
|
|
@@ -35,21 +35,11 @@ export { Expands } from "./expands/Expands";
|
|
|
35
35
|
export { FilAriane } from "./filAriane/FilAriane";
|
|
36
36
|
export { DynamicForm } from "./form/Form";
|
|
37
37
|
export { TypeInputEnum } from "./form/form.enum";
|
|
38
|
-
export type { FormMode, FormSection } from "./form/form.interface";
|
|
39
38
|
export { Input } from "./form/input/Input";
|
|
40
39
|
export { InputNumber } from "./form/inputNumber/InputNumber";
|
|
41
40
|
export { InputPrice } from "./form/inputPrice/InputPrice";
|
|
42
41
|
export { TextArea } from "./form/textArea/TextArea";
|
|
43
42
|
export { Grid } from "./grid/Grid";
|
|
44
|
-
export {
|
|
45
|
-
GeocodingService,
|
|
46
|
-
geocodingService,
|
|
47
|
-
} from "./geocoding/GeocodingService";
|
|
48
|
-
export type {
|
|
49
|
-
GeocodedAddress,
|
|
50
|
-
GeocodingProvider,
|
|
51
|
-
GeocodingSearchOptions,
|
|
52
|
-
} from "./geocoding/geocoding.interface";
|
|
53
43
|
export { Header } from "./header/Header";
|
|
54
44
|
export { Icon } from "./icon/Icon";
|
|
55
45
|
export { IconSizeEnum } from "./icon/iconSize.enum";
|
package/src/menus/Menus.tsx
CHANGED
|
@@ -22,7 +22,6 @@ export const Menus = (props: ExpandProps) => {
|
|
|
22
22
|
<Menu
|
|
23
23
|
item={item}
|
|
24
24
|
onChange={onChange}
|
|
25
|
-
className={item.subMenu && item.subMenu.length > 0 ? "has-submenu" : ""}
|
|
26
25
|
active={currentItem?.id === item.id}
|
|
27
26
|
/>
|
|
28
27
|
{item.subMenu && item.subMenu.length > 0 && (
|
package/src/menus/menu/Menu.tsx
CHANGED
|
@@ -4,13 +4,12 @@ export type MenuProps = {
|
|
|
4
4
|
active: boolean;
|
|
5
5
|
item: MenuInterface;
|
|
6
6
|
onChange: (item: MenuInterface) => void;
|
|
7
|
-
className?: string;
|
|
8
7
|
};
|
|
9
8
|
export const Menu = (props: MenuProps): JSX.Element => {
|
|
10
9
|
return (
|
|
11
10
|
<div
|
|
12
11
|
onClick={() => props.onChange(props.item)}
|
|
13
|
-
className={
|
|
12
|
+
className={props.active ? "expand expand--active" : "expand"}
|
|
14
13
|
>
|
|
15
14
|
{props.item.children}
|
|
16
15
|
</div>
|
|
@@ -4,6 +4,7 @@ import React, {
|
|
|
4
4
|
useEffect,
|
|
5
5
|
useId,
|
|
6
6
|
useImperativeHandle,
|
|
7
|
+
useLayoutEffect,
|
|
7
8
|
useRef,
|
|
8
9
|
useState,
|
|
9
10
|
} from "react";
|
|
@@ -23,14 +24,16 @@ export type PositionOverlay =
|
|
|
23
24
|
| "bottomRight";
|
|
24
25
|
|
|
25
26
|
export type OverlayPanelProps = {
|
|
26
|
-
referenceElement?: HTMLElement;
|
|
27
|
+
referenceElement?: HTMLElement | HTMLTableElement;
|
|
27
28
|
coordonnees?: { top: number; left: number };
|
|
28
29
|
position?: PositionOverlay;
|
|
29
30
|
children: React.ReactNode;
|
|
30
|
-
className?: string;
|
|
31
31
|
show?: boolean;
|
|
32
32
|
id?: string;
|
|
33
|
+
className?: string;
|
|
33
34
|
closeOverlay?: (close: boolean) => void;
|
|
35
|
+
usePortal?: boolean;
|
|
36
|
+
matchReferenceWidth?: boolean;
|
|
34
37
|
};
|
|
35
38
|
|
|
36
39
|
export const OverlayPanel = forwardRef(
|
|
@@ -39,11 +42,13 @@ export const OverlayPanel = forwardRef(
|
|
|
39
42
|
referenceElement,
|
|
40
43
|
position,
|
|
41
44
|
coordonnees,
|
|
42
|
-
className,
|
|
43
45
|
children,
|
|
44
46
|
show,
|
|
47
|
+
className,
|
|
45
48
|
id,
|
|
46
49
|
closeOverlay,
|
|
50
|
+
usePortal = true,
|
|
51
|
+
matchReferenceWidth = false,
|
|
47
52
|
}: OverlayPanelProps,
|
|
48
53
|
ref: React.Ref<{
|
|
49
54
|
setCoords?: (coords: { top: number; left: number }) => void;
|
|
@@ -54,10 +59,16 @@ export const OverlayPanel = forwardRef(
|
|
|
54
59
|
const [coords, setCoords] = useState<{ top: number; left: number }>(
|
|
55
60
|
coordonnees ?? { top: 0, left: 0 },
|
|
56
61
|
);
|
|
62
|
+
const [referenceWidth, setReferenceWidth] = useState<number | undefined>();
|
|
63
|
+
// Masque l'overlay tant que sa position n'a pas été calculée (évite le flash en 0,0)
|
|
64
|
+
const [isPositioned, setIsPositioned] = useState(false);
|
|
57
65
|
const boxRef = useRef<HTMLDivElement>(null);
|
|
58
66
|
const overlayId = useId();
|
|
59
67
|
useImperativeHandle(ref, () => ({
|
|
60
|
-
setCoords
|
|
68
|
+
setCoords: (newCoords: { top: number; left: number }) => {
|
|
69
|
+
setCoords(newCoords);
|
|
70
|
+
setIsPositioned(true);
|
|
71
|
+
},
|
|
61
72
|
}));
|
|
62
73
|
|
|
63
74
|
useEffect(() => {
|
|
@@ -66,10 +77,11 @@ export const OverlayPanel = forwardRef(
|
|
|
66
77
|
}
|
|
67
78
|
}, [activeOverlayId, overlayId]);
|
|
68
79
|
|
|
69
|
-
|
|
80
|
+
useLayoutEffect(() => {
|
|
70
81
|
const updatePosition = () => {
|
|
71
82
|
if (!position && coordonnees) {
|
|
72
83
|
setCoords(coordonnees);
|
|
84
|
+
setIsPositioned(true);
|
|
73
85
|
} else if (referenceElement) {
|
|
74
86
|
const rect = referenceElement.getBoundingClientRect();
|
|
75
87
|
const boxRect = boxRef.current?.getBoundingClientRect();
|
|
@@ -108,6 +120,14 @@ export const OverlayPanel = forwardRef(
|
|
|
108
120
|
if (position && positions[position]) {
|
|
109
121
|
// Si une position est définie, on tente de l'appliquer
|
|
110
122
|
({ top, left } = positions[position]());
|
|
123
|
+
// Manque d'espace en bas → afficher au-dessus de l'élément
|
|
124
|
+
if (
|
|
125
|
+
(position === "bottomLeft" || position === "bottomRight") &&
|
|
126
|
+
top + boxRect.height > innerHeight &&
|
|
127
|
+
rect.top - boxRect.height >= 0
|
|
128
|
+
) {
|
|
129
|
+
top = rect.top - boxRect.height;
|
|
130
|
+
}
|
|
111
131
|
} else {
|
|
112
132
|
// Sinon, on adapte dynamiquement
|
|
113
133
|
left = rect.right;
|
|
@@ -122,18 +142,35 @@ export const OverlayPanel = forwardRef(
|
|
|
122
142
|
}
|
|
123
143
|
}
|
|
124
144
|
|
|
125
|
-
|
|
145
|
+
// Coordonnées viewport → coordonnées document (position absolute dans le body)
|
|
146
|
+
setCoords({
|
|
147
|
+
top: top + window.scrollY,
|
|
148
|
+
left: (left < 0 ? 0 : left) + window.scrollX,
|
|
149
|
+
});
|
|
150
|
+
if (matchReferenceWidth) {
|
|
151
|
+
setReferenceWidth(rect.width);
|
|
152
|
+
}
|
|
153
|
+
setIsPositioned(true);
|
|
126
154
|
}
|
|
127
155
|
}
|
|
128
156
|
};
|
|
129
157
|
|
|
158
|
+
if (!isShow) {
|
|
159
|
+
setIsPositioned(false);
|
|
160
|
+
}
|
|
161
|
+
|
|
130
162
|
if (isShow) {
|
|
131
163
|
updatePosition();
|
|
132
164
|
window.addEventListener("resize", updatePosition);
|
|
165
|
+
// capture : suit aussi le scroll des conteneurs (ex. contenu d'une modale)
|
|
166
|
+
window.addEventListener("scroll", updatePosition, true);
|
|
133
167
|
}
|
|
134
168
|
|
|
135
|
-
return () =>
|
|
136
|
-
|
|
169
|
+
return () => {
|
|
170
|
+
window.removeEventListener("resize", updatePosition);
|
|
171
|
+
window.removeEventListener("scroll", updatePosition, true);
|
|
172
|
+
};
|
|
173
|
+
}, [referenceElement, isShow, position, matchReferenceWidth]);
|
|
137
174
|
|
|
138
175
|
const openOverlay = () => {
|
|
139
176
|
setIsShow(true);
|
|
@@ -154,18 +191,24 @@ export const OverlayPanel = forwardRef(
|
|
|
154
191
|
useEffect(() => {
|
|
155
192
|
const handleClickOutside = (event: MouseEvent) => {
|
|
156
193
|
if (boxRef.current && !boxRef.current.contains(event.target as Node)) {
|
|
157
|
-
|
|
194
|
+
// Pas de stopPropagation ici : le clic doit continuer vers sa cible
|
|
195
|
+
setIsShow(false);
|
|
196
|
+
setActiveOverlay(null);
|
|
197
|
+
if (closeOverlay) {
|
|
198
|
+
closeOverlay(false);
|
|
199
|
+
}
|
|
158
200
|
}
|
|
159
201
|
};
|
|
160
202
|
|
|
161
203
|
if (isShow) {
|
|
162
|
-
|
|
204
|
+
// Phase de capture : fonctionne même si un parent (ex. Modal) stoppe la propagation
|
|
205
|
+
document.addEventListener("mousedown", handleClickOutside, true);
|
|
163
206
|
}
|
|
164
207
|
|
|
165
208
|
return () => {
|
|
166
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
209
|
+
document.removeEventListener("mousedown", handleClickOutside, true);
|
|
167
210
|
};
|
|
168
|
-
}, [isShow,
|
|
211
|
+
}, [isShow, closeOverlay, setActiveOverlay]);
|
|
169
212
|
useEffect(() => {
|
|
170
213
|
if (show) {
|
|
171
214
|
openOverlay();
|
|
@@ -174,15 +217,16 @@ export const OverlayPanel = forwardRef(
|
|
|
174
217
|
|
|
175
218
|
if (!isShow) return null;
|
|
176
219
|
|
|
177
|
-
|
|
220
|
+
const overlayContent = (
|
|
178
221
|
<OverlayPanelStyled
|
|
179
|
-
className={className}
|
|
180
222
|
ref={boxRef}
|
|
181
223
|
$top={coords.top}
|
|
182
224
|
$left={coords.left}
|
|
225
|
+
$minWidth={referenceWidth}
|
|
226
|
+
$visible={isPositioned}
|
|
183
227
|
>
|
|
184
228
|
<div
|
|
185
|
-
className={`overlayPanel ${
|
|
229
|
+
className={`overlayPanel ${className ? className : ""} ${
|
|
186
230
|
coords.top > 0 || coords.left > 0 ? "visible" : "hide"
|
|
187
231
|
}`}
|
|
188
232
|
>
|
|
@@ -193,10 +237,19 @@ export const OverlayPanel = forwardRef(
|
|
|
193
237
|
>
|
|
194
238
|
<Icon classIcon="bi-x-lg" />
|
|
195
239
|
</button>
|
|
196
|
-
{children}
|
|
240
|
+
<div onClick={(e) => e.stopPropagation()}>{children}</div>
|
|
197
241
|
</div>
|
|
198
|
-
</OverlayPanelStyled
|
|
199
|
-
document.body,
|
|
242
|
+
</OverlayPanelStyled>
|
|
200
243
|
);
|
|
244
|
+
|
|
245
|
+
if (!usePortal) {
|
|
246
|
+
return (
|
|
247
|
+
<div className={`overlayPanel overlayPanel--no-portal `} ref={boxRef}>
|
|
248
|
+
<div onClick={(e) => e.stopPropagation()}>{children}</div>
|
|
249
|
+
</div>
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return ReactDOM.createPortal(overlayContent, document.body);
|
|
201
254
|
},
|
|
202
255
|
);
|
|
@@ -7,6 +7,11 @@ interface OverlayContextType {
|
|
|
7
7
|
|
|
8
8
|
const OverlayContext = createContext<OverlayContextType | undefined>(undefined);
|
|
9
9
|
|
|
10
|
+
const defaultOverlayContext: OverlayContextType = {
|
|
11
|
+
activeOverlayId: null,
|
|
12
|
+
setActiveOverlay: () => {},
|
|
13
|
+
};
|
|
14
|
+
|
|
10
15
|
export const OverlayProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
11
16
|
children,
|
|
12
17
|
}) => {
|
|
@@ -21,8 +26,5 @@ export const OverlayProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
|
21
26
|
|
|
22
27
|
export const useOverlayContext = () => {
|
|
23
28
|
const context = useContext(OverlayContext);
|
|
24
|
-
|
|
25
|
-
throw new Error("useOverlayContext must be used within an OverlayProvider");
|
|
26
|
-
}
|
|
27
|
-
return context;
|
|
29
|
+
return context ?? defaultOverlayContext;
|
|
28
30
|
};
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
.overlayPanel {
|
|
2
2
|
position: relative;
|
|
3
3
|
|
|
4
|
+
&.overlayPanel--no-portal {
|
|
5
|
+
position: absolute;
|
|
6
|
+
z-index: 14 !important;
|
|
7
|
+
width: 100%;
|
|
8
|
+
}
|
|
9
|
+
|
|
4
10
|
&.hide {
|
|
5
11
|
visibility: hidden;
|
|
6
12
|
}
|
|
13
|
+
|
|
7
14
|
&.visible {
|
|
8
15
|
visibility: visible !important;
|
|
9
16
|
}
|
|
17
|
+
|
|
10
18
|
button {
|
|
11
19
|
span {
|
|
12
20
|
text-align: left;
|
|
13
21
|
}
|
|
14
22
|
}
|
|
23
|
+
|
|
15
24
|
.toggle-btn {
|
|
16
25
|
display: flex;
|
|
17
26
|
justify-content: flex-end;
|
|
@@ -32,4 +41,4 @@
|
|
|
32
41
|
font-size: 1rem;
|
|
33
42
|
}
|
|
34
43
|
}
|
|
35
|
-
}
|
|
44
|
+
}
|
|
@@ -3,16 +3,21 @@ import styled from "styled-components";
|
|
|
3
3
|
interface OverlayPanelStyledProps {
|
|
4
4
|
$top?: number;
|
|
5
5
|
$left?: number;
|
|
6
|
+
$minWidth?: number;
|
|
7
|
+
$visible?: boolean;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
export const OverlayPanelStyled = styled.div<OverlayPanelStyledProps>`
|
|
9
11
|
position: absolute;
|
|
10
|
-
z-index:
|
|
12
|
+
z-index: 1050;
|
|
11
13
|
top: ${({ $top }) => $top}px;
|
|
12
14
|
left: ${({ $left }) => $left}px;
|
|
15
|
+
${({ $minWidth }) => ($minWidth ? `min-width: ${$minWidth}px;` : "")}
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
visibility: ${({ $visible }) => ($visible ? "visible" : "hidden")};
|
|
13
18
|
background-color: white;
|
|
14
19
|
padding: 10px;
|
|
15
20
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
16
|
-
border-radius:
|
|
21
|
+
border-radius: 2px;
|
|
17
22
|
border: 1px solid #ede;
|
|
18
23
|
`;
|