club home redesign; deal card menu anchored to button + delete
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
/** موقعیت منوی شناور کنار دکمهٔ سهنقطهٔ کارت؛ اگر دکمه پیدا نشود null */
|
||||
export function cardMenuStyle(
|
||||
cardId: string,
|
||||
width = 160,
|
||||
height = 190,
|
||||
): Record<string, string> | null {
|
||||
const btn = document.querySelector<HTMLElement>(
|
||||
`[data-card-id="${CSS.escape(cardId)}"] .menu`,
|
||||
);
|
||||
if (!btn) return null;
|
||||
const r = btn.getBoundingClientRect();
|
||||
const gap = 4;
|
||||
const left = Math.min(Math.max(8, r.left), window.innerWidth - width - 8);
|
||||
const fitsBelow = r.bottom + gap + height <= window.innerHeight;
|
||||
const top = fitsBelow ? r.bottom + gap : Math.max(8, r.top - height - gap);
|
||||
return { inset: 'auto', top: `${top}px`, left: `${left}px`, minWidth: `${width}px` };
|
||||
}
|
||||
|
||||
/** بستن منو با کلیک بیرون، Escape یا اسکرول */
|
||||
export function bindMenuDismiss(isOpen: () => boolean, close: () => void): () => void {
|
||||
const onPointer = (e: PointerEvent) => {
|
||||
if (!isOpen()) return;
|
||||
const t = e.target as Element | null;
|
||||
if (t?.closest('.menu-pop, .deal-card .menu')) return;
|
||||
close();
|
||||
};
|
||||
const onKey = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape' && isOpen()) close();
|
||||
};
|
||||
const onScroll = (e: Event) => {
|
||||
if (!isOpen()) return;
|
||||
if ((e.target as Element | null)?.closest?.('.menu-pop')) return;
|
||||
close();
|
||||
};
|
||||
window.addEventListener('pointerdown', onPointer, true);
|
||||
window.addEventListener('keydown', onKey);
|
||||
window.addEventListener('scroll', onScroll, true);
|
||||
return () => {
|
||||
window.removeEventListener('pointerdown', onPointer, true);
|
||||
window.removeEventListener('keydown', onKey);
|
||||
window.removeEventListener('scroll', onScroll, true);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user