/* eslint-disable @typescript-eslint/no-deprecated */ 'use client'; import * as React from 'react'; import { DefaultInfoButtonIcon12, DefaultInfoButtonIcon16, DefaultInfoButtonIcon20 } from './DefaultInfoButtonIcons'; import { getIntrinsicElementProps, mergeCallbacks, useControllableState, slot, useMergedRefs, isHTMLElement, elementContains } from '@fluentui/react-utilities'; import { Popover, PopoverSurface } from '@fluentui/react-popover'; const infoButtonIconMap = { small: /*#__PURE__*/ React.createElement(DefaultInfoButtonIcon12, null), medium: /*#__PURE__*/ React.createElement(DefaultInfoButtonIcon16, null), large: /*#__PURE__*/ React.createElement(DefaultInfoButtonIcon20, null) }; const popoverSizeMap = { small: 'small', medium: 'small', large: 'medium' }; /** * Create the state required to render InfoButton. * * The returned state can be modified with hooks such as useInfoButtonStyles_unstable, * before being passed to renderInfoButton_unstable. * * @param props - props from this instance of InfoButton * @param ref - reference to root HTMLElement of InfoButton * * @deprecated use {@link @fluentui/react-components#InfoLabel} from `\@fluentui/react-components` or `\@fluentui/react-infolabel` instead */ export const useInfoButton_unstable = (props, ref)=>{ const { size = 'medium', inline = true, popover, info, ...rest } = props; const state = { inline, size, components: { root: 'button', popover: Popover, info: PopoverSurface }, root: slot.always(getIntrinsicElementProps('button', { children: infoButtonIconMap[size], type: 'button', 'aria-label': 'information', ...rest, // FIXME: // `ref` is wrongly assigned to be `HTMLElement` instead of `HTMLButtonElement` // but since it would be a breaking change to fix it, we are casting ref to it's proper type ref: ref }), { elementType: 'button' }), popover: slot.always(popover, { defaultProps: { inline, positioning: 'above-start', size: popoverSizeMap[size], withArrow: true }, elementType: Popover }), info: slot.always(info, { defaultProps: { role: 'note', tabIndex: -1 }, elementType: PopoverSurface }) }; const [popoverOpen, setPopoverOpen] = useControllableState({ state: state.popover.open, defaultState: state.popover.defaultOpen, initialState: false }); state.popover.open = popoverOpen; state.popover.onOpenChange = mergeCallbacks(state.popover.onOpenChange, (e, data)=>setPopoverOpen(data.open)); const focusOutRef = React.useCallback((el)=>{ if (!el) { return; } el.addEventListener('focusout', (e)=>{ const nextFocused = e.relatedTarget; if (isHTMLElement(nextFocused) && !elementContains(el, nextFocused)) { setPopoverOpen(false); } }); }, [ setPopoverOpen ]); state.info.ref = useMergedRefs(state.info.ref, focusOutRef); return state; };