ml-ui-lib 1.0.30 → 1.0.31

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.
@@ -205,7 +205,7 @@
205
205
  /* -------------------------
206
206
  Responsive
207
207
  ------------------------- */
208
- @media (max-width: 992px) {
208
+ @media (max-width: 1100px) {
209
209
  .navbar-container {
210
210
  margin: 0 20px;
211
211
  padding: 1rem 1.5rem;
@@ -244,15 +244,14 @@
244
244
  position: fixed;
245
245
  top: 0;
246
246
  right: -100%;
247
- width: 400px;
248
247
  height: 100vh;
248
+ width: 260px;
249
249
  background: #fff;
250
250
  flex-direction: column;
251
- padding: 65px 0px 70px;
252
- transition: right 0.3s ease-in-out;
253
- box-shadow: -4px 0 12px rgba(0, 0, 0, 0.1);
254
- z-index: 9999;
255
- overflow-y: auto;
251
+ align-items: flex-start;
252
+ padding: 80px 20px;
253
+ transition: right 0.3s ease;
254
+ box-shadow: -5px 0 15px rgba(0, 0, 0, 0.1);
256
255
  }
257
256
 
258
257
  .navbar-links.open {
@@ -262,7 +261,7 @@
262
261
  .nav-items {
263
262
  flex-direction: column;
264
263
  gap: 0;
265
- overflow: visible;
264
+ /* overflow: visible; */
266
265
  }
267
266
 
268
267
  .navbar-links a {
@@ -273,6 +272,10 @@
273
272
  color: #333;
274
273
  }
275
274
 
275
+ .separator {
276
+ display: none !important;
277
+ }
278
+
276
279
  .navbar-links a:hover {
277
280
  background: #ff0000;
278
281
  color: #fff;
@@ -1,100 +1,122 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, useEffect } from 'react';
4
- import './Navbar.css';
5
- import { SlidingPanel } from '../SlidingPanel/SlidingPanel';
6
- export const Navbar = ({ siteUrl, items, logoSrc = '', logoAlt = 'Logo', logoWidth = 220, logoHeight = 40, className = '', login = false, logedinData = null, loginContent, otherContent, onClose, }) => {
7
- const [menuOpen, setMenuOpen] = useState(false);
8
- const [showLogin, setShowLogin] = useState(false);
9
- const [isClosing, setIsClosing] = useState(false);
10
- const [isMobile, setIsMobile] = useState(false);
11
- const [currentPath, setCurrentPath] = useState(null);
12
- const [openDropdown, setOpenDropdown] = useState(null);
13
- const [hideNavbar, setHideNavbar] = useState(false);
14
- const [lastScrollY, setLastScrollY] = useState(0);
15
- useEffect(() => {
16
- const handleResize = () => setIsMobile(window.innerWidth <= 992);
17
- handleResize();
18
- setCurrentPath(window.location.pathname);
19
- window.addEventListener('resize', handleResize);
20
- return () => window.removeEventListener('resize', handleResize);
21
- }, []);
22
- useEffect(() => {
23
- if (!menuOpen)
24
- setOpenDropdown(null);
25
- }, [menuOpen]);
26
- const toggleMenu = () => setMenuOpen(prev => !prev);
27
- const toggleLogin = () => {
28
- setMenuOpen(false);
29
- setShowLogin(prev => !prev);
30
- };
31
- const handleInternalClose = () => {
32
- setIsClosing(true);
33
- setTimeout(() => {
34
- setShowLogin(false);
35
- setIsClosing(false);
36
- document.body.style.overflow = '';
37
- onClose?.();
38
- }, 350);
39
- };
40
- useEffect(() => {
41
- document.body.style.overflow = menuOpen ? 'hidden' : '';
42
- document.body.style.touchAction = menuOpen ? 'none' : '';
43
- return () => {
44
- document.body.style.overflow = '';
45
- document.body.style.touchAction = '';
46
- };
47
- }, [menuOpen]);
48
- useEffect(() => {
49
- let ticking = false;
50
- const REVEAL_THRESHOLD = 10; // adjust (px). 60–120
51
- const handleScroll = () => {
52
- if (menuOpen)
53
- return;
54
- const currentY = window.scrollY;
55
- if (!ticking) {
56
- window.requestAnimationFrame(() => {
57
- if (currentY <= 0) {
58
- setHideNavbar(false);
59
- setLastScrollY(0);
60
- ticking = false;
61
- return;
62
- }
63
- const diff = lastScrollY - currentY;
64
- // scrolling DOWN → hide immediately
65
- if (currentY > lastScrollY) {
66
- setHideNavbar(true);
67
- }
68
- // scrolling UP → only show after threshold
69
- else if (diff > REVEAL_THRESHOLD) {
70
- setHideNavbar(false);
71
- }
72
- setLastScrollY(currentY);
73
- ticking = false;
74
- });
75
- ticking = true;
76
- }
77
- };
78
- window.addEventListener('scroll', handleScroll, { passive: true });
79
- return () => window.removeEventListener('scroll', handleScroll);
80
- }, [lastScrollY, menuOpen]);
81
- return (_jsxs(_Fragment, { children: [_jsx("nav", { className: `navbar ${hideNavbar ? 'navbar--hidden' : ''} ${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 => {
82
- const hasSubLinks = item.subLinks && item.subLinks.length > 0;
83
- const linkPath = new URL(item.link || '#', 'https://dummybase').pathname;
84
- const isActive = currentPath === linkPath;
85
- const isDropdownOpen = openDropdown === item.name;
86
- return (_jsxs("div", { className: `navbar-item ${hasSubLinks ? 'has-dropdown' : ''} ${isDropdownOpen ? 'open' : ''}`, children: [_jsx("a", { href: hasSubLinks ? '#' : item.link, target: item.target || '_self', className: `navbar-link ${isActive ? 'active' : ''} ${hasSubLinks ? 'parent-link' : ''}`, onClick: (e) => {
87
- if (hasSubLinks && isMobile) {
88
- e.preventDefault();
89
- setOpenDropdown(prev => (prev === item.name ? null : item.name));
90
- }
91
- else {
92
- setMenuOpen(false);
93
- }
94
- }, children: item.name }), hasSubLinks && (_jsx("div", { className: "navbar-dropdown", children: _jsx("div", { className: "navbar-dropdown-content", children: item.subLinks.map(sub => (_jsx("a", { href: sub.link, target: sub.target || '_self', className: "navbar-dropdown-link", onClick: () => {
95
- setMenuOpen(false);
96
- setOpenDropdown(null);
97
- }, children: sub.name }, sub.name))) }) }))] }, item.name));
98
- }) }), isMobile && login && !logedinData && (_jsx("div", { className: 'navbar-item', style: { background: '#ffffff' }, children: _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, children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }), !isMobile && login && !logedinData && (_jsx("span", { 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 })] }) })) }))] }));
99
- };
100
- export default Navbar;
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState, useEffect } from 'react';
4
+ import './Navbar.css';
5
+ import { SlidingPanel } from '../SlidingPanel/SlidingPanel';
6
+ export const Navbar = ({ siteUrl, items, logoSrc = '', logoAlt = 'Logo', logoWidth = 220, logoHeight = 40, className = '', login = false, logedinData = null, loginContent, otherContent, onClose, }) => {
7
+ const [menuOpen, setMenuOpen] = useState(false);
8
+ const [showLogin, setShowLogin] = useState(false);
9
+ const [isClosing, setIsClosing] = useState(false);
10
+ const [isMobile, setIsMobile] = useState(false);
11
+ const [currentPath, setCurrentPath] = useState(null);
12
+ const [openDropdown, setOpenDropdown] = useState(null);
13
+ const [hideNavbar, setHideNavbar] = useState(false);
14
+ const [lastScrollY, setLastScrollY] = useState(0);
15
+ useEffect(() => {
16
+ const handleResize = () => setIsMobile(window.innerWidth <= 992);
17
+ handleResize();
18
+ setCurrentPath(window.location.pathname);
19
+ window.addEventListener('resize', handleResize);
20
+ return () => window.removeEventListener('resize', handleResize);
21
+ }, []);
22
+ useEffect(() => {
23
+ if (!menuOpen)
24
+ setOpenDropdown(null);
25
+ }, [menuOpen]);
26
+ const toggleMenu = () => setMenuOpen(prev => !prev);
27
+ const toggleLogin = () => {
28
+ setMenuOpen(false);
29
+ setShowLogin(prev => !prev);
30
+ };
31
+ const handleInternalClose = () => {
32
+ setIsClosing(true);
33
+ setTimeout(() => {
34
+ setShowLogin(false);
35
+ setIsClosing(false);
36
+ document.body.style.overflow = '';
37
+ onClose?.();
38
+ }, 350);
39
+ };
40
+ useEffect(() => {
41
+ document.body.style.overflow = menuOpen ? 'hidden' : '';
42
+ document.body.style.touchAction = menuOpen ? 'none' : '';
43
+ return () => {
44
+ document.body.style.overflow = '';
45
+ document.body.style.touchAction = '';
46
+ };
47
+ }, [menuOpen]);
48
+ useEffect(() => {
49
+ let ticking = false;
50
+ const REVEAL_THRESHOLD = 10; // adjust (px). 60–120
51
+ const handleScroll = () => {
52
+ if (menuOpen)
53
+ return;
54
+ const currentY = window.scrollY;
55
+ if (!ticking) {
56
+ window.requestAnimationFrame(() => {
57
+ if (currentY <= 0) {
58
+ setHideNavbar(false);
59
+ setLastScrollY(0);
60
+ ticking = false;
61
+ return;
62
+ }
63
+ const diff = lastScrollY - currentY;
64
+ // scrolling DOWN → hide immediately
65
+ if (currentY > lastScrollY) {
66
+ setHideNavbar(true);
67
+ }
68
+ // scrolling UP → only show after threshold
69
+ else if (diff > REVEAL_THRESHOLD) {
70
+ setHideNavbar(false);
71
+ }
72
+ setLastScrollY(currentY);
73
+ ticking = false;
74
+ });
75
+ ticking = true;
76
+ }
77
+ };
78
+ window.addEventListener('scroll', handleScroll, { passive: true });
79
+ return () => window.removeEventListener('scroll', handleScroll);
80
+ }, [lastScrollY, menuOpen]);
81
+ return (_jsxs(_Fragment, {
82
+ children: [_jsx("nav", {
83
+ className: `navbar ${hideNavbar ? 'navbar--hidden' : ''} ${className}`, children: _jsxs("div", {
84
+ 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", {
85
+ style: { display: 'flex', flexDirection: 'row', gap: '10px', alignItems: 'center' }, children: [_jsxs("div", {
86
+ className: `navbar-links ${menuOpen ? 'open' : ''}`, children: [_jsx("div", {
87
+ className: `nav-items ${hideNavbar ? 'nav-items--hidden' : ''} ${className}`, children: items.map(item => {
88
+ const hasSubLinks = item.subLinks && item.subLinks.length > 0;
89
+ const linkPath = new URL(item.link || '#', 'https://dummybase').pathname;
90
+ const isActive = currentPath === linkPath;
91
+ const isDropdownOpen = openDropdown === item.name;
92
+ return (_jsxs("div", {
93
+ className: `navbar-item ${hasSubLinks ? 'has-dropdown' : ''} ${isDropdownOpen ? 'open' : ''}`, children: [_jsx("a", {
94
+ href: hasSubLinks ? '#' : item.link, target: item.target || '_self', className: `navbar-link ${isActive ? 'active' : ''} ${hasSubLinks ? 'parent-link' : ''}`, onClick: (e) => {
95
+ if (hasSubLinks && isMobile) {
96
+ e.preventDefault();
97
+ setOpenDropdown(prev => (prev === item.name ? null : item.name));
98
+ }
99
+ else {
100
+ setMenuOpen(false);
101
+ }
102
+ }, children: item.name
103
+ }), hasSubLinks && (_jsx("div", {
104
+ className: "navbar-dropdown", children: _jsx("div", {
105
+ className: "navbar-dropdown-content", children: item.subLinks.map(sub => (_jsx("a", {
106
+ href: sub.link, target: sub.target || '_self', className: "navbar-dropdown-link", onClick: () => {
107
+ setMenuOpen(false);
108
+ setOpenDropdown(null);
109
+ }, children: sub.name
110
+ }, sub.name)))
111
+ })
112
+ }))]
113
+ }, item.name));
114
+ })
115
+ }), isMobile && login && !logedinData && (_jsx("div", { className: 'navbar-item', style: { background: '#ffffff' }, children: _jsx("button", { className: "mobile-login-btn", onClick: toggleLogin, children: "Login" }) }))]
116
+ }), _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, children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }), !isMobile && login && !logedinData && (_jsx("span", { className: "login-btn", onClick: toggleLogin, children: "Login" }))] })]
117
+ })]
118
+ })
119
+ }), 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 })] }) })) }))]
120
+ }));
121
+ };
122
+ export default Navbar;
package/package.json CHANGED
@@ -1,29 +1,29 @@
1
- {
2
- "name": "ml-ui-lib",
3
- "version": "1.0.30",
4
- "main": "dist/index.js",
5
- "module": "dist/index.esm.js",
6
- "types": "dist/index.d.ts",
7
- "author": "Kenneth James B. Simbulan",
8
- "files": [
9
- "dist"
10
- ],
11
- "scripts": {
12
- "clean": "rimraf dist",
13
- "build": "npm run clean && tsc && npm run copy-assets",
14
- "copy-assets": "copyfiles -u 1 \"src/**/*.css\" \"src/**/*.png\" dist/",
15
- "watch": "tsc --watch",
16
- "dev": "npm run build -- --watch"
17
- },
18
- "peerDependencies": {
19
- "react": ">=17",
20
- "react-dom": ">=17"
21
- },
22
- "devDependencies": {
23
- "@types/react": "^18.0.0",
24
- "@types/react-dom": "^18.0.0",
25
- "copyfiles": "^2.4.1",
26
- "rimraf": "^5.0.10",
27
- "typescript": "^5.9.3"
28
- }
29
- }
1
+ {
2
+ "name": "ml-ui-lib",
3
+ "version": "1.0.31",
4
+ "main": "dist/index.js",
5
+ "module": "dist/index.esm.js",
6
+ "types": "dist/index.d.ts",
7
+ "author": "Kenneth James B. Simbulan",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "clean": "rimraf dist",
13
+ "build": "npm run clean && tsc && npm run copy-assets",
14
+ "copy-assets": "copyfiles -u 1 \"src/**/*.css\" \"src/**/*.png\" dist/",
15
+ "watch": "tsc --watch",
16
+ "dev": "npm run build -- --watch"
17
+ },
18
+ "peerDependencies": {
19
+ "react": ">=17",
20
+ "react-dom": ">=17"
21
+ },
22
+ "devDependencies": {
23
+ "@types/react": "^18.0.0",
24
+ "@types/react-dom": "^18.0.0",
25
+ "copyfiles": "^2.4.1",
26
+ "rimraf": "^5.0.10",
27
+ "typescript": "^5.9.3"
28
+ }
29
+ }