UNPKG

@arolariu/components

Version:

🎨 70+ beautiful, accessible React components built on Base UI. TypeScript-first, CSS Modules styling, tree-shakeable, SSR-ready. Perfect for modern web apps, design systems & rapid prototyping. Zero config, maximum flexibility! ⚡

205 lines (204 loc) • 7.95 kB
"use client"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; import { Check, ChevronsUpDown } from "lucide-react"; import { useControllableState } from "../../hooks/useControllableState.js"; import { cn } from "../../lib/utilities.js"; import { Button } from "./button.js"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from "./command.js"; import { Popover, PopoverContent, PopoverTrigger } from "./popover.js"; import combobox_module from "./combobox.module.js"; import * as __rspack_external_react from "react"; const ComboboxContext = /*#__PURE__*/ __rspack_external_react.createContext(null); function useComboboxContext(componentName) { const context = __rspack_external_react.useContext(ComboboxContext); if (!context) throw new Error(`${componentName} must be used within Combobox.`); return context; } function Combobox(props) { const { value: controlledValue, defaultValue = "", onValueChange, open: controlledOpen, defaultOpen = false, onOpenChange, placeholder = "Select an item...", searchPlaceholder = "Search...", emptyMessage = "No items found.", disabled = false, className, children } = props; const [value, setValue] = useControllableState({ controlled: controlledValue, defaultValue, onChange: onValueChange }); const [open, setOpen] = useControllableState({ controlled: controlledOpen, defaultValue: defaultOpen, onChange: onOpenChange }); const itemLabelsRef = __rspack_external_react.useRef(new Map()); const registerItem = __rspack_external_react.useCallback((itemValue, label)=>{ itemLabelsRef.current.set(itemValue, label); }, []); const unregisterItem = __rspack_external_react.useCallback((itemValue)=>{ itemLabelsRef.current.delete(itemValue); }, []); const contextValue = __rspack_external_react.useMemo(()=>({ value, onValueChange: setValue, open, setOpen, placeholder, searchPlaceholder, emptyMessage, disabled, itemLabels: itemLabelsRef.current, registerItem, unregisterItem }), [ value, setValue, open, setOpen, placeholder, searchPlaceholder, emptyMessage, disabled, registerItem, unregisterItem ]); return /*#__PURE__*/ jsx(ComboboxContext.Provider, { value: contextValue, children: /*#__PURE__*/ jsx(Popover, { open: open, onOpenChange: setOpen, children: /*#__PURE__*/ jsx("div", { className: cn(combobox_module.combobox, className), children: children }) }) }); } Combobox.displayName = "Combobox"; const ComboboxTrigger = /*#__PURE__*/ __rspack_external_react.forwardRef((props, ref)=>{ const { className, children } = props; const { open, setOpen, value, placeholder, disabled, itemLabels } = useComboboxContext("ComboboxTrigger"); const [, forceUpdate] = __rspack_external_react.useReducer((x)=>x + 1, 0); __rspack_external_react.useEffect(()=>{ forceUpdate(); }, [ value ]); const selectedLabel = itemLabels.get(value) || ""; return /*#__PURE__*/ jsx(PopoverTrigger, { render: /*#__PURE__*/ jsx(Button, { ref: ref, variant: "outline", role: "combobox", "aria-expanded": open, disabled: disabled, className: cn(combobox_module.trigger, className), onClick: ()=>setOpen(!open), children: children ?? /*#__PURE__*/ jsxs(Fragment, { children: [ /*#__PURE__*/ jsx("span", { className: cn(combobox_module.triggerValue, !selectedLabel && combobox_module.triggerPlaceholder), children: selectedLabel || placeholder }), /*#__PURE__*/ jsx(ChevronsUpDown, { className: combobox_module.triggerIcon }) ] }) }) }); }); ComboboxTrigger.displayName = "ComboboxTrigger"; const ComboboxContent = /*#__PURE__*/ __rspack_external_react.forwardRef((props, ref)=>{ const { className, children } = props; const { searchPlaceholder } = useComboboxContext("ComboboxContent"); return /*#__PURE__*/ jsx(PopoverContent, { ref: ref, className: cn(combobox_module.content, className), sideOffset: 4, children: /*#__PURE__*/ jsxs(Command, { className: combobox_module.command, children: [ /*#__PURE__*/ jsx(CommandInput, { placeholder: searchPlaceholder, className: combobox_module.commandInput }), /*#__PURE__*/ jsxs(CommandList, { className: combobox_module.commandList, children: [ /*#__PURE__*/ jsx(ComboboxEmpty, {}), children ] }) ] }) }); }); ComboboxContent.displayName = "ComboboxContent"; function ComboboxItem(props) { const { value: itemValue, className, children, disabled = false, onSelect, keywords = [] } = props; const { value: selectedValue, onValueChange, setOpen, registerItem, unregisterItem } = useComboboxContext("ComboboxItem"); const isSelected = selectedValue === itemValue; const label = "string" == typeof children ? children : itemValue; __rspack_external_react.useEffect(()=>{ registerItem(itemValue, label); return ()=>{ unregisterItem(itemValue); }; }, [ itemValue, label, registerItem, unregisterItem ]); const handleSelect = __rspack_external_react.useCallback((currentValue)=>{ const newValue = currentValue === selectedValue ? "" : currentValue; onValueChange(newValue); setOpen(false); onSelect?.(newValue); }, [ selectedValue, onValueChange, setOpen, onSelect ]); return /*#__PURE__*/ jsxs(CommandItem, { value: itemValue, disabled: disabled, onSelect: handleSelect, keywords: keywords, className: cn(combobox_module.item, isSelected && combobox_module.itemSelected, className), children: [ /*#__PURE__*/ jsx(Check, { className: cn(combobox_module.itemCheck, isSelected && combobox_module.itemCheckVisible) }), /*#__PURE__*/ jsx("span", { className: combobox_module.itemLabel, children: children }) ] }); } ComboboxItem.displayName = "ComboboxItem"; function ComboboxEmpty(props) { const { className, children } = props; const { emptyMessage } = useComboboxContext("ComboboxEmpty"); return /*#__PURE__*/ jsx(CommandEmpty, { className: cn(combobox_module.empty, className), children: children ?? emptyMessage }); } ComboboxEmpty.displayName = "ComboboxEmpty"; function ComboboxGroup(props) { const { heading, className, children } = props; return /*#__PURE__*/ jsx(CommandGroup, { heading: heading, className: cn(combobox_module.group, className), children: children }); } ComboboxGroup.displayName = "ComboboxGroup"; function ComboboxSeparator(props) { const { className } = props; return /*#__PURE__*/ jsx(CommandSeparator, { className: cn(combobox_module.separator, className) }); } ComboboxSeparator.displayName = "ComboboxSeparator"; export { Combobox, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxItem, ComboboxSeparator, ComboboxTrigger }; //# sourceMappingURL=combobox.js.map