flowbite-react
Version:
Official React components built for Flowbite and Tailwind CSS
167 lines (163 loc) • 5.53 kB
JavaScript
'use client';
'use strict';
var jsxRuntime = require('react/jsx-runtime');
var react = require('@floating-ui/react');
var React = require('react');
var hi = require('react-icons/hi');
var tailwindMerge = require('tailwind-merge');
var mergeDeep = require('../../helpers/merge-deep.cjs');
var useFloating = require('../../hooks/use-floating.cjs');
var index = require('../../theme-store/index.cjs');
var Button = require('../Button/Button.cjs');
require('../Button/ButtonGroup.cjs');
var DropdownContext = require('./DropdownContext.cjs');
var DropdownDivider = require('./DropdownDivider.cjs');
var DropdownHeader = require('./DropdownHeader.cjs');
var DropdownItem = require('./DropdownItem.cjs');
const icons = {
top: hi.HiOutlineChevronUp,
right: hi.HiOutlineChevronRight,
bottom: hi.HiOutlineChevronDown,
left: hi.HiOutlineChevronLeft
};
const Trigger = ({
refs,
children,
inline,
theme,
disabled,
setButtonWidth,
getReferenceProps,
renderTrigger,
...buttonProps
}) => {
const ref = refs.reference;
const a11yProps = getReferenceProps();
React.useEffect(() => {
if (ref.current) {
setButtonWidth?.(ref.current.clientWidth);
}
}, [ref, setButtonWidth]);
if (renderTrigger) {
const triggerElement = renderTrigger(theme);
return React.cloneElement(triggerElement, { ref: refs.setReference, disabled, ...a11yProps, ...triggerElement.props });
}
return inline ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", ref: refs.setReference, className: theme?.inlineWrapper, disabled, ...a11yProps, children }) : /* @__PURE__ */ jsxRuntime.jsx(Button.Button, { ...buttonProps, disabled, type: "button", ref: refs.setReference, ...a11yProps, children });
};
const DropdownComponent = ({
children,
className,
dismissOnClick = true,
theme: customTheme = {},
renderTrigger,
...props
}) => {
const [open, setOpen] = React.useState(false);
const [activeIndex, setActiveIndex] = React.useState(null);
const [selectedIndex, setSelectedIndex] = React.useState(null);
const [buttonWidth, setButtonWidth] = React.useState(void 0);
const elementsRef = React.useRef([]);
const labelsRef = React.useRef([]);
const theme = mergeDeep.mergeDeep(index.getTheme().dropdown, customTheme);
const theirProps = props;
const dataTestId = props["data-testid"] || "flowbite-dropdown-target";
const {
placement = props.inline ? "bottom-start" : "bottom",
trigger = "click",
label,
inline,
arrowIcon = true,
...buttonProps
} = theirProps;
const handleSelect = React.useCallback((index) => {
setSelectedIndex(index);
setOpen(false);
}, []);
const handleTypeaheadMatch = React.useCallback(
(index) => {
if (open) {
setActiveIndex(index);
} else {
handleSelect(index);
}
},
[open, handleSelect]
);
const { context, floatingStyles, refs } = useFloating.useBaseFLoating({
open,
setOpen,
placement
});
const listNav = react.useListNavigation(context, {
listRef: elementsRef,
activeIndex,
selectedIndex,
onNavigate: setActiveIndex
});
const typeahead = react.useTypeahead(context, {
listRef: labelsRef,
activeIndex,
selectedIndex,
onMatch: handleTypeaheadMatch
});
const { getReferenceProps, getFloatingProps, getItemProps } = useFloating.useFloatingInteractions({
context,
role: "menu",
trigger,
interactions: [listNav, typeahead]
});
const Icon = React.useMemo(() => {
const [p] = placement.split("-");
return icons[p] ?? hi.HiOutlineChevronDown;
}, [placement]);
return /* @__PURE__ */ jsxRuntime.jsxs(DropdownContext.DropdownContext.Provider, { value: { theme, activeIndex, dismissOnClick, getItemProps, handleSelect }, children: [
/* @__PURE__ */ jsxRuntime.jsxs(
Trigger,
{
...buttonProps,
refs,
inline,
theme,
"data-testid": dataTestId,
className: tailwindMerge.twMerge(theme.floating.target, buttonProps.className),
setButtonWidth,
getReferenceProps,
renderTrigger,
children: [
label,
arrowIcon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: theme.arrowIcon })
]
}
),
open && /* @__PURE__ */ jsxRuntime.jsx(react.FloatingFocusManager, { context, modal: false, children: /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
ref: refs.setFloating,
style: { ...floatingStyles, minWidth: buttonWidth },
"data-testid": "flowbite-dropdown",
"aria-expanded": open,
...getFloatingProps({
className: tailwindMerge.twMerge(
theme.floating.base,
theme.floating.animation,
"duration-100",
!open && theme.floating.hidden,
theme.floating.style.auto,
className
)
}),
children: /* @__PURE__ */ jsxRuntime.jsx(react.FloatingList, { elementsRef, labelsRef, children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: theme.content, tabIndex: -1, children }) })
}
) })
] });
};
DropdownComponent.displayName = "Dropdown";
DropdownHeader.DropdownHeader.displayName = "Dropdown.Header";
DropdownDivider.DropdownDivider.displayName = "Dropdown.Divider";
const Dropdown = Object.assign(DropdownComponent, {
Item: DropdownItem.DropdownItem,
Header: DropdownHeader.DropdownHeader,
Divider: DropdownDivider.DropdownDivider
});
exports.Dropdown = Dropdown;
//# sourceMappingURL=Dropdown.cjs.map