import { Dropdown as BootstrapDropdown } from "bootstrap"; import { ComponentChildren } from "preact"; import { CSSProperties, HTMLProps } from "preact/compat"; import { useCallback, useEffect, useRef, useState } from "preact/hooks"; import { useUniqueName } from "./hooks"; export interface DropdownProps extends Pick, "id" | "className"> { 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; noDropdownListStyle?: boolean; disabled?: boolean; text?: ComponentChildren; forceShown?: boolean; } export default function Dropdown({ id, className, buttonClassName, isStatic, children, title, text, dropdownContainerStyle, dropdownContainerClassName, hideToggleArrow, iconAction, disabled, noSelectButtonStyle, noDropdownListStyle, forceShown }: DropdownProps) { const dropdownRef = useRef(null); const triggerRef = useRef(null); const [ shown, setShown ] = useState(false); useEffect(() => { if (!triggerRef.current) return; const dropdown = BootstrapDropdown.getOrCreateInstance(triggerRef.current); if (forceShown) { dropdown.show(); setShown(true); } return () => dropdown.dispose(); }, []); 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 (
    {shown && children}
) }