| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- "use client";
- import { useState, useRef, useLayoutEffect, type ReactNode, useEffect } from "react";
- import clsx from "clsx";
- export function LyDropDown({
- showDropDown,
- children,
- onClose
- }: {
- showDropDown: boolean;
- children: ReactNode;
- onClose: () => void;
- }) {
- const listRef = useRef<HTMLDivElement>(null);
- const rootRef = useRef<HTMLDivElement>(null);
- const [listPosition, setListPosition] = useState({
- top: '0',
- transform: 'translate3d(0, 0%, 0)',
- });
- useLayoutEffect(() => {
- if (listRef.current && rootRef.current && showDropDown) {
- const { height } = listRef.current.getBoundingClientRect();
- // setListHeight(height);
- console.log('Measured tooltip height: ' + height);
- const triggerRect = rootRef.current.getBoundingClientRect();
- if(triggerRect.bottom + height > window.innerHeight) { // 显示在上方
- setListPosition({
- top: '0',
- transform: 'translate3d(0, -100%, 0)',
- });
- } else { // 显示在下方
- setListPosition({
- top: `${triggerRect.height}px`,
- transform: `translate3d(0, 0%, 0)`
- });
- }
-
- }
- }, [showDropDown]);
- // 点击外部关闭
- useEffect(() => {
- if (!showDropDown) return;
- function handleClickOutside(event: MouseEvent) {
- const target = event.target as Node;
- if (
- rootRef.current &&
- !rootRef.current.contains(target)
- ) {
- onClose();
- }
- }
- // 放到 document 捕获阶段
- document.addEventListener(
- "pointerdown",
- handleClickOutside,
- true
- );
- return () => {
- document.removeEventListener(
- "pointerdown",
- handleClickOutside,
- true
- );
- };
- }, [showDropDown, onClose]);
- return (
- <>
- <div className="w-full relative" ref={rootRef}>
- <div ref={listRef} className={clsx(
- "absolute w-full max-h-48 overflow-auto bg-white ly-thin-shadow border border-ly-gray rounded-md z-1",
- showDropDown ? "visible pointer-events-auto" : "invisible pointer-events-none"
- )}
- onClick={(e) => { e.stopPropagation(); }}
- style={listPosition}
- >
- {children}
-
- </div>
- </div>
- </>
- );
- }
|