@scripso-homepad/ui 0.4.16 → 0.4.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scripso-homepad/ui",
3
- "version": "0.4.16",
3
+ "version": "0.4.17",
4
4
  "type": "module",
5
5
  "description": "Cross-platform UI components for Homepad (React Web + React Native)",
6
6
  "license": "MIT",
@@ -7,6 +7,35 @@ import './drawer-scroll.css';
7
7
 
8
8
  const DRAWER_TRANSITION_MS = 300;
9
9
 
10
+ let bodyScrollLockCount = 0;
11
+ let previousBodyOverflow = '';
12
+
13
+ function lockBodyScroll() {
14
+ if (typeof document === 'undefined') {
15
+ return;
16
+ }
17
+
18
+ if (bodyScrollLockCount === 0) {
19
+ previousBodyOverflow = document.body.style.overflow;
20
+ document.body.style.overflow = 'hidden';
21
+ }
22
+
23
+ bodyScrollLockCount += 1;
24
+ }
25
+
26
+ function unlockBodyScroll() {
27
+ if (typeof document === 'undefined') {
28
+ return;
29
+ }
30
+
31
+ bodyScrollLockCount = Math.max(0, bodyScrollLockCount - 1);
32
+
33
+ if (bodyScrollLockCount === 0) {
34
+ document.body.style.overflow = previousBodyOverflow;
35
+ previousBodyOverflow = '';
36
+ }
37
+ }
38
+
10
39
  export type DrawerProps = {
11
40
  open: boolean;
12
41
  title: string;
@@ -70,8 +99,7 @@ export function Drawer({
70
99
  return;
71
100
  }
72
101
 
73
- const previousOverflow = document.body.style.overflow;
74
- document.body.style.overflow = 'hidden';
102
+ lockBodyScroll();
75
103
 
76
104
  const handleKeyDown = (event: KeyboardEvent) => {
77
105
  if (event.key === 'Escape') {
@@ -82,7 +110,7 @@ export function Drawer({
82
110
  window.addEventListener('keydown', handleKeyDown);
83
111
 
84
112
  return () => {
85
- document.body.style.overflow = previousOverflow;
113
+ unlockBodyScroll();
86
114
  window.removeEventListener('keydown', handleKeyDown);
87
115
  };
88
116
  }, [isPresent, onClose]);
@@ -10,38 +10,29 @@ export type SidebarNavItemProps = {
10
10
  onNavigate?: (item: AdminNavItem) => void;
11
11
  };
12
12
 
13
- function isModifiedClick(event: MouseEvent<HTMLAnchorElement>): boolean {
14
- return event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0;
15
- }
16
-
17
13
  export function SidebarNavItem({ item, isOpen, isActive, onNavigate }: SidebarNavItemProps) {
18
14
  if (item.hidden) {
19
15
  return null;
20
16
  }
21
17
 
22
- const handleClick = (event: MouseEvent<HTMLAnchorElement>) => {
23
- if (item.disabled) {
24
- event.preventDefault();
25
- return;
26
- }
18
+ const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
19
+ event.preventDefault();
27
20
 
28
- // Keep routing in the host app's React Router instance so workspace /
29
- // published UI copies never fight over duplicate router contexts.
30
- if (event.defaultPrevented || isModifiedClick(event)) {
21
+ if (item.disabled) {
31
22
  return;
32
23
  }
33
24
 
34
- event.preventDefault();
35
25
  item.onClick?.();
36
26
  onNavigate?.(item);
37
27
  };
38
28
 
39
29
  return (
40
- <a
41
- href={item.to}
30
+ <button
31
+ type="button"
42
32
  onClick={handleClick}
43
33
  aria-current={isActive ? 'page' : undefined}
44
34
  aria-disabled={item.disabled}
35
+ disabled={item.disabled}
45
36
  tabIndex={item.disabled ? -1 : undefined}
46
37
  className={cn(
47
38
  'relative flex items-center rounded-xl px-4 py-3 transition-[background-color,color,gap,padding] duration-300 ease-in-out',
@@ -66,6 +57,6 @@ export function SidebarNavItem({ item, isOpen, isActive, onNavigate }: SidebarNa
66
57
  >
67
58
  {item.label}
68
59
  </span>
69
- </a>
60
+ </button>
70
61
  );
71
62
  }