mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			87 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { Dropdown as BootstrapDropdown } from "bootstrap";
 | 
						|
import { ComponentChildren } from "preact";
 | 
						|
import { CSSProperties } from "preact/compat";
 | 
						|
import { useCallback, useEffect, useRef, useState } from "preact/hooks";
 | 
						|
import { useUniqueName } from "./hooks";
 | 
						|
 | 
						|
export interface DropdownProps {
 | 
						|
    className?: string;
 | 
						|
    buttonClassName?: string;
 | 
						|
    isStatic?: boolean;
 | 
						|
    children: ComponentChildren;
 | 
						|
    title?: string;
 | 
						|
    dropdownContainerStyle?: CSSProperties;
 | 
						|
    dropdownContainerClassName?: string;
 | 
						|
    hideToggleArrow?: boolean;
 | 
						|
    /** If set to true, then the dropdown button will be considered an icon action (without normal border and sized for icons only). */
 | 
						|
    iconAction?: boolean;
 | 
						|
    noSelectButtonStyle?: boolean;
 | 
						|
    disabled?: boolean;
 | 
						|
    text?: ComponentChildren;
 | 
						|
}
 | 
						|
 | 
						|
export default function Dropdown({ className, buttonClassName, isStatic, children, title, text, dropdownContainerStyle, dropdownContainerClassName, hideToggleArrow, iconAction, disabled, noSelectButtonStyle }: DropdownProps) {
 | 
						|
    const dropdownRef = useRef<HTMLDivElement | null>(null);
 | 
						|
    const triggerRef = useRef<HTMLButtonElement | null>(null);
 | 
						|
 | 
						|
    const [ shown, setShown ] = useState(false);
 | 
						|
 | 
						|
    useEffect(() => {
 | 
						|
        if (!triggerRef.current) return;
 | 
						|
        
 | 
						|
        const dropdown = BootstrapDropdown.getOrCreateInstance(triggerRef.current);
 | 
						|
        return () => dropdown.dispose();
 | 
						|
    }, []); // Add dependency array
 | 
						|
 | 
						|
    const onShown = useCallback(() => {
 | 
						|
        setShown(true);
 | 
						|
    }, [])
 | 
						|
 | 
						|
    const onHidden = useCallback(() => {
 | 
						|
        setShown(false);
 | 
						|
    }, []);
 | 
						|
 | 
						|
    useEffect(() => {
 | 
						|
        if (!dropdownRef.current) return;
 | 
						|
        
 | 
						|
        const $dropdown = $(dropdownRef.current);
 | 
						|
        $dropdown.on("show.bs.dropdown", onShown);
 | 
						|
        $dropdown.on("hide.bs.dropdown", onHidden);
 | 
						|
        
 | 
						|
        // Add proper cleanup
 | 
						|
        return () => {
 | 
						|
            $dropdown.off("show.bs.dropdown", onShown);
 | 
						|
            $dropdown.off("hide.bs.dropdown", onHidden);
 | 
						|
        };
 | 
						|
    }, []); // Add dependency array
 | 
						|
 | 
						|
    const ariaId = useUniqueName("button");
 | 
						|
 | 
						|
    return (
 | 
						|
        <div ref={dropdownRef} class={`dropdown ${className ?? ""}`} style={{ display: "flex" }}>
 | 
						|
            <button
 | 
						|
                className={`${iconAction ? "icon-action" : "btn"} ${!noSelectButtonStyle ? "select-button" : ""} ${buttonClassName ?? ""} ${!hideToggleArrow ? "dropdown-toggle" : ""}`}
 | 
						|
                ref={triggerRef}
 | 
						|
                type="button"
 | 
						|
                data-bs-toggle="dropdown"
 | 
						|
                data-bs-display={ isStatic ? "static" : undefined }
 | 
						|
                aria-haspopup="true"
 | 
						|
                aria-expanded="false"
 | 
						|
                title={title}
 | 
						|
                id={ariaId}
 | 
						|
                disabled={disabled}
 | 
						|
            >
 | 
						|
                {text}
 | 
						|
                <span className="caret"></span>
 | 
						|
            </button>
 | 
						|
 | 
						|
            <div
 | 
						|
                class={`dropdown-menu ${isStatic ? "static" : ""} ${dropdownContainerClassName ?? ""} tn-dropdown-list`}
 | 
						|
                style={dropdownContainerStyle}
 | 
						|
                aria-labelledby={ariaId}
 | 
						|
            >
 | 
						|
                {shown && children}
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
    )
 | 
						|
} |