@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
JavaScript
"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