{"version":3,"sources":["../../../src/components/Combobox/useCombobox.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { mergeCallbacks, useEventCallback, useMergedRefs, slot } from '@fluentui/react-utilities';\nimport { useComboboxExpandIconSlot, useInputTriggerSlot } from '@fluentui/react-combobox';\nimport type { ComboboxProps, ComboboxState } from './Combobox.types';\nimport { Listbox } from '../Dropdown/Listbox';\nimport { toDataAttributeValue } from '../../utils';\nimport { useListboxPopupState } from '../Dropdown/useListboxPopupState';\n\nexport const useCombobox = (props: ComboboxProps, ref: React.Ref<HTMLInputElement>): ComboboxState => {\n  const { freeform } = props;\n\n  const {\n    props: mergedProps,\n    triggerRef,\n    activeParentRef,\n    activeDescendantController,\n    triggerNativeProps,\n    internalState,\n    listbox,\n    rootSlot,\n  } = useListboxPopupState<ComboboxProps, HTMLInputElement>(props, {\n    primarySlotTagName: 'input',\n    fieldControlOptions: { supportsLabelFor: true, supportsRequired: true },\n    // For multiselect, editable should be false to display comma-separated values in the trigger\n    // For single-select, editable is true to allow filtering\n    baseStateExtras: p => ({ editable: !p.multiselect }),\n  });\n\n  const { appearance: _appearance, size: _size, ...baseState } = internalState;\n  const { clearable, clearSelection, disabled, hasFocus, multiselect, open, selectedOptions } = baseState;\n  const expandIconRef = React.useRef<HTMLSpanElement>(null);\n\n  const triggerSlot = useInputTriggerSlot(mergedProps.input ?? {}, useMergedRefs(triggerRef, activeParentRef, ref), {\n    state: internalState,\n    freeform,\n    defaultProps: {\n      type: 'text',\n      value: baseState.value ?? '',\n      'aria-controls': open ? listbox?.id : undefined,\n      ...triggerNativeProps,\n    },\n    activeDescendantController,\n    shouldCloseOnBlur: event => !expandIconRef.current || event.relatedTarget !== expandIconRef.current,\n  });\n\n  const showClearIcon = selectedOptions.length > 0 && !disabled && clearable && !multiselect;\n  const placeholderVisible = !baseState.value && !!mergedProps.placeholder;\n\n  const state: ComboboxState = {\n    ...baseState,\n    components: { root: 'div', input: 'input', expandIcon: 'span', clearIcon: 'span', listbox: Listbox },\n    root: {\n      ...rootSlot,\n      'data-open': toDataAttributeValue(open),\n      'data-disabled': toDataAttributeValue(triggerSlot.disabled),\n      'data-placeholder': toDataAttributeValue(placeholderVisible),\n      'data-invalid': toDataAttributeValue(triggerSlot['aria-invalid']),\n      'data-clearable': toDataAttributeValue(showClearIcon),\n    },\n    input: triggerSlot,\n    listbox: open || hasFocus ? listbox : undefined,\n    clearIcon: slot.optional(mergedProps.clearIcon, {\n      defaultProps: { 'aria-hidden': 'true' },\n      elementType: 'span',\n      renderByDefault: true,\n    }),\n    expandIcon: useComboboxExpandIconSlot(mergedProps.expandIcon, {\n      disabled,\n      hideFromTabOrder: showClearIcon,\n      open,\n      'aria-label': mergedProps['aria-label'],\n      'aria-labelledby': mergedProps['aria-labelledby'],\n      triggerLabelledBy: triggerSlot['aria-labelledby'],\n    }),\n    showClearIcon,\n    activeDescendantController,\n  };\n\n  const openOnPointerDownRef = React.useRef<boolean | undefined>(undefined);\n\n  const onExpandIconMouseDown = useEventCallback(\n    // eslint-disable-next-line react-hooks/refs\n    mergeCallbacks(state.expandIcon?.onMouseDown, (event: React.MouseEvent<HTMLSpanElement>) => {\n      event.preventDefault();\n      openOnPointerDownRef.current = open;\n    }),\n  );\n\n  const onExpandIconClick = useEventCallback(\n    // eslint-disable-next-line react-hooks/refs\n    mergeCallbacks(state.expandIcon?.onClick, (event: React.MouseEvent<HTMLSpanElement>) => {\n      event.preventDefault();\n      // Click-only activation must not consume a canceled pointer gesture.\n      const wasOpenOnPointerDown = event.detail > 0 ? openOnPointerDownRef.current : undefined;\n      const nextOpen = !(wasOpenOnPointerDown ?? open);\n      openOnPointerDownRef.current = undefined;\n      // A pointer interaction that starts while open light-dismisses an auto popover on pointerup.\n      // Let the popover's toggle event issue the close notification so onOpenChange fires only once.\n      if (!disabled && (!wasOpenOnPointerDown || listbox?.popover === 'manual')) {\n        internalState.setOpen(event, nextOpen);\n      }\n      triggerRef.current?.focus();\n    }),\n  );\n\n  const onExpandIconKeyDown = useEventCallback(\n    // eslint-disable-next-line react-hooks/refs\n    mergeCallbacks(state.expandIcon?.onKeyDown, event => {\n      if (open && event.key === 'Escape') {\n        event.preventDefault();\n        event.stopPropagation();\n        internalState.setOpen(event, false);\n        triggerRef.current?.focus();\n        return;\n      }\n\n      if (!disabled && (event.key === 'Enter' || event.key === ' ')) {\n        event.preventDefault();\n        const nextOpen = !open;\n        internalState.setOpen(event, nextOpen);\n        triggerRef.current?.focus();\n      }\n    }),\n  );\n  const expandIconSlotRef = useMergedRefs(state.expandIcon?.ref, expandIconRef);\n\n  if (state.expandIcon) {\n    state.expandIcon.ref = expandIconSlotRef;\n    state.expandIcon.onMouseDown = onExpandIconMouseDown;\n    state.expandIcon.onClick = onExpandIconClick;\n    state.expandIcon.onKeyDown = onExpandIconKeyDown;\n  }\n\n  state.root.onBlur = mergeCallbacks(state.root.onBlur, event => {\n    if (!event.relatedTarget || !event.currentTarget.contains(event.relatedTarget)) {\n      if (event.target !== event.currentTarget.querySelector('input')) {\n        internalState.setOpen(event as unknown as React.FocusEvent<HTMLInputElement>, false);\n      }\n      internalState.setHasFocus(false);\n    }\n  });\n\n  const onClearIconMouseDown = useEventCallback(\n    mergeCallbacks(state.clearIcon?.onMouseDown, (ev: React.MouseEvent<HTMLSpanElement>) => {\n      ev.preventDefault();\n    }),\n  );\n  const onClearIconClick = useEventCallback(\n    // eslint-disable-next-line react-hooks/refs\n    mergeCallbacks(state.clearIcon?.onClick, (ev: React.MouseEvent<HTMLSpanElement>) => {\n      clearSelection(ev);\n      triggerRef.current?.focus();\n    }),\n  );\n\n  if (state.clearIcon) {\n    state.clearIcon.onMouseDown = onClearIconMouseDown;\n    state.clearIcon.onClick = onClearIconClick;\n  }\n\n  // Heads up! We don't support \"clearable\" in multiselect mode, so we should never display a slot\n  if (multiselect) {\n    state.clearIcon = undefined;\n  }\n\n  return state;\n};\n"],"names":["useCombobox","props","ref","freeform","mergedProps","triggerRef","activeParentRef","activeDescendantController","triggerNativeProps","internalState","listbox","rootSlot","useListboxPopupState","primarySlotTagName","fieldControlOptions","supportsLabelFor","supportsRequired","baseStateExtras","p","editable","multiselect","appearance","_appearance","size","_size","baseState","clearable","clearSelection","disabled","hasFocus","open","selectedOptions","expandIconRef","React","useRef","triggerSlot","useInputTriggerSlot","input","useMergedRefs","state","defaultProps","type","value","id","undefined","shouldCloseOnBlur","event","current","relatedTarget","showClearIcon","length","placeholderVisible","placeholder","components","root","expandIcon","clearIcon","Listbox","toDataAttributeValue","slot","optional","elementType","renderByDefault","useComboboxExpandIconSlot","hideFromTabOrder","triggerLabelledBy","openOnPointerDownRef","onExpandIconMouseDown","useEventCallback","mergeCallbacks","onMouseDown","preventDefault","onExpandIconClick","onClick","wasOpenOnPointerDown","detail","nextOpen","popover","setOpen","focus","onExpandIconKeyDown","onKeyDown","key","stopPropagation","expandIconSlotRef","onBlur","currentTarget","contains","target","querySelector","setHasFocus","onClearIconMouseDown","ev","onClearIconClick"],"mappings":"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"}