{"version":3,"sources":["../src/components/Dropdown/useListboxSlot.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { type FieldControlProps, useFieldControlProps_unstable } from '@fluentui/react-field';\nimport type { DropdownOpenEvents } from '@fluentui/react-combobox';\nimport {\n  mergeCallbacks,\n  useId,\n  useEventCallback,\n  slot,\n  isResolvedShorthand,\n  useIsomorphicLayoutEffect,\n  useMergedRefs,\n} from '@fluentui/react-utilities';\nimport type { ExtractSlotProps, Slot, SlotComponentType } from '@fluentui/react-utilities';\nimport type { DropdownState } from './Dropdown.types';\nimport { Listbox } from './Listbox';\nimport type { ListboxProps } from './Listbox';\n\nexport type UseListboxSlotState = Pick<DropdownState, 'multiselect' | 'open' | 'setOpen'>;\n\ntype UseListboxSlotOptions = {\n  state: UseListboxSlotState;\n  triggerRef:\n    | React.RefObject<HTMLInputElement | null>\n    | React.RefObject<HTMLButtonElement | null>\n    | React.RefObject<HTMLButtonElement | HTMLInputElement | null>;\n  defaultProps?: Partial<ListboxProps>;\n};\n\n/**\n * @internal\n * @returns  listbox slot with desired behavior and props\n */\nexport function useListboxSlot(\n  listboxSlotFromProp: Slot<typeof Listbox> | undefined,\n  ref: React.Ref<HTMLDivElement>,\n  options: UseListboxSlotOptions,\n): SlotComponentType<ExtractSlotProps<Slot<typeof Listbox>>> | undefined {\n  const {\n    state: { multiselect, open, setOpen },\n    triggerRef,\n    defaultProps,\n  } = options;\n\n  const listboxId = useId(\n    'fluent-listbox',\n    isResolvedShorthand(listboxSlotFromProp) ? listboxSlotFromProp.id : undefined,\n  );\n\n  const listboxSlot = slot.optional(listboxSlotFromProp, {\n    renderByDefault: true,\n    elementType: Listbox,\n    defaultProps: {\n      id: listboxId,\n      multiselect,\n      tabIndex: undefined,\n      ...defaultProps,\n    },\n  });\n\n  const fieldControlProps = useFieldControlProps_unstable({ id: listboxId } as FieldControlProps, {\n    supportsLabelFor: true,\n  });\n\n  // Use the field's label to provide an accessible name for the listbox if it doesn't already have one\n  if (\n    listboxSlot &&\n    !listboxSlot['aria-label'] &&\n    !listboxSlot['aria-labelledby'] &&\n    fieldControlProps['aria-labelledby']\n  ) {\n    listboxSlot['aria-labelledby'] = fieldControlProps['aria-labelledby'];\n  }\n\n  /**\n   * Clicking on the listbox should never blur the trigger\n   * in a combobox\n   */\n  const onMouseDown = useEventCallback(\n    mergeCallbacks((event: React.MouseEvent<HTMLDivElement>) => {\n      event.preventDefault();\n    }, listboxSlot?.onMouseDown),\n  );\n\n  const onClick = useEventCallback(\n    // eslint-disable-next-line react-hooks/refs\n    mergeCallbacks((event: React.MouseEvent<HTMLDivElement>) => {\n      event.preventDefault();\n      triggerRef.current?.focus();\n    }, listboxSlot?.onClick),\n  );\n\n  // Sync the native popover state with the internal `open` state. The internal ref captures the\n  // listbox DOM element so we can imperatively call `showPopover()` / `hidePopover()`.\n  const popoverRef = React.useRef<HTMLDivElement>(null);\n  const listboxRef = useMergedRefs(listboxSlot?.ref, ref, popoverRef);\n  if (listboxSlot) {\n    listboxSlot.ref = listboxRef;\n    listboxSlot.onMouseDown = onMouseDown;\n    listboxSlot.onClick = onClick;\n  }\n\n  const onListboxToggle = useEventCallback((event: Event & { newState?: 'open' | 'closed' }) => {\n    const nextOpen = event.newState === 'open';\n    if (nextOpen === open) {\n      return;\n    }\n    setOpen(event as unknown as DropdownOpenEvents, nextOpen);\n  });\n\n  useIsomorphicLayoutEffect(() => {\n    const el = listboxRef.current;\n    if (!el) {\n      return;\n    }\n\n    el.addEventListener('toggle', onListboxToggle);\n\n    try {\n      if (open) {\n        el.showPopover();\n      } else if (el.matches(':popover-open')) {\n        el.hidePopover();\n      }\n    } catch (error) {\n      if (process.env.NODE_ENV === 'development') {\n        // eslint-disable-next-line no-console\n        console.warn(\n          [\n            'Popover API is not supported in this browser, and the listbox will not work correctly.',\n            'Please include a popover polyfill for better browser support.',\n          ].join(' '),\n          { error },\n        );\n      }\n    }\n\n    return () => {\n      el.removeEventListener('toggle', onListboxToggle);\n    };\n  }, [listboxRef, open, onListboxToggle]);\n\n  return listboxSlot;\n}\n"],"names":["useListboxSlot","listboxSlotFromProp","ref","options","state","multiselect","open","setOpen","triggerRef","defaultProps","listboxId","useId","isResolvedShorthand","id","undefined","listboxSlot","slot","optional","renderByDefault","elementType","Listbox","tabIndex","fieldControlProps","useFieldControlProps_unstable","supportsLabelFor","onMouseDown","useEventCallback","mergeCallbacks","event","preventDefault","onClick","current","focus","popoverRef","React","useRef","listboxRef","useMergedRefs","onListboxToggle","nextOpen","newState","useIsomorphicLayoutEffect","el","addEventListener","showPopover","matches","hidePopover","error","process","env","NODE_ENV","console","warn","join","removeEventListener"],"mappings":"AAAA;;;;;+BAkCgBA;;;eAAAA;;;;iEAhCO;4BAC+C;gCAU/D;yBAGiB;AAkBjB,SAASA,eACdC,mBAAqD,EACrDC,GAA8B,EAC9BC,OAA8B;IAE9B,MAAM,EACJC,OAAO,EAAEC,WAAW,EAAEC,IAAI,EAAEC,OAAO,EAAE,EACrCC,UAAU,EACVC,YAAY,EACb,GAAGN;IAEJ,MAAMO,YAAYC,IAAAA,qBAAK,EACrB,kBACAC,IAAAA,mCAAmB,EAACX,uBAAuBA,oBAAoBY,EAAE,GAAGC;IAGtE,MAAMC,cAAcC,oBAAI,CAACC,QAAQ,CAAChB,qBAAqB;QACrDiB,iBAAiB;QACjBC,aAAaC,gBAAO;QACpBX,cAAc;YACZI,IAAIH;YACJL;YACAgB,UAAUP;YACV,GAAGL,YAAY;QACjB;IACF;IAEA,MAAMa,oBAAoBC,IAAAA,yCAA6B,EAAC;QAAEV,IAAIH;IAAU,GAAwB;QAC9Fc,kBAAkB;IACpB;IAEA,qGAAqG;IACrG,IACET,eACA,CAACA,WAAW,CAAC,aAAa,IAC1B,CAACA,WAAW,CAAC,kBAAkB,IAC/BO,iBAAiB,CAAC,kBAAkB,EACpC;QACAP,WAAW,CAAC,kBAAkB,GAAGO,iBAAiB,CAAC,kBAAkB;IACvE;IAEA;;;GAGC,GACD,MAAMG,cAAcC,IAAAA,gCAAgB,EAClCC,IAAAA,8BAAc,EAAC,CAACC;QACdA,MAAMC,cAAc;IACtB,GAAGd,aAAaU;IAGlB,MAAMK,UAAUJ,IAAAA,gCAAgB,EAC9B,4CAA4C;IAC5CC,IAAAA,8BAAc,EAAC,CAACC;QACdA,MAAMC,cAAc;QACpBrB,WAAWuB,OAAO,EAAEC;IACtB,GAAGjB,aAAae;IAGlB,8FAA8F;IAC9F,qFAAqF;IACrF,MAAMG,aAAaC,OAAMC,MAAM,CAAiB;IAChD,MAAMC,aAAaC,IAAAA,6BAAa,EAACtB,aAAab,KAAKA,KAAK+B;IACxD,IAAIlB,aAAa;QACfA,YAAYb,GAAG,GAAGkC;QAClBrB,YAAYU,WAAW,GAAGA;QAC1BV,YAAYe,OAAO,GAAGA;IACxB;IAEA,MAAMQ,kBAAkBZ,IAAAA,gCAAgB,EAAC,CAACE;QACxC,MAAMW,WAAWX,MAAMY,QAAQ,KAAK;QACpC,IAAID,aAAajC,MAAM;YACrB;QACF;QACAC,QAAQqB,OAAwCW;IAClD;IAEAE,IAAAA,yCAAyB,EAAC;QACxB,MAAMC,KAAKN,WAAWL,OAAO;QAC7B,IAAI,CAACW,IAAI;YACP;QACF;QAEAA,GAAGC,gBAAgB,CAAC,UAAUL;QAE9B,IAAI;YACF,IAAIhC,MAAM;gBACRoC,GAAGE,WAAW;YAChB,OAAO,IAAIF,GAAGG,OAAO,CAAC,kBAAkB;gBACtCH,GAAGI,WAAW;YAChB;QACF,EAAE,OAAOC,OAAO;YACd,IAAIC,QAAQC,GAAG,CAACC,QAAQ,KAAK,eAAe;gBAC1C,sCAAsC;gBACtCC,QAAQC,IAAI,CACV;oBACE;oBACA;iBACD,CAACC,IAAI,CAAC,MACP;oBAAEN;gBAAM;YAEZ;QACF;QAEA,OAAO;YACLL,GAAGY,mBAAmB,CAAC,UAAUhB;QACnC;IACF,GAAG;QAACF;QAAY9B;QAAMgC;KAAgB;IAEtC,OAAOvB;AACT"}