@zauru-sdk/components 1.0.112 → 1.0.114
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/CHANGELOG.md +16 -0
- package/dist/Form/ReactZodForm/index.d.ts +1 -0
- package/dist/HOC/ValidateEmployeeAccess/index.d.ts +5 -0
- package/dist/Layouts/errorLayout/index.d.ts +1 -0
- package/dist/Layouts/index.d.ts +1 -0
- package/dist/SidePanel/index.d.ts +21 -0
- package/dist/cjs/Buttons/Button.js +7 -7
- package/dist/cjs/Form/DatePicker/index.js +1 -1
- package/dist/cjs/Form/ReactZodForm/index.js +2 -4
- package/dist/cjs/Form/SelectField/index.js +29 -12
- package/dist/cjs/Form/TextField/index.js +10 -16
- package/dist/cjs/Form/TimePicker/index.js +1 -1
- package/dist/cjs/HOC/ValidateEmployeeAccess/index.js +17 -0
- package/dist/cjs/Layouts/errorLayout/index.js +14 -0
- package/dist/cjs/Layouts/index.js +1 -0
- package/dist/cjs/SidePanel/index.js +48 -0
- package/dist/cjs/index.js +2 -0
- package/dist/esm/Buttons/Button.js +7 -7
- package/dist/esm/Form/DatePicker/index.js +2 -2
- package/dist/esm/Form/ReactZodForm/index.js +2 -4
- package/dist/esm/Form/SelectField/index.js +30 -13
- package/dist/esm/Form/TextField/index.js +10 -16
- package/dist/esm/Form/TimePicker/index.js +1 -1
- package/dist/esm/HOC/ValidateEmployeeAccess/index.js +13 -0
- package/dist/esm/Layouts/errorLayout/index.js +10 -0
- package/dist/esm/Layouts/index.js +1 -0
- package/dist/esm/SidePanel/index.js +46 -0
- package/dist/esm/index.js +2 -0
- package/dist/index.d.ts +2 -0
- package/package.json +4 -4
- package/src/Buttons/Button.tsx +29 -28
- package/src/Form/DatePicker/index.tsx +2 -2
- package/src/Form/ReactZodForm/index.tsx +4 -2
- package/src/Form/SelectField/index.tsx +54 -36
- package/src/Form/TextField/index.tsx +14 -17
- package/src/Form/TimePicker/index.tsx +1 -1
- package/src/HOC/ValidateEmployeeAccess/index.tsx +51 -0
- package/src/Layouts/errorLayout/index.tsx +47 -0
- package/src/Layouts/index.ts +1 -0
- package/src/SidePanel/index.tsx +153 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import React, { useState, ReactNode, useEffect, useRef } from "react";
|
|
2
|
+
import { motion, AnimatePresence } from "framer-motion";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SidePanel Component
|
|
6
|
+
*
|
|
7
|
+
* This component creates a collapsible side panel that can be toggled open and closed.
|
|
8
|
+
*
|
|
9
|
+
* @param {ReactNode} children - The content to be displayed inside the side panel.
|
|
10
|
+
* @param {boolean} [closeOnClickOutside=true] - If true, the panel will close when clicking outside of it.
|
|
11
|
+
* @param {number} [widthPercentage=25] - The width of the panel as a percentage of the viewport width.
|
|
12
|
+
* @param {string} [buttonIcon="chevron"] - The icon to use for the toggle button. Can be "chevron", "filter", or a custom ReactNode.
|
|
13
|
+
*
|
|
14
|
+
* @returns A toggleable side panel component.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
interface SidePanelProps {
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
closeOnClickOutside?: boolean;
|
|
20
|
+
widthPercentage?: number;
|
|
21
|
+
buttonIcon?: "chevron" | "filter" | ReactNode;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// SVG icon for the left-pointing chevron
|
|
25
|
+
const ChevronLeftIcon = () => (
|
|
26
|
+
<svg
|
|
27
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
28
|
+
viewBox="0 0 24 24"
|
|
29
|
+
fill="currentColor"
|
|
30
|
+
className="h-6 w-6"
|
|
31
|
+
>
|
|
32
|
+
<path
|
|
33
|
+
fillRule="evenodd"
|
|
34
|
+
d="M7.72 12.53a.75.75 0 010-1.06l7.5-7.5a.75.75 0 111.06 1.06L9.31 12l6.97 6.97a.75.75 0 11-1.06 1.06l-7.5-7.5z"
|
|
35
|
+
clipRule="evenodd"
|
|
36
|
+
/>
|
|
37
|
+
</svg>
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// SVG icon for the right-pointing chevron
|
|
41
|
+
const ChevronRightIcon = () => (
|
|
42
|
+
<svg
|
|
43
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
44
|
+
viewBox="0 0 24 24"
|
|
45
|
+
fill="currentColor"
|
|
46
|
+
className="h-6 w-6"
|
|
47
|
+
>
|
|
48
|
+
<path
|
|
49
|
+
fillRule="evenodd"
|
|
50
|
+
d="M16.28 11.47a.75.75 0 010 1.06l-7.5 7.5a.75.75 0 01-1.06-1.06L14.69 12 7.72 5.03a.75.75 0 011.06-1.06l7.5 7.5z"
|
|
51
|
+
clipRule="evenodd"
|
|
52
|
+
/>
|
|
53
|
+
</svg>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// SVG icon for the filter (bars filter icon)
|
|
57
|
+
const FilterIcon = () => (
|
|
58
|
+
<svg
|
|
59
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
60
|
+
viewBox="0 0 24 24"
|
|
61
|
+
fill="currentColor"
|
|
62
|
+
className="h-6 w-6"
|
|
63
|
+
>
|
|
64
|
+
<path
|
|
65
|
+
fillRule="evenodd"
|
|
66
|
+
d="M3 6a1 1 0 011-1h16a1 1 0 110 2H4a1 1 0 01-1-1zm0 6a1 1 0 011-1h10a1 1 0 110 2H4a1 1 0 01-1-1zm0 6a1 1 0 011-1h4a1 1 0 110 2H4a1 1 0 01-1-1z"
|
|
67
|
+
clipRule="evenodd"
|
|
68
|
+
/>
|
|
69
|
+
</svg>
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const SidePanel: React.FC<SidePanelProps> = ({
|
|
73
|
+
children,
|
|
74
|
+
closeOnClickOutside = true,
|
|
75
|
+
widthPercentage = 25,
|
|
76
|
+
buttonIcon = "chevron",
|
|
77
|
+
}) => {
|
|
78
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
79
|
+
const panelRef = useRef<HTMLDivElement>(null);
|
|
80
|
+
|
|
81
|
+
const togglePanel = () => {
|
|
82
|
+
setIsOpen(!isOpen);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
87
|
+
if (
|
|
88
|
+
closeOnClickOutside &&
|
|
89
|
+
panelRef.current &&
|
|
90
|
+
!panelRef.current.contains(event.target as Node)
|
|
91
|
+
) {
|
|
92
|
+
setIsOpen(false);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
97
|
+
return () => {
|
|
98
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
99
|
+
};
|
|
100
|
+
}, [closeOnClickOutside]);
|
|
101
|
+
|
|
102
|
+
const renderIcon = () => {
|
|
103
|
+
if (typeof buttonIcon === "string") {
|
|
104
|
+
switch (buttonIcon) {
|
|
105
|
+
case "chevron":
|
|
106
|
+
return isOpen ? <ChevronRightIcon /> : <ChevronLeftIcon />;
|
|
107
|
+
case "filter":
|
|
108
|
+
return <FilterIcon />;
|
|
109
|
+
default:
|
|
110
|
+
return <ChevronLeftIcon />;
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
return buttonIcon;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<>
|
|
119
|
+
<AnimatePresence>
|
|
120
|
+
{isOpen && (
|
|
121
|
+
<motion.div
|
|
122
|
+
ref={panelRef}
|
|
123
|
+
initial={{ x: "100%" }}
|
|
124
|
+
animate={{ x: 0 }}
|
|
125
|
+
exit={{ x: "100%" }}
|
|
126
|
+
transition={{ type: "spring", stiffness: 300, damping: 30 }}
|
|
127
|
+
className="fixed top-0 right-0 h-full bg-white shadow-lg z-[9999] overflow-y-auto"
|
|
128
|
+
style={{ width: `${widthPercentage}%` }}
|
|
129
|
+
>
|
|
130
|
+
<button
|
|
131
|
+
onClick={togglePanel}
|
|
132
|
+
className="absolute top-4 left-4 p-2 rounded-full bg-gray-200 hover:bg-gray-300 transition-colors"
|
|
133
|
+
>
|
|
134
|
+
<ChevronRightIcon />
|
|
135
|
+
</button>
|
|
136
|
+
<div className="p-6 mt-16">{children}</div>
|
|
137
|
+
</motion.div>
|
|
138
|
+
)}
|
|
139
|
+
</AnimatePresence>
|
|
140
|
+
|
|
141
|
+
{!isOpen && (
|
|
142
|
+
<button
|
|
143
|
+
onClick={togglePanel}
|
|
144
|
+
className="fixed top-1/2 right-0 transform -translate-y-1/2 bg-indigo-600 text-white p-3 rounded-l-lg shadow-md hover:bg-indigo-700 transition-colors z-[10000]"
|
|
145
|
+
>
|
|
146
|
+
{renderIcon()}
|
|
147
|
+
</button>
|
|
148
|
+
)}
|
|
149
|
+
</>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export default SidePanel;
|
package/src/index.ts
CHANGED