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

259 строки
7.3 KiB

  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
  3. import PopperJS from 'popper.js';
  4. import PropTypes from 'prop-types';
  5. import React, { useState } from 'react';
  6. import ReactDOM from 'react-dom';
  7. import useCallbackRef from '@restart/hooks/useCallbackRef';
  8. import useMergedRefs from '@restart/hooks/useMergedRefs';
  9. import usePopper from './usePopper';
  10. import useRootClose from './useRootClose';
  11. import useWaitForDOMRef from './utils/useWaitForDOMRef';
  12. /**
  13. * Built on top of `Popper.js`, the overlay component is
  14. * great for custom tooltip overlays.
  15. */
  16. var Overlay = React.forwardRef(function (props, outerRef) {
  17. var flip = props.flip,
  18. placement = props.placement,
  19. containerPadding = props.containerPadding,
  20. _props$popperConfig = props.popperConfig,
  21. popperConfig = _props$popperConfig === void 0 ? {} : _props$popperConfig,
  22. Transition = props.transition;
  23. var _useCallbackRef = useCallbackRef(),
  24. rootElement = _useCallbackRef[0],
  25. attachRef = _useCallbackRef[1];
  26. var _useCallbackRef2 = useCallbackRef(),
  27. arrowElement = _useCallbackRef2[0],
  28. attachArrowRef = _useCallbackRef2[1];
  29. var mergedRef = useMergedRefs(attachRef, outerRef);
  30. var container = useWaitForDOMRef(props.container);
  31. var target = useWaitForDOMRef(props.target);
  32. var _useState = useState(!props.show),
  33. exited = _useState[0],
  34. setExited = _useState[1];
  35. var _popperConfig$modifie = popperConfig.modifiers,
  36. modifiers = _popperConfig$modifie === void 0 ? {} : _popperConfig$modifie;
  37. var _usePopper = usePopper(target, rootElement, _extends({}, popperConfig, {
  38. placement: placement || 'bottom',
  39. enableEvents: props.show,
  40. modifiers: _extends({}, modifiers, {
  41. preventOverflow: _extends({
  42. padding: containerPadding || 5
  43. }, modifiers.preventOverflow),
  44. arrow: _extends({}, modifiers.arrow, {
  45. enabled: !!arrowElement,
  46. element: arrowElement
  47. }),
  48. flip: _extends({
  49. enabled: !!flip
  50. }, modifiers.preventOverflow)
  51. })
  52. })),
  53. styles = _usePopper.styles,
  54. arrowStyles = _usePopper.arrowStyles,
  55. popper = _objectWithoutPropertiesLoose(_usePopper, ["styles", "arrowStyles"]);
  56. if (props.show) {
  57. if (exited) setExited(false);
  58. } else if (!props.transition && !exited) {
  59. setExited(true);
  60. }
  61. var handleHidden = function handleHidden() {
  62. setExited(true);
  63. if (props.onExited) {
  64. props.onExited.apply(props, arguments);
  65. }
  66. }; // Don't un-render the overlay while it's transitioning out.
  67. var mountOverlay = props.show || Transition && !exited;
  68. useRootClose(rootElement, props.onHide, {
  69. disabled: !props.rootClose || props.rootCloseDisabled,
  70. clickTrigger: props.rootCloseEvent
  71. });
  72. if (!mountOverlay) {
  73. // Don't bother showing anything if we don't have to.
  74. return null;
  75. }
  76. var child = props.children(_extends({}, popper, {
  77. show: props.show,
  78. props: {
  79. style: styles,
  80. ref: mergedRef
  81. },
  82. arrowProps: {
  83. style: arrowStyles,
  84. ref: attachArrowRef
  85. }
  86. }));
  87. if (Transition) {
  88. var onExit = props.onExit,
  89. onExiting = props.onExiting,
  90. onEnter = props.onEnter,
  91. onEntering = props.onEntering,
  92. onEntered = props.onEntered;
  93. child = React.createElement(Transition, {
  94. "in": props.show,
  95. appear: true,
  96. onExit: onExit,
  97. onExiting: onExiting,
  98. onExited: handleHidden,
  99. onEnter: onEnter,
  100. onEntering: onEntering,
  101. onEntered: onEntered
  102. }, child);
  103. }
  104. return container ? ReactDOM.createPortal(child, container) : null;
  105. });
  106. Overlay.displayName = 'Overlay';
  107. Overlay.propTypes = {
  108. /**
  109. * Set the visibility of the Overlay
  110. */
  111. show: PropTypes.bool,
  112. /** Specify where the overlay element is positioned in relation to the target element */
  113. placement: PropTypes.oneOf(PopperJS.placements),
  114. /**
  115. * A DOM Element, Ref to an element, or function that returns either. The `target` element is where
  116. * the overlay is positioned relative to.
  117. */
  118. target: PropTypes.any,
  119. /**
  120. * A DOM Element, Ref to an element, or function that returns either. The `container` will have the Portal children
  121. * appended to it.
  122. */
  123. container: PropTypes.any,
  124. /**
  125. * Enables the Popper.js `flip` modifier, allowing the Overlay to
  126. * automatically adjust it's placement in case of overlap with the viewport or toggle.
  127. * Refer to the [flip docs](https://popper.js.org/popper-documentation.html#modifiers..flip.enabled) for more info
  128. */
  129. flip: PropTypes.bool,
  130. /**
  131. * A render prop that returns an element to overlay and position. See
  132. * the [react-popper documentation](https://github.com/FezVrasta/react-popper#children) for more info.
  133. *
  134. * @type {Function ({
  135. * show: boolean,
  136. * placement: Placement,
  137. * outOfBoundaries: ?boolean,
  138. * scheduleUpdate: () => void,
  139. * props: {
  140. * ref: (?HTMLElement) => void,
  141. * style: { [string]: string | number },
  142. * aria-labelledby: ?string
  143. * },
  144. * arrowProps: {
  145. * ref: (?HTMLElement) => void,
  146. * style: { [string]: string | number },
  147. * },
  148. * }) => React.Element}
  149. */
  150. children: PropTypes.func.isRequired,
  151. /**
  152. * Control how much space there is between the edge of the boundary element and overlay.
  153. * A convenience shortcut to setting `popperConfig.modfiers.preventOverflow.padding`
  154. */
  155. containerPadding: PropTypes.number,
  156. /**
  157. * A set of popper options and props passed directly to react-popper's Popper component.
  158. */
  159. popperConfig: PropTypes.object,
  160. /**
  161. * Specify whether the overlay should trigger `onHide` when the user clicks outside the overlay
  162. */
  163. rootClose: PropTypes.bool,
  164. /**
  165. * Specify event for toggling overlay
  166. */
  167. rootCloseEvent: PropTypes.oneOf(['click', 'mousedown']),
  168. /**
  169. * Specify disabled for disable RootCloseWrapper
  170. */
  171. rootCloseDisabled: PropTypes.bool,
  172. /**
  173. * A Callback fired by the Overlay when it wishes to be hidden.
  174. *
  175. * __required__ when `rootClose` is `true`.
  176. *
  177. * @type func
  178. */
  179. onHide: function onHide(props) {
  180. var propType = PropTypes.func;
  181. if (props.rootClose) {
  182. propType = propType.isRequired;
  183. }
  184. for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  185. args[_key - 1] = arguments[_key];
  186. }
  187. return propType.apply(void 0, [props].concat(args));
  188. },
  189. /**
  190. * A `react-transition-group@2.0.0` `<Transition/>` component
  191. * used to animate the overlay as it changes visibility.
  192. */
  193. transition: PropTypes.elementType,
  194. /**
  195. * Callback fired before the Overlay transitions in
  196. */
  197. onEnter: PropTypes.func,
  198. /**
  199. * Callback fired as the Overlay begins to transition in
  200. */
  201. onEntering: PropTypes.func,
  202. /**
  203. * Callback fired after the Overlay finishes transitioning in
  204. */
  205. onEntered: PropTypes.func,
  206. /**
  207. * Callback fired right before the Overlay transitions out
  208. */
  209. onExit: PropTypes.func,
  210. /**
  211. * Callback fired as the Overlay begins to transition out
  212. */
  213. onExiting: PropTypes.func,
  214. /**
  215. * Callback fired after the Overlay finishes transitioning out
  216. */
  217. onExited: PropTypes.func
  218. };
  219. Overlay.defaultProps = {
  220. containerPadding: 5
  221. };
  222. export default Overlay;