ml-ui-lib 1.0.24 → 1.0.26
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/components/Button/Button.d.ts +5 -1
- package/dist/components/Button/Button.js +7 -2
- package/dist/components/Navbar/Navbar.css +129 -26
- package/dist/components/Navbar/Navbar.d.ts +6 -0
- package/dist/components/Navbar/Navbar.js +59 -12
- package/dist/components/SlidingPanel/SlidingPanel.css +3 -2
- package/package.json +1 -1
|
@@ -2,8 +2,12 @@ import React from "react";
|
|
|
2
2
|
import "./Button.css";
|
|
3
3
|
export interface ButtonProps {
|
|
4
4
|
label: string;
|
|
5
|
-
variant?: "default" | "white" | "red" | "black" | "
|
|
5
|
+
variant?: "default" | "white" | "red" | "black" | "transparent-white";
|
|
6
6
|
onClick?: () => void;
|
|
7
7
|
disabled?: boolean;
|
|
8
|
+
/** Optional custom colors */
|
|
9
|
+
bgColor?: string;
|
|
10
|
+
textColor?: string;
|
|
11
|
+
borderColor?: string;
|
|
8
12
|
}
|
|
9
13
|
export declare const Button: React.FC<ButtonProps>;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import "./Button.css";
|
|
3
|
-
export const Button = ({ label, variant = "default", onClick, disabled = false }) => {
|
|
4
|
-
|
|
3
|
+
export const Button = ({ label, variant = "default", onClick, disabled = false, bgColor, textColor, borderColor }) => {
|
|
4
|
+
const customStyle = {
|
|
5
|
+
background: bgColor,
|
|
6
|
+
color: textColor,
|
|
7
|
+
border: borderColor ? `1px solid ${borderColor}` : undefined
|
|
8
|
+
};
|
|
9
|
+
return (_jsx("button", { className: `btn btn-${variant}`, onClick: onClick, disabled: disabled, style: customStyle, children: label }));
|
|
5
10
|
};
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/* -------------------------
|
|
2
|
+
Navbar Base
|
|
3
|
+
------------------------- */
|
|
1
4
|
.navbar {
|
|
2
5
|
background: #fff;
|
|
3
6
|
border-bottom: 1px solid #eee;
|
|
@@ -18,17 +21,70 @@
|
|
|
18
21
|
max-height: 50px;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
/* -------------------------
|
|
25
|
+
Nav Items
|
|
26
|
+
------------------------- */
|
|
22
27
|
.nav-items {
|
|
23
28
|
display: flex;
|
|
24
|
-
overflow:
|
|
29
|
+
overflow: none;
|
|
25
30
|
gap: 1.5rem;
|
|
26
31
|
}
|
|
27
32
|
|
|
33
|
+
.navbar-item {
|
|
34
|
+
position: relative;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.navbar-item.has-dropdown>.navbar-link {
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Dropdown menu */
|
|
42
|
+
.navbar-dropdown {
|
|
43
|
+
/* hidden by default */
|
|
44
|
+
display: none;
|
|
45
|
+
padding: 20px 25px 10px 10px;
|
|
46
|
+
position: absolute;
|
|
47
|
+
top: 20px;
|
|
48
|
+
left: -25px;
|
|
49
|
+
background: #fff;
|
|
50
|
+
min-width: 180px;
|
|
51
|
+
/* box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15); */
|
|
52
|
+
flex-direction: column;
|
|
53
|
+
z-index: 999;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.navbar-dropdown-link {
|
|
57
|
+
padding: 10px 15px;
|
|
58
|
+
color: #000;
|
|
59
|
+
text-decoration: none;
|
|
60
|
+
white-space: nowrap;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.navbar-dropdown-link:hover {
|
|
64
|
+
background: #f2f2f2;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Show dropdown on hover (desktop) */
|
|
68
|
+
.navbar-item.has-dropdown:hover .navbar-dropdown {
|
|
69
|
+
display: flex;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Add linear caret for items with dropdown */
|
|
73
|
+
.navbar-item.has-dropdown>.navbar-link::after {
|
|
74
|
+
content: ">";
|
|
75
|
+
display: inline-block;
|
|
76
|
+
margin-left: 6px;
|
|
77
|
+
font-size: 0.8em;
|
|
78
|
+
font-weight: bold;
|
|
79
|
+
transition: transform 0.3s ease;
|
|
80
|
+
transform: rotate(90deg);
|
|
81
|
+
}
|
|
28
82
|
|
|
83
|
+
/* -------------------------
|
|
84
|
+
Navbar Links
|
|
85
|
+
------------------------- */
|
|
29
86
|
.navbar-links {
|
|
30
87
|
display: flex;
|
|
31
|
-
/* gap: 1.5rem; */
|
|
32
88
|
transition: all 0.3s ease;
|
|
33
89
|
margin-left: 35px;
|
|
34
90
|
}
|
|
@@ -39,6 +95,28 @@
|
|
|
39
95
|
font-weight: 400;
|
|
40
96
|
font-size: 17px;
|
|
41
97
|
transition: color 0.2s;
|
|
98
|
+
display: inline-block;
|
|
99
|
+
/* allows width & height */
|
|
100
|
+
width: auto;
|
|
101
|
+
/* default for desktop */
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Style for parent items with sublinks (desktop) */
|
|
105
|
+
.navbar-link.parent-link {
|
|
106
|
+
cursor: default;
|
|
107
|
+
/* show pointer as normal arrow, not hand */
|
|
108
|
+
color: #333 !important;
|
|
109
|
+
/* normal text color */
|
|
110
|
+
/* font-weight: 500; */
|
|
111
|
+
/* optional: slightly bolder */
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Prevent hover effect for parent items */
|
|
115
|
+
.navbar-link.parent-link:hover {
|
|
116
|
+
color: #333;
|
|
117
|
+
/* do not turn red */
|
|
118
|
+
background: none;
|
|
119
|
+
/* no background change */
|
|
42
120
|
}
|
|
43
121
|
|
|
44
122
|
.navbar-links a:hover {
|
|
@@ -51,12 +129,9 @@
|
|
|
51
129
|
color: #ff0000;
|
|
52
130
|
}
|
|
53
131
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
/* Burger Icon */
|
|
132
|
+
/* -------------------------
|
|
133
|
+
Burger Icon
|
|
134
|
+
------------------------- */
|
|
60
135
|
.burger {
|
|
61
136
|
display: none;
|
|
62
137
|
flex-direction: column;
|
|
@@ -90,7 +165,9 @@
|
|
|
90
165
|
transform: translateY(-8px) rotate(-45deg);
|
|
91
166
|
}
|
|
92
167
|
|
|
93
|
-
|
|
168
|
+
/* -------------------------
|
|
169
|
+
Responsive
|
|
170
|
+
------------------------- */
|
|
94
171
|
@media (min-width: 1000px) {
|
|
95
172
|
.navbar-container {
|
|
96
173
|
padding: 1rem 5rem;
|
|
@@ -101,22 +178,30 @@
|
|
|
101
178
|
.navbar-container {
|
|
102
179
|
padding: 1rem 0;
|
|
103
180
|
}
|
|
104
|
-
|
|
105
181
|
}
|
|
106
182
|
|
|
107
183
|
@media (max-width: 500px) {
|
|
108
184
|
.navbar-container {
|
|
109
185
|
margin: 0 !important;
|
|
110
186
|
}
|
|
111
|
-
|
|
112
187
|
}
|
|
113
188
|
|
|
114
189
|
.mobile-login-btn {
|
|
115
190
|
display: none;
|
|
116
191
|
}
|
|
117
192
|
|
|
118
|
-
/*
|
|
193
|
+
/* -------------------------
|
|
194
|
+
Mobile Menu
|
|
195
|
+
------------------------- */
|
|
119
196
|
@media (max-width: 992px) {
|
|
197
|
+
/* .navbar-item.has-dropdown>.navbar-link::after {
|
|
198
|
+
display: none;
|
|
199
|
+
} */
|
|
200
|
+
|
|
201
|
+
.separator {
|
|
202
|
+
display: none;
|
|
203
|
+
}
|
|
204
|
+
|
|
120
205
|
.mobile-login-btn {
|
|
121
206
|
display: block;
|
|
122
207
|
}
|
|
@@ -136,8 +221,6 @@
|
|
|
136
221
|
justify-content: space-between;
|
|
137
222
|
}
|
|
138
223
|
|
|
139
|
-
/* ⭐ SLIDE-IN MENU */
|
|
140
|
-
|
|
141
224
|
.nav-items {
|
|
142
225
|
gap: 0px;
|
|
143
226
|
flex-direction: column;
|
|
@@ -162,8 +245,9 @@
|
|
|
162
245
|
}
|
|
163
246
|
|
|
164
247
|
.navbar-links a {
|
|
165
|
-
|
|
248
|
+
display: block;
|
|
166
249
|
width: 100%;
|
|
250
|
+
padding: 1rem 50px;
|
|
167
251
|
font-size: 1.2rem;
|
|
168
252
|
}
|
|
169
253
|
|
|
@@ -172,7 +256,30 @@
|
|
|
172
256
|
color: #fff;
|
|
173
257
|
}
|
|
174
258
|
|
|
175
|
-
|
|
259
|
+
.navbar-links a.active:hover {
|
|
260
|
+
color: #fff;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* Mobile dropdown inside sliding menu */
|
|
264
|
+
.navbar-dropdown {
|
|
265
|
+
position: static;
|
|
266
|
+
display: flex !important;
|
|
267
|
+
flex-direction: column;
|
|
268
|
+
background: transparent;
|
|
269
|
+
box-shadow: none;
|
|
270
|
+
padding: 0px;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.navbar-dropdown-link {
|
|
274
|
+
padding-left: 50px;
|
|
275
|
+
color: #333;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.has-dropdown .navbar-dropdown-link {
|
|
279
|
+
padding: 1rem 70px;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/* MOBILE LOGIN FIXED AT BOTTOM */
|
|
176
283
|
.mobile-login-btn {
|
|
177
284
|
position: absolute;
|
|
178
285
|
bottom: 0;
|
|
@@ -180,20 +287,18 @@
|
|
|
180
287
|
width: 100%;
|
|
181
288
|
padding: 1.3rem;
|
|
182
289
|
border: none;
|
|
183
|
-
/* background: #d00000; */
|
|
184
290
|
color: #333;
|
|
185
291
|
font-size: 1.1rem;
|
|
186
292
|
font-weight: 600;
|
|
187
|
-
/* text-align: center; */
|
|
188
293
|
}
|
|
189
294
|
}
|
|
190
295
|
|
|
191
|
-
|
|
192
|
-
|
|
296
|
+
/* -------------------------
|
|
297
|
+
Login Button
|
|
298
|
+
------------------------- */
|
|
193
299
|
.login-btn {
|
|
194
300
|
color: #333;
|
|
195
301
|
border: none;
|
|
196
|
-
/* padding: 0.5rem 1.25rem; */
|
|
197
302
|
border-radius: 6px;
|
|
198
303
|
cursor: pointer;
|
|
199
304
|
transition: background 0.3s ease;
|
|
@@ -208,7 +313,6 @@
|
|
|
208
313
|
font-weight: 500;
|
|
209
314
|
}
|
|
210
315
|
|
|
211
|
-
|
|
212
316
|
.navbar-login-panel .spb-header {
|
|
213
317
|
padding: 0 !important;
|
|
214
318
|
border-bottom: none !important;
|
|
@@ -218,6 +322,7 @@
|
|
|
218
322
|
padding: 20px;
|
|
219
323
|
}
|
|
220
324
|
|
|
325
|
+
/* Overlay for desktop login panel */
|
|
221
326
|
@media (min-width: 591px) {
|
|
222
327
|
.overlay-side-content {
|
|
223
328
|
position: fixed;
|
|
@@ -269,23 +374,21 @@
|
|
|
269
374
|
gap: 20px;
|
|
270
375
|
}
|
|
271
376
|
|
|
377
|
+
/* Scrollbar styling */
|
|
272
378
|
::-webkit-scrollbar {
|
|
273
379
|
width: 5px;
|
|
274
380
|
}
|
|
275
381
|
|
|
276
|
-
/* Track */
|
|
277
382
|
::-webkit-scrollbar-track {
|
|
278
383
|
box-shadow: inset 0 0 5px grey;
|
|
279
384
|
border-radius: 10px;
|
|
280
385
|
}
|
|
281
386
|
|
|
282
|
-
/* Handle */
|
|
283
387
|
::-webkit-scrollbar-thumb {
|
|
284
388
|
background: #757575;
|
|
285
389
|
border-radius: 10px;
|
|
286
390
|
}
|
|
287
391
|
|
|
288
|
-
/* Handle on hover */
|
|
289
392
|
::-webkit-scrollbar-thumb:hover {
|
|
290
393
|
background: #4f4f4f;
|
|
291
394
|
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import './Navbar.css';
|
|
3
|
+
export interface NavbarSubItem {
|
|
4
|
+
name: string;
|
|
5
|
+
link: string;
|
|
6
|
+
target?: '_blank' | '_self';
|
|
7
|
+
}
|
|
3
8
|
export interface NavbarItem {
|
|
4
9
|
name: string;
|
|
5
10
|
link: string;
|
|
6
11
|
target?: '_blank' | '_self';
|
|
12
|
+
subLinks?: NavbarSubItem[];
|
|
7
13
|
}
|
|
8
14
|
export interface NavbarProps {
|
|
9
15
|
siteUrl?: string;
|
|
@@ -6,8 +6,10 @@ import { SlidingPanel } from '../SlidingPanel/SlidingPanel';
|
|
|
6
6
|
export const Navbar = ({ siteUrl, items, logoSrc = '', logoAlt = 'M Lhuillier Logo', logoWidth = 220, logoHeight = 40, className = '', login = false, logedinData = null, loginContent, otherContent, onClose, }) => {
|
|
7
7
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
8
8
|
const [showLogin, setShowLogin] = useState(false);
|
|
9
|
+
const [isClosing, setIsClosing] = useState(false);
|
|
9
10
|
const [isMobile, setIsMobile] = useState(false);
|
|
10
11
|
const [currentPath, setCurrentPath] = useState(null);
|
|
12
|
+
const [openDropdown, setOpenDropdown] = useState(null);
|
|
11
13
|
useEffect(() => {
|
|
12
14
|
const handleResize = () => setIsMobile(window.innerWidth <= 590);
|
|
13
15
|
handleResize();
|
|
@@ -15,22 +17,67 @@ export const Navbar = ({ siteUrl, items, logoSrc = '', logoAlt = 'M Lhuillier Lo
|
|
|
15
17
|
window.addEventListener('resize', handleResize);
|
|
16
18
|
return () => window.removeEventListener('resize', handleResize);
|
|
17
19
|
}, []);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!menuOpen)
|
|
22
|
+
setOpenDropdown(null);
|
|
23
|
+
}, [menuOpen]);
|
|
18
24
|
const toggleMenu = () => setMenuOpen((prev) => !prev);
|
|
19
|
-
const toggleLogin = () =>
|
|
25
|
+
const toggleLogin = () => {
|
|
26
|
+
setMenuOpen(false);
|
|
27
|
+
setShowLogin((prev) => !prev);
|
|
28
|
+
};
|
|
29
|
+
const toggleDropdown = (name) => {
|
|
30
|
+
setOpenDropdown(prev => (prev === name ? null : name));
|
|
31
|
+
};
|
|
20
32
|
const handleInternalClose = () => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
33
|
+
setIsClosing(true);
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
setShowLogin(false);
|
|
36
|
+
setIsClosing(false);
|
|
37
|
+
document.body.style.overflow = '';
|
|
38
|
+
onClose?.();
|
|
39
|
+
}, 350);
|
|
24
40
|
};
|
|
25
|
-
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (menuOpen) {
|
|
43
|
+
document.body.style.overflow = 'hidden';
|
|
44
|
+
document.body.style.touchAction = 'none';
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
document.body.style.overflow = '';
|
|
48
|
+
document.body.style.touchAction = '';
|
|
49
|
+
}
|
|
50
|
+
return () => {
|
|
51
|
+
document.body.style.overflow = '';
|
|
52
|
+
document.body.style.touchAction = '';
|
|
53
|
+
};
|
|
54
|
+
}, [menuOpen]);
|
|
55
|
+
return (_jsxs(_Fragment, { children: [_jsx("nav", { className: `navbar ${className}`, children: _jsxs("div", { className: "navbar-container", children: [_jsx("div", { className: "navbar-logo", children: _jsx("a", { href: siteUrl, className: "navbar-brand", children: _jsx("img", { src: logoSrc, alt: logoAlt, width: logoWidth, height: logoHeight, style: { cursor: 'pointer', display: 'block' } }) }) }), _jsxs("div", { style: { display: 'flex', flexDirection: 'row', gap: '10px', alignItems: 'center' }, children: [_jsxs("div", { className: `navbar-links ${menuOpen ? 'open' : ''}`, children: [_jsx("div", { className: "nav-items", children: items.map(item => {
|
|
56
|
+
const hasSubLinks = item.subLinks && item.subLinks.length > 0;
|
|
26
57
|
const linkPath = new URL(item.link, 'https://dummybase').pathname;
|
|
27
58
|
const isActive = currentPath === linkPath;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
59
|
+
const isDropdownOpen = openDropdown === item.name;
|
|
60
|
+
return (_jsxs("div", { className: `navbar-item ${hasSubLinks ? 'has-dropdown' : ''} ${isDropdownOpen ? 'open' : ''}`, children: [_jsx("a", { href: hasSubLinks && !isMobile ? '#' : item.link, target: item.target || '_self', className: `navbar-link ${isActive ? 'active' : ''} ${hasSubLinks && !isMobile ? 'parent-link' : ''}`, onClick: (e) => {
|
|
61
|
+
if (hasSubLinks) {
|
|
62
|
+
if (isMobile) {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
toggleDropdown(item.name);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
e.preventDefault(); // prevent desktop click
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
setMenuOpen(false);
|
|
72
|
+
}
|
|
73
|
+
}, children: item.name }), hasSubLinks && (_jsx("div", { className: "navbar-dropdown", style: {
|
|
74
|
+
display: isMobile
|
|
75
|
+
? isDropdownOpen ? 'flex' : 'none'
|
|
76
|
+
: undefined,
|
|
77
|
+
}, children: item.subLinks.map(sub => (_jsx("a", { href: sub.link, target: sub.target || '_self', className: "navbar-dropdown-link", onClick: () => {
|
|
78
|
+
setMenuOpen(false);
|
|
79
|
+
setOpenDropdown(null);
|
|
80
|
+
}, children: sub.name }, sub.name))) }))] }, item.name));
|
|
81
|
+
}) }), isMobile && login && !logedinData && (_jsx("button", { className: "mobile-login-btn", onClick: toggleLogin, children: "Login" }))] }), _jsx("div", { className: 'separator', style: { color: '#aaaaaa', fontSize: '27px', padding: '0 15px' }, children: " | " }), _jsxs("div", { className: "navbar-right", children: [_jsxs("button", { className: `burger ${menuOpen ? 'active' : ''}`, onClick: toggleMenu, "aria-label": "Toggle menu", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }), !isMobile && login && !logedinData && (_jsx("span", { style: { color: '#e00000', fontWeight: '700' }, className: "login-btn", onClick: toggleLogin, children: "Login" }))] })] })] }) }), login && !logedinData && (_jsx(_Fragment, { children: !isMobile ? (showLogin && (_jsxs(_Fragment, { children: [_jsx("div", { className: "overlay-side-content", children: otherContent }), _jsx("div", { className: "navbar-login-panel", children: _jsxs(SlidingPanel, { isOpen: showLogin && !isClosing, width: "400px", height: "100%", position: "right", closeOnOverlayClick: false, onClose: handleInternalClose, children: [_jsx("div", { className: "navbar-panel-header" }), _jsx("div", { className: "navbar-panel-content", children: loginContent })] }) })] }))) : (_jsx("div", { className: "navbar-login-panel", children: _jsxs(SlidingPanel, { isOpen: showLogin, height: "70%", position: "bottom", onClose: handleInternalClose, children: [_jsx("div", { className: "navbar-panel-header" }), _jsx("div", { className: "navbar-panel-content", children: loginContent })] }) })) }))] }));
|
|
35
82
|
};
|
|
36
83
|
export default Navbar;
|
|
@@ -145,13 +145,14 @@
|
|
|
145
145
|
font-size: 20px;
|
|
146
146
|
line-height: 1;
|
|
147
147
|
cursor: pointer;
|
|
148
|
-
padding: 5px
|
|
148
|
+
padding: 5px 10px;
|
|
149
149
|
border-radius: 6px;
|
|
150
150
|
color: #111827;
|
|
151
|
+
margin-right: 7px;
|
|
151
152
|
}
|
|
152
153
|
|
|
153
154
|
.spb-close-btn:hover {
|
|
154
|
-
background:
|
|
155
|
+
background: rgb(255 0 0 / 27%);
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
/* Handle (mobile) */
|