flowbite-react
Version:
Official React components built for Flowbite and Tailwind CSS
1 lines • 12.6 kB
Source Map (JSON)
{"version":3,"file":"Dropdown.mjs","sources":["../../../../src/components/Dropdown/Dropdown.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ExtendedRefs } from \"@floating-ui/react\";\nimport { FloatingFocusManager, FloatingList, useListNavigation, useTypeahead } from \"@floating-ui/react\";\nimport type {\n ComponentProps,\n Dispatch,\n FC,\n HTMLProps,\n MutableRefObject,\n ReactElement,\n ReactNode,\n SetStateAction,\n} from \"react\";\nimport { cloneElement, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { HiOutlineChevronDown, HiOutlineChevronLeft, HiOutlineChevronRight, HiOutlineChevronUp } from \"react-icons/hi\";\nimport { twMerge } from \"tailwind-merge\";\nimport { mergeDeep } from \"../../helpers/merge-deep\";\nimport { useBaseFLoating, useFloatingInteractions } from \"../../hooks/use-floating\";\nimport { getTheme } from \"../../theme-store\";\nimport type { DeepPartial } from \"../../types\";\nimport { Button, type ButtonProps } from \"../Button\";\nimport type { FloatingProps, FlowbiteFloatingTheme } from \"../Floating\";\nimport { DropdownContext } from \"./DropdownContext\";\nimport { DropdownDivider, type FlowbiteDropdownDividerTheme } from \"./DropdownDivider\";\nimport { DropdownHeader, type FlowbiteDropdownHeaderTheme } from \"./DropdownHeader\";\nimport { DropdownItem, type FlowbiteDropdownItemTheme } from \"./DropdownItem\";\n\nexport interface FlowbiteDropdownFloatingTheme\n extends FlowbiteFloatingTheme,\n FlowbiteDropdownDividerTheme,\n FlowbiteDropdownHeaderTheme {\n item: FlowbiteDropdownItemTheme;\n}\n\nexport interface FlowbiteDropdownTheme {\n floating: FlowbiteDropdownFloatingTheme;\n content: string;\n inlineWrapper: string;\n arrowIcon: string;\n}\n\nexport interface DropdownProps extends Pick<FloatingProps, \"placement\" | \"trigger\">, Omit<ButtonProps, \"theme\"> {\n arrowIcon?: boolean;\n dismissOnClick?: boolean;\n floatingArrow?: boolean;\n inline?: boolean;\n label: ReactNode;\n theme?: DeepPartial<FlowbiteDropdownTheme>;\n renderTrigger?: (theme: FlowbiteDropdownTheme) => ReactElement;\n \"data-testid\"?: string;\n}\n\nconst icons: Record<string, FC<ComponentProps<\"svg\">>> = {\n top: HiOutlineChevronUp,\n right: HiOutlineChevronRight,\n bottom: HiOutlineChevronDown,\n left: HiOutlineChevronLeft,\n};\n\nexport interface TriggerProps extends Omit<ButtonProps, \"theme\"> {\n refs: ExtendedRefs<HTMLElement>;\n inline?: boolean;\n theme: FlowbiteDropdownTheme;\n setButtonWidth?: Dispatch<SetStateAction<number | undefined>>;\n getReferenceProps: (userProps?: HTMLProps<Element> | undefined) => Record<string, unknown>;\n renderTrigger?: (theme: FlowbiteDropdownTheme) => ReactElement;\n}\n\nconst Trigger = ({\n refs,\n children,\n inline,\n theme,\n disabled,\n setButtonWidth,\n getReferenceProps,\n renderTrigger,\n ...buttonProps\n}: TriggerProps) => {\n const ref = refs.reference as MutableRefObject<HTMLElement>;\n const a11yProps = getReferenceProps();\n\n useEffect(() => {\n if (ref.current) {\n setButtonWidth?.(ref.current.clientWidth);\n }\n }, [ref, setButtonWidth]);\n\n if (renderTrigger) {\n const triggerElement = renderTrigger(theme);\n return cloneElement(triggerElement, { ref: refs.setReference, disabled, ...a11yProps, ...triggerElement.props });\n }\n\n return inline ? (\n <button type=\"button\" ref={refs.setReference} className={theme?.inlineWrapper} disabled={disabled} {...a11yProps}>\n {children}\n </button>\n ) : (\n <Button {...buttonProps} disabled={disabled} type=\"button\" ref={refs.setReference} {...a11yProps}>\n {children}\n </Button>\n );\n};\n\nconst DropdownComponent: FC<DropdownProps> = ({\n children,\n className,\n dismissOnClick = true,\n theme: customTheme = {},\n renderTrigger,\n ...props\n}) => {\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const [selectedIndex, setSelectedIndex] = useState<number | null>(null);\n const [buttonWidth, setButtonWidth] = useState<number | undefined>(undefined);\n const elementsRef = useRef<Array<HTMLElement | null>>([]);\n const labelsRef = useRef<Array<string | null>>([]);\n\n const theme = mergeDeep(getTheme().dropdown, customTheme);\n const theirProps = props as Omit<DropdownProps, \"theme\">;\n const dataTestId = props[\"data-testid\"] || \"flowbite-dropdown-target\";\n const {\n placement = props.inline ? \"bottom-start\" : \"bottom\",\n trigger = \"click\",\n label,\n inline,\n arrowIcon = true,\n ...buttonProps\n } = theirProps;\n\n const handleSelect = useCallback((index: number | null) => {\n setSelectedIndex(index);\n setOpen(false);\n }, []);\n\n const handleTypeaheadMatch = useCallback(\n (index: number | null) => {\n if (open) {\n setActiveIndex(index);\n } else {\n handleSelect(index);\n }\n },\n [open, handleSelect],\n );\n\n const { context, floatingStyles, refs } = useBaseFLoating<HTMLButtonElement>({\n open,\n setOpen,\n placement,\n });\n\n const listNav = useListNavigation(context, {\n listRef: elementsRef,\n activeIndex,\n selectedIndex,\n onNavigate: setActiveIndex,\n });\n\n const typeahead = useTypeahead(context, {\n listRef: labelsRef,\n activeIndex,\n selectedIndex,\n onMatch: handleTypeaheadMatch,\n });\n\n const { getReferenceProps, getFloatingProps, getItemProps } = useFloatingInteractions({\n context,\n role: \"menu\",\n trigger,\n interactions: [listNav, typeahead],\n });\n\n const Icon = useMemo(() => {\n const [p] = placement.split(\"-\");\n return icons[p] ?? HiOutlineChevronDown;\n }, [placement]);\n\n return (\n <DropdownContext.Provider value={{ theme, activeIndex, dismissOnClick, getItemProps, handleSelect }}>\n <Trigger\n {...buttonProps}\n refs={refs}\n inline={inline}\n theme={theme}\n data-testid={dataTestId}\n className={twMerge(theme.floating.target, buttonProps.className)}\n setButtonWidth={setButtonWidth}\n getReferenceProps={getReferenceProps}\n renderTrigger={renderTrigger}\n >\n {label}\n {arrowIcon && <Icon className={theme.arrowIcon} />}\n </Trigger>\n {open && (\n <FloatingFocusManager context={context} modal={false}>\n <div\n ref={refs.setFloating}\n style={{ ...floatingStyles, minWidth: buttonWidth }}\n data-testid=\"flowbite-dropdown\"\n aria-expanded={open}\n {...getFloatingProps({\n className: twMerge(\n theme.floating.base,\n theme.floating.animation,\n \"duration-100\",\n !open && theme.floating.hidden,\n theme.floating.style.auto,\n className,\n ),\n })}\n >\n <FloatingList elementsRef={elementsRef} labelsRef={labelsRef}>\n <ul className={theme.content} tabIndex={-1}>\n {children}\n </ul>\n </FloatingList>\n </div>\n </FloatingFocusManager>\n )}\n </DropdownContext.Provider>\n );\n};\n\nDropdownComponent.displayName = \"Dropdown\";\nDropdownHeader.displayName = \"Dropdown.Header\";\nDropdownDivider.displayName = \"Dropdown.Divider\";\n\nexport const Dropdown = Object.assign(DropdownComponent, {\n Item: DropdownItem,\n Header: DropdownHeader,\n Divider: DropdownDivider,\n});\n"],"names":[],"mappings":"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"}