"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "useComboboxBaseState", { enumerable: true, get: function() { return useComboboxBaseState; } }); const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard"); const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react")); const _reactdom = /*#__PURE__*/ _interop_require_wildcard._(require("react-dom")); const _reactutilities = require("@fluentui/react-utilities"); const _useOptionCollection = require("../utils/useOptionCollection"); const _useSelection = require("../utils/useSelection"); const useComboboxBaseState = (props)=>{ 'use no memo'; const { appearance = 'outline', disableAutoFocus, children, clearable = false, editable = false, inlinePopup = false, mountNode = undefined, multiselect, onOpenChange, size = 'medium', activeDescendantController, freeform = false, disabled = false, onActiveOptionChange = null } = props; const optionCollection = (0, _useOptionCollection.useOptionCollection)(); const { getOptionsMatchingValue } = optionCollection; const { getOptionById } = optionCollection; const getActiveOption = _react.useCallback(()=>{ const activeOptionId = activeDescendantController.active(); return activeOptionId ? getOptionById(activeOptionId) : undefined; }, [ activeDescendantController, getOptionById ]); // Keeping some kind of backwards compatible functionality here // eslint-disable-next-line @typescript-eslint/naming-convention const UNSAFE_activeOption = getActiveOption(); // eslint-disable-next-line @typescript-eslint/naming-convention const UNSAFE_setActiveOption = _react.useCallback((option)=>{ let nextOption = undefined; if (typeof option === 'function') { const activeOption = getActiveOption(); nextOption = option(activeOption); } if (nextOption) { activeDescendantController.focus(nextOption.id); } else { activeDescendantController.blur(); } }, [ activeDescendantController, getActiveOption ]); // track whether keyboard focus outline should be shown // tabster/keyborg doesn't work here, since the actual keyboard focus target doesn't move const [focusVisible, setFocusVisible] = _react.useState(false); // track focused state to conditionally render collapsed listbox // when the trigger is focused - the listbox should but hidden until the open state is changed const [hasFocus, setHasFocus] = _react.useState(false); const ignoreNextBlur = _react.useRef(false); // calculate value based on props, internal value changes, and selected options const isFirstMount = (0, _reactutilities.useFirstMount)(); const [controllableValue, setValue] = (0, _reactutilities.useControllableState)({ state: props.value, initialState: undefined }); const { selectedOptions, selectOption: baseSelectOption, clearSelection } = (0, _useSelection.useSelection)(props); // reset any typed value when an option is selected const selectOption = _react.useCallback((ev, option)=>{ _reactdom.unstable_batchedUpdates(()=>{ setValue(undefined); baseSelectOption(ev, option); }); }, [ setValue, baseSelectOption ]); const value = _react.useMemo(()=>{ // don't compute the value if it is defined through props or setValue, if (controllableValue !== undefined) { return controllableValue; } // handle defaultValue here, so it is overridden by selection if (isFirstMount && props.defaultValue !== undefined) { return props.defaultValue; } const selectedOptionsText = getOptionsMatchingValue((optionValue)=>{ return selectedOptions.includes(optionValue); }).map((option)=>option.text); if (multiselect) { // editable inputs should not display multiple selected options in the input as text return editable ? '' : selectedOptionsText.join(', '); } return selectedOptionsText[0]; // do not change value after isFirstMount changes, // we do not want to accidentally override defaultValue on a second render // unless another value is intentionally set // eslint-disable-next-line react-hooks/exhaustive-deps }, [ controllableValue, editable, getOptionsMatchingValue, multiselect, props.defaultValue, selectedOptions ]); // Handle open state, which is shared with options in context const [open, setOpenState] = (0, _reactutilities.useControllableState)({ state: props.open, defaultState: props.defaultOpen, initialState: false }); const setOpen = _react.useCallback((event, newState)=>{ if (disabled) { return; } onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(event, { open: newState }); _reactdom.unstable_batchedUpdates(()=>{ if (!newState && !freeform) { setValue(undefined); } setOpenState(newState); }); }, [ onOpenChange, setOpenState, setValue, freeform, disabled ]); // update active option based on change in open state _react.useEffect(()=>{ if (open) { // if it is single-select and there is a selected option, start at the selected option if (!multiselect && selectedOptions.length > 0) { const selectedOption = getOptionsMatchingValue((v)=>v === selectedOptions[0]).pop(); if (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.id) { activeDescendantController.focus(selectedOption.id); } } } else { activeDescendantController.blur(); } // this should only be run in response to changes in the open state // eslint-disable-next-line react-hooks/exhaustive-deps }, [ open, activeDescendantController ]); // Fallback focus when children are updated in an open popover results in no item being focused _react.useEffect(()=>{ if (open && !disableAutoFocus && !activeDescendantController.active()) { activeDescendantController.first(); } // this should only be run in response to changes in the open state or children }, [ open, children, disableAutoFocus, activeDescendantController, getOptionById ]); const onActiveDescendantChange = (0, _reactutilities.useEventCallback)((event)=>{ const previousOption = event.detail.previousId ? optionCollection.getOptionById(event.detail.previousId) : null; const nextOption = optionCollection.getOptionById(event.detail.id); onActiveOptionChange === null || onActiveOptionChange === void 0 ? void 0 : onActiveOptionChange(event, { event, type: 'change', previousOption, nextOption }); }); return { ...optionCollection, freeform, disabled, selectOption, clearSelection, selectedOptions, activeOption: UNSAFE_activeOption, appearance, clearable, focusVisible, ignoreNextBlur, inlinePopup, mountNode, open, hasFocus, setActiveOption: UNSAFE_setActiveOption, setFocusVisible, setHasFocus, setOpen, setValue, size, value, multiselect, onOptionClick: (0, _reactutilities.useEventCallback)((e)=>{ if (!multiselect) { setOpen(e, false); } }), onActiveDescendantChange }; };