UNPKG

flowbite-react

Version:

Official React components built for Flowbite and Tailwind CSS

184 lines (180 loc) 6.19 kB
'use client'; 'use strict'; var jsxRuntime = require('react/jsx-runtime'); var react = require('@floating-ui/react'); var React = require('react'); var get = require('../../helpers/get.cjs'); var resolveProps = require('../../helpers/resolve-props.cjs'); var resolveTheme = require('../../helpers/resolve-theme.cjs'); var tailwindMerge = require('../../helpers/tailwind-merge.cjs'); var useFloating = require('../../hooks/use-floating.cjs'); var chevronDownIcon = require('../../icons/chevron-down-icon.cjs'); var chevronLeftIcon = require('../../icons/chevron-left-icon.cjs'); var chevronRightIcon = require('../../icons/chevron-right-icon.cjs'); var chevronUpIcon = require('../../icons/chevron-up-icon.cjs'); var provider = require('../../theme/provider.cjs'); var Button = require('../Button/Button.cjs'); require('../Button/ButtonGroup.cjs'); require('../Button/ButtonGroupContext.cjs'); var DropdownContext = require('./DropdownContext.cjs'); var theme = require('./theme.cjs'); const icons = { top: chevronUpIcon.ChevronUpIcon, right: chevronRightIcon.ChevronRightIcon, bottom: chevronDownIcon.ChevronDownIcon, left: chevronLeftIcon.ChevronLeftIcon }; function 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 }); } function Dropdown(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 provider$1 = provider.useThemeProvider(); const theme$1 = resolveTheme.useResolveTheme( [theme.dropdownTheme, provider$1.theme?.dropdown, props.theme], [get.get(provider$1.clearTheme, "dropdown"), props.clearTheme], [get.get(provider$1.applyTheme, "dropdown"), props.applyTheme] ); const { children, className, dismissOnClick = true, enableTypeAhead = true, renderTrigger, ...restProps } = resolveProps.resolveProps(props, provider$1.props?.dropdown); const { placement = restProps.inline ? "bottom-start" : "bottom", trigger = "click", label, inline, arrowIcon = true, ...buttonProps } = restProps; const dataTestId = restProps["data-testid"] || "flowbite-dropdown-target"; 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, enabled: enableTypeAhead }); const { getReferenceProps, getFloatingProps, getItemProps } = useFloating.useFloatingInteractions({ context, role: "menu", trigger, interactions: [listNav, typeahead] }); const Icon = React.useMemo(() => { const [p] = placement.split("-"); return icons[p] ?? chevronDownIcon.ChevronDownIcon; }, [placement]); return /* @__PURE__ */ jsxRuntime.jsxs( DropdownContext.DropdownContext.Provider, { value: { theme: props.theme, clearTheme: props.clearTheme, applyTheme: props.applyTheme, activeIndex, dismissOnClick, getItemProps, handleSelect }, children: [ /* @__PURE__ */ jsxRuntime.jsxs( Trigger, { ...buttonProps, refs, inline, theme: theme$1, "data-testid": dataTestId, className: tailwindMerge.twMerge(theme$1.floating.target, className), setButtonWidth, getReferenceProps, renderTrigger, children: [ label, arrowIcon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: theme$1.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$1.floating.base, theme$1.floating.animation, "duration-100", !open && theme$1.floating.hidden, theme$1.floating.style.auto, className ) }), children: /* @__PURE__ */ jsxRuntime.jsx(react.FloatingList, { elementsRef, labelsRef, children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: theme$1.content, tabIndex: -1, children }) }) } ) }) ] } ); } Dropdown.displayName = "Dropdown"; exports.Dropdown = Dropdown; //# sourceMappingURL=Dropdown.cjs.map