oneslash-design-system 1.0.9 → 1.1.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.
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import React, { useState, useEffect, useCallback } from 'react';
2
3
 
3
4
  interface ButtonProps{
@@ -1,5 +1,4 @@
1
1
  'use client';
2
-
3
2
  import { useState } from 'react';
4
3
 
5
4
  interface CheckboxProps {
@@ -52,13 +52,13 @@ export default function MenuItem({
52
52
  flex items-center space-x-2 p-2 rounded-[8px] cursor-pointer justify-start
53
53
  ${isSelected
54
54
  ? 'bg-light-action-selected dark:bg-dark-action-selected'
55
- : 'hover:bg-light-action-hover dark:hover:bg-dark-action-hover'}
55
+ : 'hover:bg-light-background-accent100 hover:dark:bg-dark-background-accent100'}
56
56
  `}
57
57
  style={{ width: '100%' }}
58
58
  onClick={onClick}
59
59
  >
60
- {Icon && <Icon className="w-5 h-5" />}
61
- <span className="whitespace-nowrap text-body1">
60
+ {Icon && <Icon className="w-6 h-6" />}
61
+ <span className="whitespace-nowrap text-body1 px-2">
62
62
  {label}
63
63
  </span>
64
64
  </div>
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import React, { useEffect } from 'react';
2
3
 
3
4
  interface ModalProps {
@@ -1,98 +1,68 @@
1
- 'use client';
2
- import React, { useState, useRef, useLayoutEffect } from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
+ import { createPortal } from 'react-dom';
3
+ import { usePopper } from 'react-popper';
3
4
 
4
5
  interface PopoverProps {
5
6
  id?: string;
6
7
  anchorEl?: HTMLElement | null;
7
- open?: boolean;
8
- onClose?: () => void;
9
- children: any;
8
+ open: boolean;
9
+ onClose: () => void;
10
+ children: React.ReactNode;
10
11
  }
11
12
 
12
- export default function Popover({
13
- anchorEl,
14
- open = false,
15
- onClose,
16
- children
13
+ export default function Popover({
14
+ id,
15
+ anchorEl,
16
+ open,
17
+ onClose,
18
+ children,
17
19
  }: PopoverProps) {
20
+ const [popoverElement, setPopoverElement] = useState<HTMLDivElement | null>(null);
21
+ const [hasMounted, setHasMounted] = useState(false);
18
22
 
19
- const [popoverStyle, setPopoverStyle] = useState<React.CSSProperties>({});
20
- const popoverRef = useRef<HTMLDivElement>(null);
23
+ // Initialize Popper.js
24
+ const { styles, attributes } = usePopper(anchorEl, popoverElement, {
25
+ placement: 'bottom-start', // Default placement, can be customized
26
+ modifiers: [
27
+ { name: 'offset', options: { offset: [0, 8] } }, // Offset for spacing between anchor and popover
28
+ ],
29
+ });
21
30
 
22
- // Close popover when clicking outside
23
- useLayoutEffect(() => {
31
+ // Handle outside clicks to close the popover
32
+ useEffect(() => {
24
33
  const handleClickOutside = (event: MouseEvent) => {
25
- if (popoverRef.current && !popoverRef.current.contains(event.target as Node) && anchorEl) {
26
- onClose?.(); // Safe call for optional onClose
34
+ if (popoverElement && !popoverElement.contains(event.target as Node) && anchorEl) {
35
+ onClose();
27
36
  }
28
37
  };
38
+
29
39
  if (open) {
30
40
  document.addEventListener('mousedown', handleClickOutside);
31
41
  }
32
42
  return () => {
33
43
  document.removeEventListener('mousedown', handleClickOutside);
34
44
  };
35
- }, [open, anchorEl, onClose]);
36
-
37
- // Calculate position and handle scroll/resize
38
- useLayoutEffect(() => {
39
- if (anchorEl && open) {
40
- const handlePositioning = () => {
41
- const anchorRect = anchorEl.getBoundingClientRect();
42
- const popoverRect = popoverRef.current?.getBoundingClientRect();
43
-
44
- if (popoverRect) {
45
- const spaceBelow = window.innerHeight - anchorRect.bottom;
46
- const spaceAbove = anchorRect.top;
47
-
48
- // Decide whether to place the popover above or below the anchor
49
- const shouldPlaceAbove = spaceBelow < popoverRect.height + 8 && spaceAbove > popoverRect.height + 8;
50
-
51
- // Calculate top and left positions
52
- const topPosition = shouldPlaceAbove
53
- ? anchorRect.top + window.scrollY - popoverRect.height - 8
54
- : anchorRect.bottom + window.scrollY + 8;
55
-
56
- let leftPosition = anchorRect.left + window.scrollX + (anchorRect.width / 2) - (popoverRect.width / 2);
45
+ }, [open, anchorEl, popoverElement, onClose]);
57
46
 
58
- // Ensure the popover doesn't overflow off the left or right of the screen
59
- if (leftPosition < 8) {
60
- leftPosition = 8; // Prevent overflow on the left
61
- } else if (leftPosition + popoverRect.width > window.innerWidth - 8) {
62
- leftPosition = window.innerWidth - popoverRect.width - 8; // Prevent overflow on the right
63
- }
64
-
65
- setPopoverStyle({
66
- position: 'absolute',
67
- top: `${topPosition}px`,
68
- left: `${leftPosition}px`,
69
- zIndex: 10000,
70
- visibility: 'visible',
71
- });
72
- }
73
- };
74
-
75
- handlePositioning(); // Initial positioning calculation
76
- window.addEventListener('resize', handlePositioning);
77
- window.addEventListener('scroll', handlePositioning, true);
78
-
79
- return () => {
80
- window.removeEventListener('resize', handlePositioning);
81
- window.removeEventListener('scroll', handlePositioning, true);
82
- };
83
- }
84
- }, [anchorEl, open]);
47
+ // Ensure popover is only rendered after the component mounts
48
+ useEffect(() => {
49
+ setHasMounted(true);
50
+ }, []);
85
51
 
86
- if (!open || !anchorEl) return null;
52
+ if (!open || !hasMounted || !anchorEl) return null;
87
53
 
88
- return (
54
+ // Render popover in a portal to prevent layout shifts and positioning issues
55
+ return createPortal(
89
56
  <div
90
- ref={popoverRef}
91
- style={popoverStyle}
57
+ id={id}
58
+ ref={setPopoverElement}
59
+ style={{ ...styles.popper, display: open ? 'block' : 'none' }}
60
+ {...attributes.popper}
92
61
  className="bg-light-background-accent100 dark:bg-dark-background-accent100 rounded-[8px] shadow-lg p-2"
93
62
  role="dialog"
94
63
  >
95
64
  {children}
96
- </div>
65
+ </div>,
66
+ document.body // Mounting the popover in the document body for isolation
97
67
  );
98
68
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "oneslash-design-system",
3
3
  "description": "A design system for the Oneslash projects",
4
- "version": "1.0.9",
4
+ "version": "1.1.1",
5
5
  "private": false,
6
6
  "scripts": {
7
7
  "dev": "next dev",
@@ -12,9 +12,11 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@heroicons/react": "^2.1.5",
15
+ "@popperjs/core": "^2.11.8",
15
16
  "next": "14.2.13",
16
17
  "react": "^18",
17
- "react-dom": "^18"
18
+ "react-dom": "^18",
19
+ "react-popper": "^2.3.0"
18
20
  },
19
21
  "devDependencies": {
20
22
  "@types/node": "20.16.10",