UNPKG

@diceui/combobox

Version:

Combobox is a component that allows users to select an option from a list of options.

1,317 lines (1,308 loc) 45.6 kB
'use client'; 'use strict'; var shared = require('@diceui/shared'); var React = require('react'); var react = require('@floating-ui/react'); function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var React__namespace = /*#__PURE__*/_interopNamespace(React); function getDataState(open) { return open ? "open" : "closed"; } var ROOT_NAME = "ComboboxRoot"; var [ComboboxProvider, useComboboxContext] = shared.createContext(ROOT_NAME); function ComboboxRootImpl(props, forwardedRef) { const { value: valueProp, defaultValue, onValueChange: onValueChangeProp, open: openProp, defaultOpen = false, onOpenChange, inputValue: inputValueProp, onInputValueChange, onFilter, autoHighlight = false, disabled = false, exactMatch = false, manualFiltering = false, loop = false, modal = false, multiple = false, openOnFocus = false, preserveInputOnBlur = false, readOnly = false, required = false, dir: dirProp, name, children, ...rootProps } = props; const inputRef = React__namespace.useRef(null); const listRef = React__namespace.useRef(null); const inputId = shared.useId(); const labelId = shared.useId(); const listId = shared.useId(); const dir = shared.useDirection(dirProp); const { collectionRef, getItems, itemMap, groupMap, onItemRegister } = shared.useCollection({ grouped: true }); const { anchorRef, hasAnchor, onHasAnchorChange } = shared.useAnchor(); const { isFormControl, onTriggerChange } = shared.useFormControl(); const composedRef = shared.useComposedRefs( forwardedRef, collectionRef, (node) => onTriggerChange(node) ); const [selectedText, setSelectedText] = React__namespace.useState(""); const [highlightedItem, setHighlightedItem] = React__namespace.useState(null); const [highlightedBadgeIndex, setHighlightedBadgeIndex] = React__namespace.useState(-1); const [hasBadgeList, setHasBadgeList] = React__namespace.useState(false); const [open = false, setOpen] = shared.useControllableState({ prop: openProp, defaultProp: defaultOpen, onChange: (newOpen) => { if (!newOpen) { filterStore.search = ""; } onOpenChange?.(newOpen); if (multiple) { setHighlightedBadgeIndex(-1); return; } if (defaultValue && !Array.isArray(defaultValue) && selectedText === "") { setSelectedText(defaultValue); } } }); const [value = multiple ? [] : "", setValue] = shared.useControllableState({ prop: valueProp, defaultProp: defaultValue, onChange: onValueChangeProp }); const [inputValue = "", setInputValue] = shared.useControllableState({ defaultProp: !multiple && defaultValue ? String(defaultValue) : "", prop: inputValueProp, onChange: (payload) => { if (disabled || readOnly) return; onInputValueChange?.(payload); if (autoHighlight && open) { onHighlightMove("first"); } } }); const { filterStore, onItemsFilter, getIsItemVisible, getIsListEmpty } = shared.useFilterStore({ itemMap, groupMap, onFilter, exactMatch, manualFiltering }); const onValueChange = React__namespace.useCallback( (newValue) => { if (disabled || readOnly) return; if (multiple) { const currentValue = Array.isArray(value) ? value : []; const typedNewValue = typeof newValue === "string" ? newValue : ""; if (!typedNewValue) return; const newValues = currentValue.includes(typedNewValue) ? currentValue.filter((v) => v !== newValue) : [...currentValue, newValue]; setValue(newValues); return; } setValue(newValue); }, [multiple, setValue, value, disabled, readOnly] ); const onItemRemove = React__namespace.useCallback( (currentValue) => { const newValues = Array.isArray(value) ? value.filter((v) => v !== currentValue) : []; setValue(newValues); }, [setValue, value] ); const { onHighlightMove } = shared.useListHighlighting({ highlightedItem, onHighlightedItemChange: setHighlightedItem, getItems: React__namespace.useCallback(() => { return getItems().filter( (item) => !item.disabled && getIsItemVisible(item.value) ); }, [getItems, getIsItemVisible]), getIsItemSelected: (item) => { const selectedValue = Array.isArray(value) ? value[0] : value; return item.value === selectedValue; }, loop }); return /* @__PURE__ */ React__namespace.createElement( ComboboxProvider, { value, onValueChange, open, onOpenChange: setOpen, inputValue, onInputValueChange: setInputValue, selectedText, onSelectedTextChange: setSelectedText, filterStore, onFilter, onItemsFilter, highlightedItem, onHighlightedItemChange: setHighlightedItem, highlightedBadgeIndex, onHighlightedBadgeIndexChange: setHighlightedBadgeIndex, onItemRegister, onItemRemove, onHighlightMove, getIsItemVisible, getIsListEmpty, hasAnchor, onHasAnchorChange, hasBadgeList, onHasBadgeListChange: setHasBadgeList, autoHighlight, disabled, loop, manualFiltering, modal, multiple, openOnFocus, preserveInputOnBlur, readOnly, collectionRef, listRef, inputRef, anchorRef, dir, inputId, labelId, listId }, /* @__PURE__ */ React__namespace.createElement(shared.Primitive.div, { ...rootProps, ref: composedRef }, children, isFormControl && name && /* @__PURE__ */ React__namespace.createElement( shared.VisuallyHiddenInput, { type: "hidden", control: collectionRef.current, name, value, disabled, readOnly, required } )) ); } var ComboboxRoot = shared.forwardRef(ComboboxRootImpl); ComboboxRoot.displayName = ROOT_NAME; var Root = ComboboxRoot; var LABEL_NAME = "ComboboxLabel"; var ComboboxLabel = React__namespace.forwardRef( (props, forwardedRef) => { const context = useComboboxContext(LABEL_NAME); return /* @__PURE__ */ React__namespace.createElement( shared.Primitive.label, { id: context.labelId, htmlFor: context.inputId, ...props, ref: forwardedRef } ); } ); ComboboxLabel.displayName = LABEL_NAME; var Label = ComboboxLabel; var ANCHOR_NAME = "ComboboxAnchor"; var ComboboxAnchor = React__namespace.forwardRef( (props, forwardedRef) => { const { preventInputFocus, ...anchorProps } = props; const context = useComboboxContext(ANCHOR_NAME); const composedRef = shared.useComposedRefs( forwardedRef, context.anchorRef, (node) => context.onHasAnchorChange(!!node) ); const [isFocused, setIsFocused] = React__namespace.useState(false); return /* @__PURE__ */ React__namespace.createElement( shared.Primitive.div, { "data-state": context.open ? "open" : "closed", "data-anchor": "", "data-disabled": context.disabled ? "" : void 0, "data-focused": isFocused ? "" : void 0, dir: context.dir, ...anchorProps, ref: composedRef, onBlur: shared.composeEventHandlers( anchorProps.onBlur, () => setIsFocused(false) ), onClick: shared.composeEventHandlers(anchorProps.onClick, (event) => { if (preventInputFocus) return; event.currentTarget.focus(); context.inputRef.current?.focus(); }), onFocus: shared.composeEventHandlers( anchorProps.onFocus, () => setIsFocused(true) ), onPointerDown: shared.composeEventHandlers( anchorProps.onPointerDown, (event) => { if (context.disabled) return; const target = event.target; if (!(target instanceof HTMLElement)) return; if (target.hasPointerCapture(event.pointerId)) { target.releasePointerCapture(event.pointerId); } if (event.button === 0 && event.ctrlKey === false && event.pointerType === "mouse" && !(event.target instanceof HTMLInputElement)) { event.preventDefault(); } } ) } ); } ); ComboboxAnchor.displayName = ANCHOR_NAME; var Anchor = ComboboxAnchor; var GROUP_NAME = "ComboboxGroup"; var [ComboboxGroupProvider, useComboboxGroupContext] = shared.createContext(GROUP_NAME); var ComboboxGroup = React__namespace.forwardRef( (props, forwardedRef) => { const { forceMount = false, ...groupProps } = props; const id = shared.useId(); const labelId = `${id}label`; const context = useComboboxContext(GROUP_NAME); const isVisible = forceMount || !context.filterStore.search || context.filterStore.groups?.has(id); if (!isVisible) return null; return /* @__PURE__ */ React__namespace.createElement(ComboboxGroupProvider, { id, labelId, forceMount }, /* @__PURE__ */ React__namespace.createElement( shared.Primitive.div, { role: "group", id, "aria-labelledby": labelId, ...groupProps, ref: forwardedRef } )); } ); ComboboxGroup.displayName = GROUP_NAME; var Group = ComboboxGroup; // src/combobox-item.tsx var ITEM_NAME = "ComboboxItem"; var ITEM_SELECT_EVENT = `${ITEM_NAME}.Select.Event`; var [ComboboxItemProvider, useComboboxItemContext] = shared.createContext(ITEM_NAME); var ComboboxItem = React__namespace.forwardRef( (props, forwardedRef) => { const { value, label: labelProp, disabled, onSelect, ...itemProps } = props; const context = useComboboxContext(ITEM_NAME); const groupContext = useComboboxGroupContext(ITEM_NAME, true); const { label, onLabelChange } = shared.useLabel({ defaultValue: labelProp }); const itemRef = React__namespace.useRef(null); const composedRef = shared.useComposedRefs(forwardedRef, itemRef); const isPointerDownRef = React__namespace.useRef(false); const id = shared.useId(); const textId = `${id}text`; const isSelected = Array.isArray(context.value) ? context.value.includes(value) : context.value === value; const isDisabled = disabled || context.disabled || false; const onItemSelect = React__namespace.useCallback(() => { const itemElement = itemRef.current; if (!itemElement) return; if (onSelect) { const itemSelectEvent = new CustomEvent(ITEM_SELECT_EVENT, { bubbles: true }); itemElement.addEventListener( ITEM_SELECT_EVENT, () => onSelect?.(value), { once: true } ); shared.dispatchDiscreteCustomEvent(itemElement, itemSelectEvent); } if (context.multiple) { context.onInputValueChange(""); } else { const selectedLabel = label ?? itemElement.textContent ?? ""; context.onInputValueChange(selectedLabel); context.onSelectedTextChange(selectedLabel); context.onHighlightedItemChange(null); context.onOpenChange(false); } context.filterStore.search = ""; context.onValueChange(value); context.inputRef.current?.focus(); }, [ label, value, onSelect, context.multiple, context.onInputValueChange, context.onHighlightedItemChange, context.onOpenChange, context.onSelectedTextChange, context.onValueChange, context.inputRef, context.filterStore ]); shared.useIsomorphicLayoutEffect(() => { if (value === "") { throw new Error(`${ITEM_NAME} value cannot be an empty string`); } return context.onItemRegister( { ref: itemRef, label, value, disabled: isDisabled, onSelect }, groupContext?.id ); }, [ label, value, isDisabled, onSelect, groupContext?.id, context.onItemRegister ]); const isVisible = context.getIsItemVisible(value); if (!isVisible) return null; return /* @__PURE__ */ React__namespace.createElement( ComboboxItemProvider, { value, isSelected, disabled, textId, onItemLabelChange: onLabelChange }, /* @__PURE__ */ React__namespace.createElement( shared.Primitive.div, { role: "option", id, "aria-selected": isSelected, "aria-disabled": isDisabled, "aria-labelledby": textId, ...{ [shared.DATA_ITEM_ATTR]: "" }, "data-state": isSelected ? "checked" : "unchecked", "data-highlighted": context.highlightedItem?.ref.current?.id === id ? "" : void 0, "data-disabled": isDisabled ? "" : void 0, tabIndex: disabled ? void 0 : -1, ...itemProps, ref: composedRef, onClick: shared.composeEventHandlers(itemProps.onClick, (event) => { if (isDisabled || context.readOnly) return; event?.currentTarget.focus(); onItemSelect(); }), onPointerDown: shared.composeEventHandlers( itemProps.onPointerDown, (event) => { if (isDisabled) return; isPointerDownRef.current = true; const target = event.target; if (!(target instanceof HTMLElement)) return; if (target.hasPointerCapture(event.pointerId)) { target.releasePointerCapture(event.pointerId); } if (event.button === 0 && event.ctrlKey === false && event.pointerType === "mouse") { event.preventDefault(); } } ), onPointerUp: shared.composeEventHandlers(itemProps.onPointerUp, (event) => { if (!isPointerDownRef.current) event.currentTarget?.click(); isPointerDownRef.current = false; }), onPointerMove: shared.composeEventHandlers(itemProps.onPointerMove, () => { if (isDisabled) return; context.onHighlightedItemChange({ ref: itemRef, label, value, disabled: isDisabled }); }) } ) ); } ); ComboboxItem.displayName = ITEM_NAME; var Item = ComboboxItem; // src/combobox-input.tsx var INPUT_NAME = "ComboboxInput"; var ComboboxInput = React__namespace.forwardRef( (props, forwardedRef) => { const context = useComboboxContext(INPUT_NAME); const composedRef = shared.useComposedRefs(forwardedRef, context.inputRef); const onChange = React__namespace.useCallback( (event) => { if (context.disabled || context.readOnly) return; if (!context.open) context.onOpenChange(true); const value = event.target.value; const trimmedValue = value.trim(); requestAnimationFrame(() => { context.onInputValueChange(value); if (trimmedValue === "") { context.onValueChange(trimmedValue); context.onHighlightedItemChange(null); } context.filterStore.search = trimmedValue; context.onItemsFilter(); }); }, [ context.open, context.onOpenChange, context.filterStore, context.onItemsFilter, context.onInputValueChange, context.onValueChange, context.onHighlightedItemChange, context.disabled, context.readOnly ] ); const onFocus = React__namespace.useCallback(() => { if (context.openOnFocus && !context.open && !context.readOnly) { context.onOpenChange(true); } }, [ context.openOnFocus, context.open, context.readOnly, context.onOpenChange ]); const onBlur = React__namespace.useCallback(() => { if (!context.multiple && context.value) { context.onInputValueChange(context.selectedText); return; } if (context.inputValue && !context.preserveInputOnBlur) { context.onInputValueChange(""); context.onHighlightedItemChange(null); } if (context.multiple) { context.onHighlightedBadgeIndexChange(-1); } }, [ context.multiple, context.value, context.preserveInputOnBlur, context.onInputValueChange, context.onHighlightedItemChange, context.inputValue, context.selectedText, context.onHighlightedBadgeIndexChange ]); const onKeyDown = React__namespace.useCallback( (event) => { function onHighlightMove(direction) { if (direction === "selected" && context.value.length > 0) { context.onHighlightMove("selected"); } else if (direction === "selected") { context.onHighlightMove("first"); } else { context.onHighlightMove(direction); } } function onItemSelect() { if (context.disabled || context.readOnly || !context.highlightedItem) return; const { value, label, onSelect } = context.highlightedItem; if (!value) return; const itemElement = context.highlightedItem.ref.current; if (itemElement && onSelect) { const itemSelectEvent = new CustomEvent(ITEM_SELECT_EVENT, { bubbles: true }); itemElement.addEventListener( ITEM_SELECT_EVENT, () => onSelect(value), { once: true } ); shared.dispatchDiscreteCustomEvent(itemElement, itemSelectEvent); } if (context.multiple) { context.onInputValueChange(""); } else { context.onInputValueChange(label); context.onSelectedTextChange(label); context.onHighlightedItemChange(null); context.onOpenChange(false); } context.filterStore.search = ""; context.onValueChange(value); } function onMenuOpen(direction) { if (context.open) return; context.onOpenChange(true); requestAnimationFrame(() => { if (direction) onHighlightMove(direction); }); } function onMenuClose() { if (!context.open) return; context.onOpenChange(false); context.onHighlightedItemChange(null); } const isNavigationKey = [ "ArrowDown", "ArrowUp", "Home", "End", "Enter", "Escape", "Tab", "PageUp", "PageDown" ].includes(event.key); if (isNavigationKey && event.key !== "Tab") event.preventDefault(); switch (event.key) { case "Enter": if (context.multiple && context.hasBadgeList && context.highlightedBadgeIndex > -1) { const valueToRemove = context.value[context.highlightedBadgeIndex]; if (valueToRemove) { context.onItemRemove(valueToRemove); context.onHighlightedBadgeIndexChange(-1); return; } } if (!context.open) { if (context.inputValue.trim()) { onMenuOpen(); } else if (!context.multiple && context.value) { context.onInputValueChange(context.selectedText); } return; } if (!context.highlightedItem) { if (!context.multiple && context.value) { context.onInputValueChange(context.selectedText); } else { context.onInputValueChange(""); } context.onOpenChange(false); return; } onItemSelect(); break; case "ArrowDown": if (context.open) { onHighlightMove(context.highlightedItem ? "next" : "first"); } else { onMenuOpen(context.value.length > 0 ? "selected" : "first"); } break; case "ArrowUp": if (context.open) { onHighlightMove(context.highlightedItem ? "prev" : "last"); } else { onMenuOpen(context.value.length > 0 ? "selected" : "last"); } break; case "ArrowLeft": { if (!context.multiple || !context.hasBadgeList) return; const input = event.currentTarget; const isAtStart = input.selectionStart === 0 && input.selectionEnd === 0; if (!isAtStart) return; if (context.open && isAtStart) { context.onHighlightedItemChange(null); const values = Array.isArray(context.value) ? context.value : []; if (values.length > 0) { event.preventDefault(); context.onOpenChange(false); requestAnimationFrame(() => { context.onHighlightedBadgeIndexChange(values.length - 1); }); } } else if (!context.open && context.highlightedBadgeIndex > -1) { event.preventDefault(); context.onHighlightedBadgeIndexChange( Math.max(0, context.highlightedBadgeIndex - 1) ); } else if (!context.open && isAtStart) { const values = Array.isArray(context.value) ? context.value : []; if (values.length > 0) { event.preventDefault(); context.onHighlightedBadgeIndexChange(values.length - 1); } } break; } case "ArrowRight": { if (!context.multiple || !context.hasBadgeList) return; const input = event.currentTarget; const isAtEnd = input.selectionStart === input.value.length && input.selectionEnd === input.value.length; if (!isAtEnd) return; if (!context.open && context.highlightedBadgeIndex > -1) { event.preventDefault(); const values = Array.isArray(context.value) ? context.value : []; if (context.highlightedBadgeIndex < values.length - 1) { context.onHighlightedBadgeIndexChange( context.highlightedBadgeIndex + 1 ); } else { context.onHighlightedBadgeIndexChange(-1); event.currentTarget.focus(); } } break; } case "Home": if (context.open) onHighlightMove("first"); break; case "End": if (context.open) onHighlightMove("last"); break; case "PageUp": if (context.modal && context.open) onHighlightMove("prev"); break; case "PageDown": if (context.modal && context.open) onHighlightMove("next"); break; case "Tab": if (context.open && context.modal) { event.preventDefault(); return; } onMenuClose(); break; case "Backspace": case "Delete": if (context.multiple && context.hasBadgeList && !context.inputValue && Array.isArray(context.value) && context.value.length > 0) { if (context.highlightedBadgeIndex > -1) { const valueToRemove = context.value[context.highlightedBadgeIndex]; if (valueToRemove) { context.onItemRemove(valueToRemove); const newIndex = Math.max( 0, context.highlightedBadgeIndex - 1 ); context.onHighlightedBadgeIndexChange( context.value.length > 1 ? newIndex : -1 ); } } else { const lastValue = context.value[context.value.length - 1]; if (lastValue) { context.onItemRemove(lastValue); } } } break; case "Escape": if (context.value.length > 0 && !context.multiple) { context.onInputValueChange(context.selectedText); } else { context.onInputValueChange(""); } onMenuClose(); break; } }, [ context.open, context.onOpenChange, context.inputValue, context.onInputValueChange, context.onHighlightedItemChange, context.value, context.highlightedItem, context.onHighlightMove, context.selectedText, context.highlightedBadgeIndex, context.onHighlightedBadgeIndexChange, context.onItemRemove, context.onSelectedTextChange, context.onValueChange, context.filterStore, context.disabled, context.hasBadgeList, context.modal, context.multiple, context.readOnly ] ); return /* @__PURE__ */ React__namespace.createElement( shared.Primitive.input, { role: "combobox", id: context.inputId, autoCapitalize: "off", autoComplete: "off", autoCorrect: "off", spellCheck: "false", "aria-expanded": context.open, "aria-controls": context.listId, "aria-labelledby": context.labelId, "aria-autocomplete": "list", "aria-activedescendant": context.highlightedItem?.ref?.current?.id, "aria-disabled": context.disabled, "aria-readonly": context.readOnly, dir: context.dir, disabled: context.disabled, readOnly: context.readOnly, ...props, ref: composedRef, value: context.inputValue, onChange: shared.composeEventHandlers(props.onChange, onChange), onFocus: shared.composeEventHandlers(props.onFocus, onFocus), onKeyDown: shared.composeEventHandlers(props.onKeyDown, onKeyDown), onBlur: shared.composeEventHandlers(props.onBlur, onBlur) } ); } ); ComboboxInput.displayName = INPUT_NAME; var Input = ComboboxInput; var TRIGGER_NAME = "ComboboxTrigger"; var ComboboxTrigger = React__namespace.forwardRef((props, forwardedRef) => { const { disabled, ...triggerProps } = props; const context = useComboboxContext(TRIGGER_NAME); const isDisabled = disabled || context.disabled; return /* @__PURE__ */ React__namespace.createElement( shared.Primitive.button, { type: "button", "aria-haspopup": "listbox", "aria-expanded": context.open, "aria-controls": context.listId, "data-state": context.open ? "open" : "closed", "data-disabled": isDisabled ? "" : void 0, dir: context.dir, disabled: isDisabled, tabIndex: isDisabled ? void 0 : -1, ...triggerProps, ref: forwardedRef, onClick: shared.composeEventHandlers(triggerProps.onClick, async () => { const newOpenState = !context.open; context.onOpenChange(newOpenState); await new Promise((resolve) => requestAnimationFrame(resolve)); const input = context.inputRef.current; if (input) { input.focus(); const length = input.value.length; input.setSelectionRange(length, length); } if (!newOpenState) return; if (context.value.length > 0) { context.onHighlightMove("selected"); return; } if (context.autoHighlight && !context.open) { context.onHighlightMove("first"); } }), onPointerDown: shared.composeEventHandlers( triggerProps.onPointerDown, (event) => { if (context.disabled) return; const target = event.target; if (!(target instanceof Element)) return; if (target.hasPointerCapture(event.pointerId)) { target.releasePointerCapture(event.pointerId); } if (event.button === 0 && event.ctrlKey === false && event.pointerType === "mouse" && !(event.target instanceof HTMLInputElement)) { event.preventDefault(); } } ) } ); }); ComboboxTrigger.displayName = TRIGGER_NAME; var Trigger = ComboboxTrigger; var BADGE_LIST_NAME = "ComboboxBadgeList"; var [ComboboxBadgeListProvider, useComboboxBadgeListContext] = shared.createContext(BADGE_LIST_NAME); var ComboboxBadgeList = React__namespace.forwardRef((props, forwardedRef) => { const { forceMount = false, orientation = "horizontal", ...badgeListProps } = props; const context = useComboboxContext(BADGE_LIST_NAME); const values = Array.isArray(context.value) ? context.value : []; const composedRef = shared.useComposedRefs(forwardedRef, (node) => { context.onHasBadgeListChange(!!node); }); if (!forceMount && (!context.multiple || values.length === 0)) { return null; } return /* @__PURE__ */ React__namespace.createElement( ComboboxBadgeListProvider, { orientation, badgeCount: values.length }, /* @__PURE__ */ React__namespace.createElement( shared.Primitive.div, { role: "listbox", "aria-multiselectable": context.multiple, "aria-orientation": orientation, "data-orientation": orientation, ...badgeListProps, ref: composedRef } ) ); }); ComboboxBadgeList.displayName = BADGE_LIST_NAME; var BadgeList = ComboboxBadgeList; var BADGE_ITEM_NAME = "ComboboxBadgeItem"; var [ComboboxBadgeItemProvider, useComboboxBadgeItemContext] = shared.createContext(BADGE_ITEM_NAME); var ComboboxBadgeItem = React__namespace.forwardRef((props, forwardedRef) => { const { value, disabled, ...badgeItemProps } = props; const id = shared.useId(); const context = useComboboxContext(BADGE_ITEM_NAME); const badgeListContext = useComboboxBadgeListContext(BADGE_ITEM_NAME); const index = Array.isArray(context.value) ? context.value.indexOf(value) : -1; const isHighlighted = index === context.highlightedBadgeIndex; const position = index + 1; const isDisabled = disabled || context.disabled; return /* @__PURE__ */ React__namespace.createElement( ComboboxBadgeItemProvider, { value, id, isHighlighted, position, disabled: isDisabled }, /* @__PURE__ */ React__namespace.createElement( shared.Primitive.div, { role: "option", id, "aria-selected": isHighlighted, "aria-disabled": isDisabled, "aria-orientation": badgeListContext.orientation, "aria-posinset": position, "aria-setsize": badgeListContext.badgeCount, "data-disabled": isDisabled ? "" : void 0, "data-highlighted": isHighlighted ? "" : void 0, "data-orientation": badgeListContext.orientation, ...badgeItemProps, ref: forwardedRef, onFocus: shared.composeEventHandlers(props.onFocus, () => { if (!isDisabled) { context.onHighlightedBadgeIndexChange(index); } }), onBlur: shared.composeEventHandlers(props.onBlur, () => { if (context.highlightedBadgeIndex === index) { context.onHighlightedBadgeIndexChange(-1); } }) } ) ); }); ComboboxBadgeItem.displayName = BADGE_ITEM_NAME; var BadgeItem = ComboboxBadgeItem; var BADGE_ITEM_DELETE_NAME = "ComboboxBadgeItemDelete"; var ComboboxBadgeItemDelete = React__namespace.forwardRef((props, forwardedRef) => { const context = useComboboxContext(BADGE_ITEM_DELETE_NAME); const badgeItemContext = useComboboxBadgeItemContext(BADGE_ITEM_DELETE_NAME); const buttonRef = React__namespace.useRef(null); const composedRef = shared.useComposedRefs(forwardedRef, buttonRef); return /* @__PURE__ */ React__namespace.createElement( shared.Primitive.button, { type: "button", "aria-controls": badgeItemContext.id, "aria-disabled": badgeItemContext.disabled, "data-disabled": badgeItemContext.disabled ? "" : void 0, "data-highlighted": badgeItemContext.isHighlighted ? "" : void 0, tabIndex: badgeItemContext.disabled ? void 0 : -1, ...props, ref: composedRef, onClick: shared.composeEventHandlers(props.onClick, (event) => { if (badgeItemContext.disabled) return; event.stopPropagation(); context.onItemRemove(badgeItemContext.value); requestAnimationFrame(() => { context.inputRef.current?.focus(); }); }), onPointerDown: shared.composeEventHandlers(props.onPointerDown, (event) => { if (badgeItemContext.disabled) return; const target = event.target; if (!(target instanceof Element)) return; if (target.hasPointerCapture(event.pointerId)) { target.releasePointerCapture(event.pointerId); } if (event.button === 0 && event.ctrlKey === false && event.pointerType === "mouse") { event.preventDefault(); } }) } ); }); ComboboxBadgeItemDelete.displayName = BADGE_ITEM_DELETE_NAME; var BadgeItemDelete = ComboboxBadgeItemDelete; var CANCEL_NAME = "ComboboxCancel"; var ComboboxCancel = React__namespace.forwardRef( (props, forwardedRef) => { const { forceMount = false, disabled, ...cancelProps } = props; const context = useComboboxContext(CANCEL_NAME); const isDisabled = disabled || context.disabled; if (!forceMount && !context.inputValue) return null; return /* @__PURE__ */ React__namespace.createElement( shared.Primitive.button, { type: "button", "aria-controls": context.inputId, "data-disabled": isDisabled ? "" : void 0, disabled: isDisabled, ...cancelProps, ref: forwardedRef, onClick: shared.composeEventHandlers(cancelProps.onClick, () => { context.onInputValueChange(""); context.filterStore.search = ""; requestAnimationFrame(() => { context.inputRef.current?.focus(); }); }), onPointerDown: shared.composeEventHandlers( cancelProps.onPointerDown, (event) => { if (isDisabled) return; const target = event.target; if (!(target instanceof Element)) return; if (target.hasPointerCapture(event.pointerId)) { target.releasePointerCapture(event.pointerId); } if (event.button === 0 && event.ctrlKey === false && event.pointerType === "mouse") { event.preventDefault(); } } ) } ); } ); ComboboxCancel.displayName = CANCEL_NAME; var Cancel = ComboboxCancel; var PORTAL_NAME = "ComboboxPortal"; var ComboboxPortal = React__namespace.forwardRef( (props, forwardedRef) => { const { container, ...portalProps } = props; return /* @__PURE__ */ React__namespace.createElement( shared.Portal, { container, ...portalProps, ref: forwardedRef, asChild: true } ); } ); ComboboxPortal.displayName = PORTAL_NAME; var Portal = ComboboxPortal; var CONTENT_NAME = "ComboboxContent"; var [ComboboxContentProvider, useComboboxContentContext] = shared.createContext(CONTENT_NAME); var ComboboxContent = React__namespace.forwardRef( (props, forwardedRef) => { const { forceMount = false, side = "bottom", sideOffset = 4, align = "start", alignOffset = 0, arrowPadding = 0, collisionBoundary, collisionPadding, sticky = "partial", strategy = "absolute", avoidCollisions = true, fitViewport = false, hideWhenDetached = false, trackAnchor = true, onEscapeKeyDown, onPointerDownOutside, style, ...contentProps } = props; const context = useComboboxContext(CONTENT_NAME); const positionerContext = shared.useAnchorPositioner({ open: context.open, onOpenChange: context.onOpenChange, anchorRef: context.hasAnchor ? context.anchorRef : context.inputRef, side, sideOffset, align, alignOffset, arrowPadding, collisionBoundary, collisionPadding, sticky, strategy, avoidCollisions, fitViewport, hideWhenDetached, trackAnchor }); const composedRef = shared.useComposedRefs( forwardedRef, context.listRef, (node) => positionerContext.refs.setFloating(node) ); const composedStyle = React__namespace.useMemo(() => { return { ...style, ...positionerContext.floatingStyles, ...!context.open && forceMount ? { visibility: "hidden" } : {} }; }, [style, positionerContext.floatingStyles, context.open, forceMount]); shared.useDismiss({ enabled: context.open, onDismiss: () => context.onOpenChange(false), refs: [context.listRef, context.anchorRef], onFocusOutside: (event) => event.preventDefault(), onEscapeKeyDown, onPointerDownOutside, disableOutsidePointerEvents: context.open && context.modal, preventScrollDismiss: context.open }); shared.useScrollLock({ referenceElement: context.inputRef.current, enabled: context.open && context.modal }); return /* @__PURE__ */ React__namespace.createElement( ComboboxContentProvider, { side: positionerContext.side, align: positionerContext.align, onArrowChange: positionerContext.onArrowChange, arrowDisplaced: positionerContext.arrowDisplaced, arrowStyles: positionerContext.arrowStyles, forceMount }, /* @__PURE__ */ React__namespace.createElement( react.FloatingFocusManager, { context: positionerContext.context, modal: false, initialFocus: context.inputRef, returnFocus: false, disabled: !context.open, visuallyHiddenDismiss: true }, /* @__PURE__ */ React__namespace.createElement(shared.Presence, { present: forceMount || context.open }, /* @__PURE__ */ React__namespace.createElement( shared.Primitive.div, { "data-state": getDataState(context.open), role: "listbox", dir: context.dir, ...positionerContext.getFloatingProps(contentProps), ref: composedRef, style: composedStyle } )) ) ); } ); ComboboxContent.displayName = CONTENT_NAME; var Content = ComboboxContent; var ARROW_NAME = "ComboboxArrow"; var ComboboxArrow = React__namespace.forwardRef( (props, forwardedRef) => { const { width = 10, height = 5, ...arrowProps } = props; const context = useComboboxContext(ARROW_NAME); const contentContext = useComboboxContentContext(ARROW_NAME); if (!context.open) return null; return /* @__PURE__ */ React__namespace.createElement( "span", { ref: (node) => contentContext.onArrowChange(node), style: { ...contentContext.arrowStyles, visibility: contentContext.arrowDisplaced ? "hidden" : void 0 } }, /* @__PURE__ */ React__namespace.createElement( shared.Primitive.svg, { width, height, viewBox: "0 0 30 10", preserveAspectRatio: "none", "aria-hidden": contentContext.arrowDisplaced, "data-side": contentContext.side, "data-align": contentContext.align, "data-displaced": contentContext.arrowDisplaced ? "" : void 0, "data-state": getDataState(context.open), ...arrowProps, ref: forwardedRef, style: { ...arrowProps.style, // ensure the svg is measured correctly display: "block" } }, props.asChild ? props.children : /* @__PURE__ */ React__namespace.createElement("path", { d: "M0 10 L15 0 L30 10", fill: "currentColor" }) ) ); } ); ComboboxArrow.displayName = ARROW_NAME; var Arrow = ComboboxArrow; var LOADING_NAME = "ComboboxLoading"; var ComboboxLoading = React__namespace.forwardRef( (props, forwardedRef) => { const context = useComboboxContext(LOADING_NAME); if (!context.open) return null; const { value, max, label, ...progressProps } = props; const progress = shared.useProgress({ value, max }); if (progress.state === "complete") return null; return /* @__PURE__ */ React__namespace.createElement( shared.Primitive.div, { "aria-label": label, ...progress.progressProps, ...progressProps, ref: forwardedRef } ); } ); ComboboxLoading.displayName = LOADING_NAME; var Loading = ComboboxLoading; var EMPTY_NAME = "ComboboxEmpty"; var ComboboxEmpty = React__namespace.forwardRef( (props, forwardedRef) => { const { keepVisible = false, ...emptyProps } = props; const context = useComboboxContext(EMPTY_NAME); const isVisible = context.open && context.getIsListEmpty(keepVisible); if (!isVisible) return null; return /* @__PURE__ */ React__namespace.createElement( shared.Primitive.div, { role: "status", "aria-live": "polite", "aria-atomic": "true", "data-state": "empty", ...emptyProps, ref: forwardedRef } ); } ); ComboboxEmpty.displayName = EMPTY_NAME; var Empty = ComboboxEmpty; var GROUP_LABEL_NAME = "ComboboxGroupLabel"; var ComboboxGroupLabel = React__namespace.forwardRef((props, forwardedRef) => { const groupContext = useComboboxGroupContext(GROUP_LABEL_NAME); return /* @__PURE__ */ React__namespace.createElement(shared.Primitive.div, { id: groupContext.labelId, ...props, ref: forwardedRef }); }); ComboboxGroupLabel.displayName = GROUP_LABEL_NAME; var GroupLabel = ComboboxGroupLabel; var ITEM_INDICATOR_NAME = "ComboboxItemIndicator"; var ComboboxItemIndicator = React__namespace.forwardRef((props, forwardedRef) => { const { forceMount = false, ...indicatorProps } = props; const itemContext = useComboboxItemContext(ITEM_INDICATOR_NAME); if (!forceMount && !itemContext.isSelected) return null; return /* @__PURE__ */ React__namespace.createElement(shared.Primitive.span, { "aria-hidden": "true", ...indicatorProps, ref: forwardedRef }); }); ComboboxItemIndicator.displayName = ITEM_INDICATOR_NAME; var ItemIndicator = ComboboxItemIndicator; var ITEM_TEXT_NAME = "ComboboxItemText"; var ComboboxItemText = React__namespace.forwardRef((props, forwardedRef) => { const itemContext = useComboboxItemContext(ITEM_TEXT_NAME); const composedRef = shared.useComposedRefs( forwardedRef, itemContext.onItemLabelChange ); return /* @__PURE__ */ React__namespace.createElement(shared.Primitive.span, { id: itemContext.textId, ...props, ref: composedRef }); }); ComboboxItemText.displayName = ITEM_TEXT_NAME; var ItemText = ComboboxItemText; var SEPARATOR_NAME = "ComboboxSeparator"; var ComboboxSeparator = React__namespace.forwardRef((props, forwardedRef) => { const { keepVisible = false, ...separatorProps } = props; const context = useComboboxContext(SEPARATOR_NAME); const shouldRender = keepVisible || !context.filterStore.search; if (!shouldRender) return null; return /* @__PURE__ */ React__namespace.createElement( shared.Primitive.div, { role: "separator", "aria-hidden": "true", ...separatorProps, ref: forwardedRef } ); }); ComboboxSeparator.displayName = SEPARATOR_NAME; var Separator = ComboboxSeparator; exports.Anchor = Anchor; exports.Arrow = Arrow; exports.BadgeItem = BadgeItem; exports.BadgeItemDelete = BadgeItemDelete; exports.BadgeList = BadgeList; exports.Cancel = Cancel; exports.ComboboxAnchor = ComboboxAnchor; exports.ComboboxArrow = ComboboxArrow; exports.ComboboxBadgeItem = ComboboxBadgeItem; exports.ComboboxBadgeItemDelete = ComboboxBadgeItemDelete; exports.ComboboxBadgeList = ComboboxBadgeList; exports.ComboboxCancel = ComboboxCancel; exports.ComboboxContent = ComboboxContent; exports.ComboboxEmpty = ComboboxEmpty; exports.ComboboxGroup = ComboboxGroup; exports.ComboboxGroupLabel = ComboboxGroupLabel; exports.ComboboxInput = ComboboxInput; exports.ComboboxItem = ComboboxItem; exports.ComboboxItemIndicator = ComboboxItemIndicator; exports.ComboboxItemText = ComboboxItemText; exports.ComboboxLabel = ComboboxLabel; exports.ComboboxLoading = ComboboxLoading; exports.ComboboxPortal = ComboboxPortal; exports.ComboboxRoot = ComboboxRoot; exports.ComboboxSeparator = ComboboxSeparator; exports.ComboboxTrigger = ComboboxTrigger; exports.Content = Content; exports.Empty = Empty; exports.Group = Group; exports.GroupLabel = GroupLabel; exports.Input = Input; exports.Item = Item; exports.ItemIndicator = ItemIndicator; exports.ItemText = ItemText; exports.Label = Label; exports.Loading = Loading; exports.Portal = Portal; exports.Root = Root; exports.Separator = Separator; exports.Trigger = Trigger;