kelt-ui-kit-react 0.1.9 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/card/Card.d.ts +0 -8
- package/dist/card/cardAction/CardAction.d.ts +8 -0
- package/dist/card/cardAction.interface.d.ts +1 -0
- package/dist/card/hook/useCardInteractions.d.ts +8 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1201 -1146
- package/dist/menus/menu/menu.interface.d.ts +1 -0
- package/dist/modal/Modal.d.ts +10 -0
- package/dist/modal/Modal.view.d.ts +1 -0
- package/dist/overlayPanel/overlay.context.d.ts +11 -0
- package/dist/sidebar/Sidebar.d.ts +4 -3
- package/dist/sidebarData/SidebarData.d.ts +3 -7
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/App.menu.tsx +8 -0
- package/src/App.tsx +12 -9
- package/src/card/Card.tsx +22 -53
- package/src/card/Card.view.tsx +3 -4
- package/src/card/card.css +56 -12
- package/src/card/cardAction/CardAction.tsx +72 -0
- package/src/card/cardAction/cardAction.css +7 -0
- package/src/card/cardAction.interface.tsx +1 -0
- package/src/card/hook/useCardInteractions.tsx +30 -0
- package/src/index.css +15 -1
- package/src/index.ts +2 -0
- package/src/menus/menu/menu.interface.tsx +1 -0
- package/src/modal/Modal.tsx +34 -0
- package/src/modal/Modal.view.tsx +19 -0
- package/src/modal/modal.css +63 -0
- package/src/overlayPanel/OverlayPanel.tsx +52 -48
- package/src/overlayPanel/OverlayPanel.view.tsx +3 -2
- package/src/overlayPanel/overlay.context.tsx +28 -0
- package/src/quantity/Quantity.tsx +3 -0
- package/src/quantity/quantity.css +5 -0
- package/src/sidebar/Sidebar.tsx +7 -2
- package/src/sidebarData/SidebarData.tsx +7 -23
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
1
|
+
import React, { useCallback, useEffect, useId, useRef, useState } from "react";
|
|
2
2
|
import ReactDOM from "react-dom";
|
|
3
|
+
|
|
3
4
|
import { Icon } from "../icon/Icon";
|
|
5
|
+
import { useOverlayContext } from "./overlay.context";
|
|
4
6
|
import "./overlayPanel.css";
|
|
5
7
|
import { OverlayPanelStyled } from "./overlayPanelStyled/overlayPanelStyled";
|
|
8
|
+
|
|
6
9
|
type Position =
|
|
7
10
|
| "left"
|
|
8
11
|
| "right"
|
|
@@ -12,8 +15,8 @@ type Position =
|
|
|
12
15
|
| "bottomRight";
|
|
13
16
|
|
|
14
17
|
interface OverlayPanelProps {
|
|
15
|
-
referenceElement: HTMLElement;
|
|
16
|
-
position?: Position;
|
|
18
|
+
referenceElement: HTMLElement;
|
|
19
|
+
position?: Position;
|
|
17
20
|
children: React.ReactNode;
|
|
18
21
|
show?: boolean;
|
|
19
22
|
closeOverlay?: (close: boolean) => void;
|
|
@@ -26,57 +29,44 @@ export const OverlayPanel = ({
|
|
|
26
29
|
show,
|
|
27
30
|
closeOverlay,
|
|
28
31
|
}: OverlayPanelProps) => {
|
|
32
|
+
const { activeOverlayId, setActiveOverlay } = useOverlayContext();
|
|
29
33
|
const [isShow, setIsShow] = useState(show || false);
|
|
30
34
|
const [coords, setCoords] = useState({ top: 0, left: 0 });
|
|
31
35
|
const boxRef = useRef<HTMLDivElement>(null);
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
top: rect.top - boxRect.height,
|
|
41
|
-
left: rect.left,
|
|
42
|
-
};
|
|
43
|
-
};
|
|
44
|
-
const getCoordBottomRight = (rect: DOMRect, panelRect: DOMRect) => {
|
|
45
|
-
return {
|
|
46
|
-
top: rect.bottom,
|
|
47
|
-
left: rect.right - panelRect.width,
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
const getCoordBottomLeft = (rect: DOMRect) => {
|
|
51
|
-
return {
|
|
52
|
-
top: rect.bottom,
|
|
53
|
-
left: rect.left,
|
|
54
|
-
};
|
|
55
|
-
};
|
|
56
|
-
const getCoordLeft = (rect: DOMRect, boxRect: DOMRect) => {
|
|
57
|
-
return {
|
|
58
|
-
top: rect.top + rect.height / 2 - boxRect.height / 2,
|
|
59
|
-
left: rect.left - boxRect.width,
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
const getCoordRight = (rect: DOMRect, boxRect: DOMRect) => {
|
|
63
|
-
return {
|
|
64
|
-
top: rect.top + rect.height / 2 - boxRect.height / 2,
|
|
65
|
-
left: rect.right,
|
|
66
|
-
};
|
|
67
|
-
};
|
|
36
|
+
const overlayId = useId();
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (activeOverlayId !== overlayId) {
|
|
39
|
+
setIsShow(false);
|
|
40
|
+
}
|
|
41
|
+
}, [activeOverlayId, overlayId]);
|
|
42
|
+
|
|
68
43
|
useEffect(() => {
|
|
69
44
|
const updatePosition = () => {
|
|
70
45
|
const rect = referenceElement.getBoundingClientRect();
|
|
71
46
|
const boxRect = boxRef.current?.getBoundingClientRect();
|
|
72
47
|
if (boxRect) {
|
|
73
48
|
const coords = {
|
|
74
|
-
topRight:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
49
|
+
topRight: (r: DOMRect, b: DOMRect) => ({
|
|
50
|
+
top: r.top - b.height,
|
|
51
|
+
left: r.right - b.width,
|
|
52
|
+
}),
|
|
53
|
+
topLeft: (r: DOMRect, b: DOMRect) => ({
|
|
54
|
+
top: r.top - b.height,
|
|
55
|
+
left: r.left,
|
|
56
|
+
}),
|
|
57
|
+
bottomRight: (r: DOMRect, b: DOMRect) => ({
|
|
58
|
+
top: r.bottom,
|
|
59
|
+
left: r.right - b.width,
|
|
60
|
+
}),
|
|
61
|
+
bottomLeft: (r: DOMRect) => ({ top: r.bottom, left: r.left }),
|
|
62
|
+
left: (r: DOMRect, b: DOMRect) => ({
|
|
63
|
+
top: r.top + r.height / 2 - b.height / 2,
|
|
64
|
+
left: r.left - b.width,
|
|
65
|
+
}),
|
|
66
|
+
right: (r: DOMRect, b: DOMRect) => ({
|
|
67
|
+
top: r.top + r.height / 2 - b.height / 2,
|
|
68
|
+
left: r.right,
|
|
69
|
+
}),
|
|
80
70
|
};
|
|
81
71
|
const { top, left } = coords[position ?? "topLeft"](rect, boxRect);
|
|
82
72
|
setCoords({ top, left });
|
|
@@ -87,18 +77,32 @@ export const OverlayPanel = ({
|
|
|
87
77
|
window.addEventListener("resize", updatePosition);
|
|
88
78
|
return () => window.removeEventListener("resize", updatePosition);
|
|
89
79
|
}, [referenceElement, position]);
|
|
90
|
-
|
|
80
|
+
|
|
81
|
+
const openOverlay = () => {
|
|
82
|
+
setIsShow(true);
|
|
83
|
+
setActiveOverlay(overlayId);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const closeOverlayHandler = useCallback(() => {
|
|
91
87
|
setIsShow(false);
|
|
88
|
+
setActiveOverlay(null);
|
|
92
89
|
if (closeOverlay) {
|
|
93
90
|
closeOverlay(false);
|
|
94
91
|
}
|
|
95
|
-
}, [
|
|
92
|
+
}, [closeOverlay, setActiveOverlay]);
|
|
93
|
+
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (show) {
|
|
96
|
+
openOverlay();
|
|
97
|
+
}
|
|
98
|
+
}, [show]);
|
|
96
99
|
|
|
97
100
|
if (!isShow) return null;
|
|
101
|
+
|
|
98
102
|
return ReactDOM.createPortal(
|
|
99
103
|
<OverlayPanelStyled ref={boxRef} $top={coords.top} $left={coords.left}>
|
|
100
104
|
<div className="overlayPanel">
|
|
101
|
-
<button className="toggle-btn" onClick={
|
|
105
|
+
<button className="toggle-btn" onClick={closeOverlayHandler}>
|
|
102
106
|
<Icon classIcon="bi-x-lg" />
|
|
103
107
|
</button>
|
|
104
108
|
{children}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { useRef, useState } from "react";
|
|
2
|
-
import { OverlayPanel } from "./OverlayPanel";
|
|
3
2
|
import { Icon } from "../icon/Icon";
|
|
3
|
+
import { OverlayPanel } from "./OverlayPanel";
|
|
4
4
|
|
|
5
5
|
export const OverlayPanelView = () => {
|
|
6
6
|
const refButton = useRef<HTMLDivElement>(null);
|
|
7
7
|
const [openOverlay, setOpenOverlay] = useState(false);
|
|
8
|
+
|
|
8
9
|
return (
|
|
9
10
|
<>
|
|
10
11
|
<div ref={refButton} onClick={() => setOpenOverlay(!openOverlay)}>
|
|
11
12
|
<Icon classIcon="bi-list" />
|
|
12
13
|
</div>
|
|
13
|
-
{
|
|
14
|
+
{refButton.current && (
|
|
14
15
|
<OverlayPanel
|
|
15
16
|
position="bottomRight"
|
|
16
17
|
show={openOverlay}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React, { createContext, useContext, useState } from "react";
|
|
2
|
+
|
|
3
|
+
interface OverlayContextType {
|
|
4
|
+
activeOverlayId: string | null;
|
|
5
|
+
setActiveOverlay: (id: string | null) => void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const OverlayContext = createContext<OverlayContextType | undefined>(undefined);
|
|
9
|
+
|
|
10
|
+
export const OverlayProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
11
|
+
children,
|
|
12
|
+
}) => {
|
|
13
|
+
const [activeOverlayId, setActiveOverlay] = useState<string | null>(null);
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<OverlayContext.Provider value={{ activeOverlayId, setActiveOverlay }}>
|
|
17
|
+
{children}
|
|
18
|
+
</OverlayContext.Provider>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const useOverlayContext = () => {
|
|
23
|
+
const context = useContext(OverlayContext);
|
|
24
|
+
if (!context) {
|
|
25
|
+
throw new Error("useOverlayContext must be used within an OverlayProvider");
|
|
26
|
+
}
|
|
27
|
+
return context;
|
|
28
|
+
};
|
|
@@ -29,6 +29,9 @@ export const Quantity = ({ setQuantity, item }: QuantityProps) => {
|
|
|
29
29
|
const decrementQte = useCallback(
|
|
30
30
|
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
31
31
|
e.stopPropagation();
|
|
32
|
+
if (qte === 0) {
|
|
33
|
+
return qte;
|
|
34
|
+
}
|
|
32
35
|
changeQuantity(qte - 1);
|
|
33
36
|
},
|
|
34
37
|
[changeQuantity, qte]
|
package/src/sidebar/Sidebar.tsx
CHANGED
|
@@ -3,13 +3,15 @@ import ReactDOM from "react-dom";
|
|
|
3
3
|
import { Icon } from "../icon/Icon";
|
|
4
4
|
import "./sidebar.css";
|
|
5
5
|
|
|
6
|
-
interface SidebarProps {
|
|
6
|
+
export interface SidebarProps {
|
|
7
7
|
id?: string;
|
|
8
8
|
open?: boolean;
|
|
9
9
|
title?: string;
|
|
10
10
|
children?: React.ReactNode;
|
|
11
11
|
className?: string;
|
|
12
12
|
width?: string;
|
|
13
|
+
displayOverlay?: boolean;
|
|
14
|
+
closeOnClickOutside?: boolean;
|
|
13
15
|
onClose?: (close: boolean) => void;
|
|
14
16
|
}
|
|
15
17
|
|
|
@@ -21,6 +23,8 @@ export const Sidebar = ({
|
|
|
21
23
|
className,
|
|
22
24
|
id,
|
|
23
25
|
width,
|
|
26
|
+
closeOnClickOutside = true,
|
|
27
|
+
displayOverlay = true,
|
|
24
28
|
}: SidebarProps): JSX.Element => {
|
|
25
29
|
const [isOpen, setIsOpen] = useState(open || false);
|
|
26
30
|
const sidebarRef = useRef<HTMLDivElement | null>(null);
|
|
@@ -57,6 +61,7 @@ export const Sidebar = ({
|
|
|
57
61
|
|
|
58
62
|
const handleClickOutside = useCallback(
|
|
59
63
|
(event: MouseEvent) => {
|
|
64
|
+
if (!closeOnClickOutside) return;
|
|
60
65
|
if (
|
|
61
66
|
sidebarRef.current &&
|
|
62
67
|
!sidebarRef.current.contains(event.target as Node)
|
|
@@ -80,7 +85,7 @@ export const Sidebar = ({
|
|
|
80
85
|
|
|
81
86
|
return ReactDOM.createPortal(
|
|
82
87
|
<>
|
|
83
|
-
{isOpen && <div className="overlay"></div>}
|
|
88
|
+
{isOpen && displayOverlay && <div className="overlay"></div>}
|
|
84
89
|
<div
|
|
85
90
|
ref={sidebarRef}
|
|
86
91
|
style={width ? { width: width } : {}}
|
|
@@ -1,33 +1,17 @@
|
|
|
1
|
-
import { Sidebar } from "../sidebar/Sidebar";
|
|
1
|
+
import { Sidebar, SidebarProps } from "../sidebar/Sidebar";
|
|
2
2
|
import "./sidebarData.css";
|
|
3
3
|
|
|
4
|
-
interface SidebarDataProps {
|
|
5
|
-
open?: boolean;
|
|
6
|
-
title?: string;
|
|
7
|
-
width?: string;
|
|
8
|
-
className?: string;
|
|
4
|
+
interface SidebarDataProps extends SidebarProps {
|
|
9
5
|
children?: React.ReactNode;
|
|
10
|
-
onClose?: (close: boolean) => void;
|
|
11
6
|
}
|
|
12
7
|
|
|
13
|
-
export const SidebarData = ({
|
|
14
|
-
open,
|
|
15
|
-
children,
|
|
16
|
-
title,
|
|
17
|
-
onClose,
|
|
18
|
-
width,
|
|
19
|
-
className,
|
|
20
|
-
}: SidebarDataProps) => {
|
|
8
|
+
export const SidebarData = (props: SidebarDataProps) => {
|
|
21
9
|
return (
|
|
22
10
|
<>
|
|
23
|
-
<Sidebar
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
width={width}
|
|
28
|
-
className={`full sidebar-data ${className}`}
|
|
29
|
-
>
|
|
30
|
-
{children && <div className="sidebar-data-content">{children}</div>}
|
|
11
|
+
<Sidebar {...props} className={`full sidebar-data ${props.className}`}>
|
|
12
|
+
{props.children && (
|
|
13
|
+
<div className="sidebar-data-content">{props.children}</div>
|
|
14
|
+
)}
|
|
31
15
|
</Sidebar>
|
|
32
16
|
</>
|
|
33
17
|
);
|