You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

usePopper.js 4.5 KiB

3 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. exports.__esModule = true;
  4. exports["default"] = usePopper;
  5. var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
  6. var _popper = _interopRequireDefault(require("popper.js"));
  7. var _react = require("react");
  8. var initialPopperStyles = {
  9. position: 'absolute',
  10. top: '0',
  11. left: '0',
  12. opacity: '0',
  13. pointerEvents: 'none'
  14. };
  15. var initialArrowStyles = {};
  16. /**
  17. * Position an element relative some reference element using Popper.js
  18. *
  19. * @param {HTMLElement} referenceElement The element
  20. * @param {HTMLElement} popperElement
  21. * @param {Object} options
  22. * @param {Object} options.modifiers Popper.js modifiers
  23. * @param {Boolean} options.enabled toggle the popper functionality on/off
  24. * @param {String} options.placement The popper element placement relative to the reference element
  25. * @param {Boolean} options.positionFixed use fixed positioning
  26. * @param {Boolean} options.eventsEnabled have Popper listen on window resize events to reposition the element
  27. */
  28. function usePopper(referenceElement, popperElement, _temp) {
  29. var _ref = _temp === void 0 ? {} : _temp,
  30. _ref$enabled = _ref.enabled,
  31. enabled = _ref$enabled === void 0 ? true : _ref$enabled,
  32. _ref$placement = _ref.placement,
  33. placement = _ref$placement === void 0 ? 'bottom' : _ref$placement,
  34. _ref$positionFixed = _ref.positionFixed,
  35. positionFixed = _ref$positionFixed === void 0 ? false : _ref$positionFixed,
  36. _ref$eventsEnabled = _ref.eventsEnabled,
  37. eventsEnabled = _ref$eventsEnabled === void 0 ? true : _ref$eventsEnabled,
  38. _ref$modifiers = _ref.modifiers,
  39. modifiers = _ref$modifiers === void 0 ? {} : _ref$modifiers;
  40. var popperInstanceRef = (0, _react.useRef)();
  41. var hasArrow = !!(modifiers.arrow && modifiers.arrow.element);
  42. var scheduleUpdate = (0, _react.useCallback)(function () {
  43. if (popperInstanceRef.current) {
  44. popperInstanceRef.current.scheduleUpdate();
  45. }
  46. }, []);
  47. var _useState = (0, _react.useState)({
  48. placement: placement,
  49. scheduleUpdate: scheduleUpdate,
  50. outOfBoundaries: false,
  51. styles: initialPopperStyles,
  52. arrowStyles: initialArrowStyles
  53. }),
  54. state = _useState[0],
  55. setState = _useState[1]; // A placement difference in state means popper determined a new placement
  56. // apart from the props value. By the time the popper element is rendered with
  57. // the new position Popper has already measured it, if the place change triggers
  58. // a size change it will result in a misaligned popper. So we schedule an update to be sure.
  59. (0, _react.useEffect)(function () {
  60. scheduleUpdate();
  61. }, [state.placement, scheduleUpdate]);
  62. /** Toggle Events */
  63. (0, _react.useEffect)(function () {
  64. if (popperInstanceRef.current) {
  65. // eslint-disable-next-line no-unused-expressions
  66. eventsEnabled ? popperInstanceRef.current.enableEventListeners() : popperInstanceRef.current.disableEventListeners();
  67. }
  68. }, [eventsEnabled]);
  69. (0, _react.useEffect)(function () {
  70. if (!enabled || referenceElement == null || popperElement == null) {
  71. return undefined;
  72. }
  73. var arrow = modifiers.arrow && (0, _extends2["default"])({}, modifiers.arrow, {
  74. element: modifiers.arrow.element
  75. });
  76. popperInstanceRef.current = new _popper["default"](referenceElement, popperElement, {
  77. placement: placement,
  78. positionFixed: positionFixed,
  79. modifiers: (0, _extends2["default"])({}, modifiers, {
  80. arrow: arrow,
  81. applyStyle: {
  82. enabled: false
  83. },
  84. updateStateModifier: {
  85. enabled: true,
  86. order: 900,
  87. fn: function fn(data) {
  88. setState({
  89. scheduleUpdate: scheduleUpdate,
  90. styles: (0, _extends2["default"])({
  91. position: data.offsets.popper.position
  92. }, data.styles),
  93. arrowStyles: data.arrowStyles,
  94. outOfBoundaries: data.hide,
  95. placement: data.placement
  96. });
  97. }
  98. }
  99. })
  100. });
  101. return function () {
  102. if (popperInstanceRef.current !== null) {
  103. popperInstanceRef.current.destroy();
  104. popperInstanceRef.current = null;
  105. }
  106. }; // intentionally NOT re-running on new modifiers
  107. // eslint-disable-next-line react-hooks/exhaustive-deps
  108. }, [enabled, placement, positionFixed, referenceElement, popperElement, hasArrow]);
  109. return state;
  110. }
  111. module.exports = exports.default;