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.

85 lines
2.1 KiB

  1. // @flow
  2. import type { State, Padding } from '../types';
  3. import type {
  4. Placement,
  5. ComputedPlacement,
  6. Boundary,
  7. RootBoundary,
  8. } from '../enums';
  9. import getVariation from './getVariation';
  10. import {
  11. variationPlacements,
  12. basePlacements,
  13. placements as allPlacements,
  14. } from '../enums';
  15. import detectOverflow from './detectOverflow';
  16. import getBasePlacement from './getBasePlacement';
  17. type Options = {
  18. placement: Placement,
  19. padding: Padding,
  20. boundary: Boundary,
  21. rootBoundary: RootBoundary,
  22. flipVariations: boolean,
  23. allowedAutoPlacements?: Array<Placement>,
  24. };
  25. type OverflowsMap = { [ComputedPlacement]: number };
  26. export default function computeAutoPlacement(
  27. state: $Shape<State>,
  28. options: Options = {}
  29. ): Array<ComputedPlacement> {
  30. const {
  31. placement,
  32. boundary,
  33. rootBoundary,
  34. padding,
  35. flipVariations,
  36. allowedAutoPlacements = allPlacements,
  37. } = options;
  38. const variation = getVariation(placement);
  39. const placements = variation
  40. ? flipVariations
  41. ? variationPlacements
  42. : variationPlacements.filter(
  43. (placement) => getVariation(placement) === variation
  44. )
  45. : basePlacements;
  46. let allowedPlacements = placements.filter(
  47. (placement) => allowedAutoPlacements.indexOf(placement) >= 0
  48. );
  49. if (allowedPlacements.length === 0) {
  50. allowedPlacements = placements;
  51. if (false) {
  52. console.error(
  53. [
  54. 'Popper: The `allowedAutoPlacements` option did not allow any',
  55. 'placements. Ensure the `placement` option matches the variation',
  56. 'of the allowed placements.',
  57. 'For example, "auto" cannot be used to allow "bottom-start".',
  58. 'Use "auto-start" instead.',
  59. ].join(' ')
  60. );
  61. }
  62. }
  63. // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...
  64. const overflows: OverflowsMap = allowedPlacements.reduce((acc, placement) => {
  65. acc[placement] = detectOverflow(state, {
  66. placement,
  67. boundary,
  68. rootBoundary,
  69. padding,
  70. })[getBasePlacement(placement)];
  71. return acc;
  72. }, {});
  73. return Object.keys(overflows).sort((a, b) => overflows[a] - overflows[b]);
  74. }