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.

76 lines
2.0 KiB

2 months ago
  1. // @flow
  2. import type {
  3. ModifierArguments,
  4. Modifier,
  5. Rect,
  6. SideObject,
  7. Offsets,
  8. } from '../types';
  9. import { top, bottom, left, right } from '../enums';
  10. import detectOverflow from '../utils/detectOverflow';
  11. function getSideOffsets(
  12. overflow: SideObject,
  13. rect: Rect,
  14. preventedOffsets: Offsets = { x: 0, y: 0 }
  15. ): SideObject {
  16. return {
  17. top: overflow.top - rect.height - preventedOffsets.y,
  18. right: overflow.right - rect.width + preventedOffsets.x,
  19. bottom: overflow.bottom - rect.height + preventedOffsets.y,
  20. left: overflow.left - rect.width - preventedOffsets.x,
  21. };
  22. }
  23. function isAnySideFullyClipped(overflow: SideObject): boolean {
  24. return [top, right, bottom, left].some((side) => overflow[side] >= 0);
  25. }
  26. function hide({ state, name }: ModifierArguments<{||}>) {
  27. const referenceRect = state.rects.reference;
  28. const popperRect = state.rects.popper;
  29. const preventedOffsets = state.modifiersData.preventOverflow;
  30. const referenceOverflow = detectOverflow(state, {
  31. elementContext: 'reference',
  32. });
  33. const popperAltOverflow = detectOverflow(state, {
  34. altBoundary: true,
  35. });
  36. const referenceClippingOffsets = getSideOffsets(
  37. referenceOverflow,
  38. referenceRect
  39. );
  40. const popperEscapeOffsets = getSideOffsets(
  41. popperAltOverflow,
  42. popperRect,
  43. preventedOffsets
  44. );
  45. const isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
  46. const hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
  47. state.modifiersData[name] = {
  48. referenceClippingOffsets,
  49. popperEscapeOffsets,
  50. isReferenceHidden,
  51. hasPopperEscaped,
  52. };
  53. state.attributes.popper = {
  54. ...state.attributes.popper,
  55. 'data-popper-reference-hidden': isReferenceHidden,
  56. 'data-popper-escaped': hasPopperEscaped,
  57. };
  58. }
  59. // eslint-disable-next-line import/no-unused-modules
  60. export type HideModifier = Modifier<'hide', {||}>;
  61. export default ({
  62. name: 'hide',
  63. enabled: true,
  64. phase: 'main',
  65. requiresIfExists: ['preventOverflow'],
  66. fn: hide,
  67. }: HideModifier);