aboutsummaryrefslogtreecommitdiff
path: root/packages/components/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/components/src')
-rw-r--r--packages/components/src/components/MultiToggle/MultiToggle.tsx16
-rw-r--r--packages/components/src/components/Popup/Popup.tsx43
2 files changed, 44 insertions, 15 deletions
diff --git a/packages/components/src/components/MultiToggle/MultiToggle.tsx b/packages/components/src/components/MultiToggle/MultiToggle.tsx
index 0a6fb81c9..c1d610c34 100644
--- a/packages/components/src/components/MultiToggle/MultiToggle.tsx
+++ b/packages/components/src/components/MultiToggle/MultiToggle.tsx
@@ -17,6 +17,7 @@ export interface IMultiToggleProps extends IGlobalProps {
selectedItems?: (string | number) | (string | number)[];
onSelectionChange?: (val: (string | number) | (string | number)[], added: boolean) => unknown;
toggleStatus?: boolean;
+ showUntilToggle?: boolean; // whether popup stays open when background is clicked. muyst click toggle button tp close it.
}
function promoteToArrayOrUndefined(d: (string | number)[] | (string | number) | undefined) {
@@ -32,12 +33,23 @@ export const MultiToggle = (props: IMultiToggleProps) => {
init = false;
const [selectedItemsLocal, setSelectedItemsLocal] = useState(initVal as (string | number) | (string | number)[]);
- const { items, selectedItems = selectedItemsLocal, tooltip, tooltipPlacement = 'top', onSelectionChange, color, background } = props;
+ const {
+ items, //
+ selectedItems = selectedItemsLocal,
+ tooltip,
+ toggleStatus,
+ tooltipPlacement = 'top',
+ onSelectionChange,
+ color,
+ background,
+ } = props;
const itemsMap = new Map();
items.forEach(item => itemsMap.set(item.val, item));
return (
<div className="multiToggle-container">
<Popup
+ isOpen={toggleStatus}
+ multitoggle={true} // this is used to indicate that this is a multi toggle, so it can be styled differently in the popup
toggle={
<div style={{ position: 'relative' }}>
<IconButton
@@ -53,7 +65,7 @@ export const MultiToggle = (props: IMultiToggleProps) => {
{promoteToArray(selectedItems).length < 2 ? null : <div style={{ position: 'absolute', top: '0', left: '0', color: color ?? Colors.MEDIUM_BLUE }}>+</div>}
</div>
}
- isToggle={true}
+ showUntilToggle={props.showUntilToggle ?? true}
toggleFunc={() => {
const selItem = items.find(item => promoteToArray(selectedItems).includes(item.val));
selItem && setSelectedItemsLocal([selItem.val]);
diff --git a/packages/components/src/components/Popup/Popup.tsx b/packages/components/src/components/Popup/Popup.tsx
index 9e72ece87..9e91a75cf 100644
--- a/packages/components/src/components/Popup/Popup.tsx
+++ b/packages/components/src/components/Popup/Popup.tsx
@@ -3,6 +3,7 @@ import { IGlobalProps, Placement, Size } from '../../global';
import { Toggle, ToggleType } from '../Toggle';
import './Popup.scss';
import { Popper } from '@mui/material';
+import PositionObserver from '@thednp/position-observer';
export enum PopupTrigger {
CLICK = 'click',
@@ -23,9 +24,10 @@ export interface IPopupProps extends IGlobalProps {
isOpen?: boolean;
setOpen?: (b: boolean) => void;
background?: string;
- isToggle?: boolean; // whether popup stays open when background is clicked. muyst click toggle button tp close it.
+ showUntilToggle?: boolean; // whether popup stays open when background is clicked. muyst click toggle button tp close it.
toggleFunc?: () => void;
popupContainsPt?: (x: number, y: number) => boolean;
+ multitoggle?: boolean;
}
/**
@@ -57,20 +59,21 @@ export const Popup = (props: IPopupProps) => {
fillWidth,
iconPlacement = 'left',
background,
+ multitoggle,
popupContainsPt,
} = props;
const triggerRef = useRef(null);
const popperRef = useRef<HTMLDivElement | null>(null);
- const toggleRef = useRef<HTMLDivElement | null>(null);
+ const [toggleRef, setToggleRef] = useState<HTMLDivElement | null>(null);
let timeout = setTimeout(() => {});
const handlePointerAwayDown = (e: PointerEvent) => {
const rect = popperRef.current?.getBoundingClientRect();
- const rect2 = toggleRef.current?.getBoundingClientRect();
+ const rect2 = toggleRef?.getBoundingClientRect();
if (
- !props.isToggle &&
+ !props.showUntilToggle &&
(!rect2 || !(rect2.left < e.clientX && rect2.top < e.clientY && rect2.right > e.clientX && rect2.bottom > e.clientY)) &&
rect &&
!(rect.left < e.clientX && rect.top < e.clientY && rect.right > e.clientX && rect.bottom > e.clientY) &&
@@ -82,22 +85,36 @@ export const Popup = (props: IPopupProps) => {
}
};
+ let observer: PositionObserver | undefined = undefined;
+ const [previousPosition, setPreviousPosition] = useState<DOMRect | undefined>(toggleRef?.getBoundingClientRect());
+
useEffect(() => {
if (isOpen) {
window.removeEventListener('pointerdown', handlePointerAwayDown, { capture: true });
window.addEventListener('pointerdown', handlePointerAwayDown, { capture: true });
- return () => window.removeEventListener('pointerdown', handlePointerAwayDown, { capture: true });
- }
- }, [isOpen, popupContainsPt]);
-
+ if (toggleRef && multitoggle) {
+ (observer = new PositionObserver(entries => {
+ entries.forEach(entry => {
+ const currentPosition = entry.boundingClientRect;
+ if (Math.floor(currentPosition.top) !== Math.floor(previousPosition?.top ?? 0) || Math.floor(currentPosition.left) !== Math.floor(previousPosition?.left ?? 0)) {
+ // Perform actions when position changes
+ setPreviousPosition(currentPosition); // Update previous position
+ }
+ });
+ })).observe(toggleRef);
+ }
+ return () => {
+ window.removeEventListener('pointerdown', handlePointerAwayDown, { capture: true });
+ observer?.disconnect();
+ };
+ } else observer?.disconnect();
+ }, [isOpen, toggleRef, popupContainsPt]);
return (
<div className={`popup-wrapper ${fillWidth && 'fillWidth'}`}>
<div
- className={`trigger-container ${fillWidth && 'fillWidth'}`}
ref={triggerRef}
- onClick={() => {
- if (trigger === PopupTrigger.CLICK) setOpen(!isOpen);
- }}
+ className={`trigger-container ${fillWidth && 'fillWidth'}`}
+ onClick={() => trigger === PopupTrigger.CLICK && setOpen(!isOpen)}
onPointerEnter={() => {
if (trigger === PopupTrigger.HOVER || trigger === PopupTrigger.HOVER_DELAY) {
clearTimeout(timeout);
@@ -109,7 +126,7 @@ export const Popup = (props: IPopupProps) => {
timeout = setTimeout(() => setOpen(false), 1000);
}
}}>
- <div ref={toggleRef}>
+ <div className="special" ref={R => setToggleRef(R)}>
{toggle ?? (
<Toggle
tooltip={tooltip}