function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
import { ariaHideOutside } from '@react-aria/overlays';
import { useId, useLabels } from '@react-aria/utils';
import React from 'react';
var emptyObj = {};
var returnEmpty = function returnEmpty() {
  return {};
};
var a11yPresets = {
  haspopup: {
    getOverlayProps: function getOverlayProps(_ref) {
      var role = _ref.role,
        overlayId = _ref.overlayId;
      return {
        id: overlayId,
        role: role
      };
    },
    getTriggerProps: function getTriggerProps(_ref2) {
      var role = _ref2.role,
        isVisible = _ref2.isVisible,
        overlayId = _ref2.overlayId;
      return {
        'aria-expanded': isVisible,
        'aria-controls': isVisible ? overlayId : undefined,
        'aria-haspopup': role
      };
    }
  },
  tooltip: {
    getOverlayProps: function getOverlayProps(_ref3) {
      var overlayId = _ref3.overlayId;
      return {
        role: 'tooltip',
        id: overlayId
      };
    },
    getTriggerProps: function getTriggerProps(_ref4) {
      var isVisible = _ref4.isVisible,
        overlayId = _ref4.overlayId;
      return isVisible ? {
        'aria-describedby': overlayId
      } : {};
    }
  }
};
export function getA11yPreset(role) {
  switch (role) {
    case 'dialog':
    case 'listbox':
    case 'menu':
      return a11yPresets.haspopup;
    case 'tooltip':
      return a11yPresets.tooltip;
    case 'none':
      return {
        getOverlayProps: function () {
          return {
            role: 'none'
          };
        },
        getTriggerProps: returnEmpty
      };
    default:
      return {
        getOverlayProps: returnEmpty,
        getTriggerProps: returnEmpty
      };
  }
}
/**
 * Manages labelling for an element and the other DOM. Defaults an ID for `aria-labelledby` usage.
 *
 * When `aria-label` and `aria-labelledby` both exist, it combines them into `aria-labelledby` for a screen reader chain.
 * @link [W3 naming with aria-labelledby](https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/#naming_with_aria-labelledby)
 */
export function useLabelled(props) {
  var _ref5 = props || emptyObj,
    ariaDescribedby = _ref5['aria-describedby'],
    ariaDetails = _ref5['aria-details'],
    ariaLabelledby = _ref5['aria-labelledby'],
    ariaLabel = _ref5['aria-label'],
    id = _ref5.id;
  var ariaLabelOnly = ariaLabel && !ariaLabelledby;

  // Generate an ID. We want to use this unless they are using only aria-label
  var labelledId = useId(ariaLabelledby);

  // Merges aria-label and aria-labelledby into aria-labelledby when both exist
  var widgetId = useId(id);
  var fieldProps = useLabels({
    'aria-label': ariaLabel,
    'aria-labelledby': ariaLabelOnly ? undefined : labelledId,
    id: widgetId
  });
  return {
    descriptionProps: {
      id: ariaDescribedby
    },
    labelProps: {
      id: ariaLabelOnly ? undefined : labelledId
    },
    widgetProps: _objectSpread(_objectSpread({}, fieldProps), {}, {
      'aria-describedby': ariaDescribedby,
      'aria-details': ariaDetails
    })
  };
}

/**
 * Cover the label links for the trigger (button), the popup element (dialog), and the popup element title (heading).
 * Similar to [React Aria useOverlayTrigger](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-aria/overlays/src/useOverlayTrigger.ts)
 * but with element title support.
 * @link [MDN aria-haspopup](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-haspopup)
 */
export function useLabelledPopup(_ref6) {
  var _getA11yPreset$getTri, _getA11yPreset, _getA11yPreset$getOve, _getA11yPreset2;
  var ariaDescribedby = _ref6['aria-describedby'],
    ariaDetails = _ref6['aria-details'],
    ariaLabelledby = _ref6['aria-labelledby'],
    ariaLabel = _ref6['aria-label'],
    id_ = _ref6.id,
    isOpen = _ref6.isOpen,
    _ref6$type = _ref6.type,
    type = _ref6$type === void 0 ? 'button' : _ref6$type,
    popupRole = _ref6.popupRole,
    popupId_ = _ref6.popupId;
  /** Web spec default for aria-haspopup=true is menu, unless element has role combobox, which have an implicit aria-haspopup value of listbox. */
  // const popupRole = popupRole_ || type === 'combobox' ? 'listbox' : 'menu'
  var id = useId(id_);
  var popupId = useId(popupId_);
  var presetArgs = {
    isVisible: isOpen,
    role: popupRole,
    overlayId: popupId
  };
  var triggerProps = (_getA11yPreset$getTri = (_getA11yPreset = getA11yPreset(popupRole)).getTriggerProps) === null || _getA11yPreset$getTri === void 0 ? void 0 : _getA11yPreset$getTri.call(_getA11yPreset, presetArgs);
  var overlayProps = (_getA11yPreset$getOve = (_getA11yPreset2 = getA11yPreset(popupRole)).getOverlayProps) === null || _getA11yPreset$getOve === void 0 ? void 0 : _getA11yPreset$getOve.call(_getA11yPreset2, presetArgs);
  var _useLabelled = useLabelled({
      'aria-describedby': ariaDescribedby,
      'aria-details': ariaDetails,
      'aria-labelledby': ariaLabelledby,
      'aria-label': ariaLabel,
      id: id
    }),
    labelProps = _useLabelled.labelProps,
    widgetProps = _useLabelled.widgetProps;
  return {
    labelProps: labelProps,
    popupProps: _objectSpread(_objectSpread({
      role: popupRole
    }, widgetProps), overlayProps),
    triggerProps: triggerProps
  };
}

/**
 * For dialog experiences:
 * - Has role dialog and aria linked title props
 * - Focus management props to work with FocusScope
 *
 * For modal dialog experiences (full screen locked experiences):
 * - Hides old and new content outside with aria-hidden with ariaHideOutside (like aria-modal)
 * - (it will in breaking) Prevent scroll
 *
 * For either experiences, you still MUST support:
 * - have Escape key to close (It should!)
 * - have click outside, like scrim click
 *
 * _More about 'modal dialog' and `isModal` not using `aria-modal`:_
 * Setting aria-modal="true" tells assistive technologies to let the user know the ability to interact with,
 * or access other content on the page requires the modal dialog to be closed or otherwise lose focus.
 *  Modal dialogs are when content is displayed and the user's interaction is limited to only that section until it is dismissed.
 * [MDN aria modal](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-modal).
 * To support the most, like Narrator in Edge, Core React uses `ariaHideOutside` to set `aria-hidden` on
 * all elements outside the dialog, and **all elements outside added while opened**, so the dialog will act as a
 * _modal_ even without `aria-modal` on the dialog itself. See Future Considerations below.
 * [Screen Reader aria modal support table](https://a11ysupport.io/tech/aria/aria-modal_attribute) - [MS Narrator Edge aria modal support](https://a11ysupport.io/tests/apg__modal-dialog-example/aria__aria-modal_attribute/convey_presence/narrator/edge)
 * _Future Considerations:_ Replace ariaHideOutside with aria-modal="true".
 * Using aria-modal, then we would need to involve Portal and so tooltips
 * or Toasts could mount within the visible aria-modal container.
 */

export function useModalDialogLike(_ref7) {
  var ariaDescribedby = _ref7['aria-describedby'],
    ariaDetails = _ref7['aria-details'],
    ariaLabelledby = _ref7['aria-labelledby'],
    ariaLabel = _ref7['aria-label'],
    id = _ref7.id,
    isModal = _ref7.isModal,
    isOpen = _ref7.isOpen,
    ref = _ref7.ref,
    _ref7$role = _ref7.role,
    role = _ref7$role === void 0 ? 'dialog' : _ref7$role;
  var _useLabelled2 = useLabelled({
      'aria-describedby': ariaDescribedby,
      'aria-details': ariaDetails,
      'aria-labelledby': ariaLabelledby,
      'aria-label': ariaLabel
    }),
    labelProps = _useLabelled2.labelProps,
    widgetProps = _useLabelled2.widgetProps;
  var dialogProps = _objectSpread(_objectSpread({}, widgetProps), {}, {
    id: id,
    role: role,
    tabIndex: -1
  });

  // usePreventScroll({
  //   isDisabled: isModal ? !isOpen : true,
  // })

  // Fills aria-modal=true
  React.useLayoutEffect(function () {
    if (isModal && isOpen && ref.current) {
      // Could add additional visible element refs here
      return ariaHideOutside([ref.current]);
    }
  }, [isModal, isOpen, ref]);
  return {
    dialogProps: dialogProps,
    labelProps: labelProps,
    focusScopeProps: {
      autoFocus: true,
      contain: true,
      restoreFocus: true
    }
  };
}

/**
 * Takes many roles and determines props necessary for DOM/components.
 * **Side effect of role="dialog"**, current and any content added later
 * outside of the element (like by portals) will get `aria-hidden=true`
 * to replace the `aria-modal=true` `inert` nature.
 * @see useModalDialogLike */
export function useOverlayTriggerA11y(_ref8) {
  var alwaysAriaVisible = _ref8.alwaysAriaVisible,
    ariaDescribedby = _ref8['aria-describedby'],
    ariaDetails = _ref8['aria-details'],
    ariaLabelledby = _ref8['aria-labelledby'],
    ariaLabel = _ref8['aria-label'],
    canPropOverlayUp = _ref8.canPropOverlayUp,
    id_ = _ref8.id,
    isOpen = _ref8.isOpen,
    role = _ref8.role;
  var isDialog = role === 'dialog';
  var id = useId(id_);
  var _getA11yPreset3 = getA11yPreset(role),
    getTriggerProps = _getA11yPreset3.getTriggerProps,
    getOverlayProps = _getA11yPreset3.getOverlayProps;
  var triggerProps = getTriggerProps === null || getTriggerProps === void 0 ? void 0 : getTriggerProps({
    isVisible: isOpen,
    role: role,
    overlayId: id
  });
  var overlayA11yProps = getOverlayProps === null || getOverlayProps === void 0 ? void 0 : getOverlayProps({
    isVisible: isOpen,
    role: role,
    overlayId: id
  });
  var wrapperA11yProps = !canPropOverlayUp ? overlayA11yProps : emptyObj;
  var overlayProps = canPropOverlayUp ? overlayA11yProps : emptyObj;
  var _useModalDialogLike = useModalDialogLike({
      'aria-describedby': ariaDescribedby,
      'aria-details': ariaDetails,
      'aria-labelledby': ariaLabelledby,
      'aria-label': ariaLabel,
      id: id,
      isModal: false,
      isOpen: isOpen
    }),
    dialogProps = _useModalDialogLike.dialogProps,
    labelProps = _useModalDialogLike.labelProps,
    focusScopeProps = _useModalDialogLike.focusScopeProps;

  /**  This is a code side-effect from ariaHideOutside hiding everthing */
  var portalProps = role === 'tooltip' || alwaysAriaVisible // || !role
  ? {
    'data-react-aria-top-layer': true,
    'data-live-announcer': true
  } : emptyObj;

  /**
   * If it is a dialog, we can merge the dialog props with any haspopup props
   */
  var wrapperFinalProps = isDialog ? _objectSpread(_objectSpread({}, wrapperA11yProps), dialogProps) : wrapperA11yProps;

  /**
   * If it is a dialog, we have opinions on `FocusScope` props.
   */
  var focusScopeFinalProps = isDialog ? focusScopeProps : emptyObj;
  return {
    focusScopeProps: focusScopeFinalProps,
    labelProps: labelProps,
    overlayProps: overlayProps,
    portalProps: portalProps,
    triggerProps: triggerProps,
    wrapperProps: wrapperFinalProps
  };
}

// WIP Example combobox
// function useCombox({
//   controls,
//   isOpen = false,
// }: {
//   controls: 'dialog' | 'menu' | 'listbox'
//   isOpen: boolean
// }) {
//   const { labelProps, popupProps, triggerProps } = useLabelledPopup({
//     role: controls,
//     type: 'combobox',
//     isOpen,
//   })
// dispatch between elements.
// NOTE combobox has two labels, that could be different
// one for the trigger input (typically the form label)
// second for the thing it controls (listbox, dialog)
// - label id=1
// - input role='combobox' aria-labelledby=1
// - div role={controls} aria-label
// Also, any icon only buttons like clear or open should have a
// label and -1 tabindex. No nested interactive roles.
// }
//# sourceMappingURL=a11yPresets.js.map