Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

168 строки
5.1 KiB

  1. import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
  2. import _extends from "@babel/runtime/helpers/esm/extends";
  3. import PropTypes from 'prop-types';
  4. import { useContext, useRef } from 'react';
  5. import useCallbackRef from '@restart/hooks/useCallbackRef';
  6. import DropdownContext from './DropdownContext';
  7. import usePopper from './usePopper';
  8. import useRootClose from './useRootClose';
  9. export function useDropdownMenu(options) {
  10. if (options === void 0) {
  11. options = {};
  12. }
  13. var context = useContext(DropdownContext);
  14. var _useCallbackRef = useCallbackRef(),
  15. arrowElement = _useCallbackRef[0],
  16. attachArrowRef = _useCallbackRef[1];
  17. var hasShownRef = useRef(false);
  18. var _options = options,
  19. flip = _options.flip,
  20. rootCloseEvent = _options.rootCloseEvent,
  21. _options$popperConfig = _options.popperConfig,
  22. popperConfig = _options$popperConfig === void 0 ? {} : _options$popperConfig,
  23. _options$usePopper = _options.usePopper,
  24. shouldUsePopper = _options$usePopper === void 0 ? true : _options$usePopper;
  25. var show = context.show == null ? options.show : context.show;
  26. var alignEnd = context.alignEnd == null ? options.alignEnd : context.alignEnd;
  27. if (show && !hasShownRef.current) {
  28. hasShownRef.current = true;
  29. }
  30. var handleClose = function handleClose(e) {
  31. if (!context.toggle) return;
  32. context.toggle(false, e);
  33. };
  34. var drop = context.drop,
  35. setMenu = context.setMenu,
  36. menuElement = context.menuElement,
  37. toggleElement = context.toggleElement;
  38. var placement = alignEnd ? 'bottom-end' : 'bottom-start';
  39. if (drop === 'up') placement = alignEnd ? 'top-end' : 'top-start';else if (drop === 'right') placement = alignEnd ? 'right-end' : 'right-start';else if (drop === 'left') placement = alignEnd ? 'left-end' : 'left-start';
  40. var popper = usePopper(toggleElement, menuElement, {
  41. placement: placement,
  42. enabled: !!(shouldUsePopper && show),
  43. eventsEnabled: !!show,
  44. modifiers: _extends({
  45. flip: {
  46. enabled: !!flip
  47. },
  48. arrow: _extends({}, popperConfig.modifiers && popperConfig.modifiers.arrow, {
  49. enabled: !!arrowElement,
  50. element: arrowElement
  51. })
  52. }, popperConfig.modifiers)
  53. });
  54. var menu = null;
  55. var menuProps = {
  56. ref: setMenu,
  57. 'aria-labelledby': toggleElement && toggleElement.id
  58. };
  59. var childArgs = {
  60. show: show,
  61. alignEnd: alignEnd,
  62. hasShown: hasShownRef.current,
  63. close: handleClose
  64. };
  65. if (!shouldUsePopper) {
  66. menu = _extends({}, childArgs, {
  67. props: menuProps
  68. });
  69. } else {
  70. menu = _extends({}, popper, {}, childArgs, {
  71. props: _extends({}, menuProps, {
  72. style: popper.styles
  73. }),
  74. arrowProps: {
  75. ref: attachArrowRef,
  76. style: popper.arrowStyles
  77. }
  78. });
  79. }
  80. useRootClose(menuElement, handleClose, {
  81. clickTrigger: rootCloseEvent,
  82. disabled: !(menu && show)
  83. });
  84. return menu;
  85. }
  86. var propTypes = {
  87. /**
  88. * A render prop that returns a Menu element. The `props`
  89. * argument should spread through to **a component that can accept a ref**.
  90. *
  91. * @type {Function ({
  92. * show: boolean,
  93. * alignEnd: boolean,
  94. * close: (?SyntheticEvent) => void,
  95. * placement: Placement,
  96. * outOfBoundaries: ?boolean,
  97. * scheduleUpdate: () => void,
  98. * props: {
  99. * ref: (?HTMLElement) => void,
  100. * style: { [string]: string | number },
  101. * aria-labelledby: ?string
  102. * },
  103. * arrowProps: {
  104. * ref: (?HTMLElement) => void,
  105. * style: { [string]: string | number },
  106. * },
  107. * }) => React.Element}
  108. */
  109. children: PropTypes.func.isRequired,
  110. /**
  111. * Controls the visible state of the menu, generally this is
  112. * provided by the parent `Dropdown` component,
  113. * but may also be specified as a prop directly.
  114. */
  115. show: PropTypes.bool,
  116. /**
  117. * Aligns the dropdown menu to the 'end' of it's placement position.
  118. * Generally this is provided by the parent `Dropdown` component,
  119. * but may also be specified as a prop directly.
  120. */
  121. alignEnd: PropTypes.bool,
  122. /**
  123. * Enables the Popper.js `flip` modifier, allowing the Dropdown to
  124. * automatically adjust it's placement in case of overlap with the viewport or toggle.
  125. * Refer to the [flip docs](https://popper.js.org/popper-documentation.html#modifiers..flip.enabled) for more info
  126. */
  127. flip: PropTypes.bool,
  128. usePopper: PropTypes.oneOf([true, false]),
  129. /**
  130. * A set of popper options and props passed directly to react-popper's Popper component.
  131. */
  132. popperConfig: PropTypes.object,
  133. /**
  134. * Override the default event used by RootCloseWrapper.
  135. */
  136. rootCloseEvent: PropTypes.string
  137. };
  138. var defaultProps = {
  139. usePopper: true
  140. };
  141. function DropdownMenu(_ref) {
  142. var children = _ref.children,
  143. options = _objectWithoutPropertiesLoose(_ref, ["children"]);
  144. var args = useDropdownMenu(options);
  145. return args.hasShown ? children(args) : null;
  146. }
  147. DropdownMenu.displayName = 'ReactOverlaysDropdownMenu';
  148. DropdownMenu.propTypes = propTypes;
  149. DropdownMenu.defaultProps = defaultProps;
  150. /** @component */
  151. export default DropdownMenu;