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.

functions.web.ts 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. const getLeftAlignedStyle = (bounds: DOMRect) => {
  2. return {
  3. position: 'fixed',
  4. right: `${window.innerWidth - bounds.x}px`
  5. };
  6. };
  7. const getRightAlignedStyle = (bounds: DOMRect) => {
  8. return {
  9. position: 'fixed',
  10. left: `${bounds.x + bounds.width}px`
  11. };
  12. };
  13. const getTopAlignedStyle = (bounds: DOMRect) => {
  14. return {
  15. position: 'fixed',
  16. bottom: `${window.innerHeight - bounds.y}px`
  17. };
  18. };
  19. const getBottomAlignedStyle = (bounds: DOMRect) => {
  20. return {
  21. position: 'fixed',
  22. top: `${bounds.y + bounds.height}px`
  23. };
  24. };
  25. const getLeftRightStartAlign = (bounds: DOMRect, size: DOMRectReadOnly) => {
  26. return {
  27. top: `${Math.min(bounds.y, window.innerHeight - size.height - 20)}px`
  28. };
  29. };
  30. const getLeftRightMidAlign = (bounds: DOMRect, size: DOMRectReadOnly) => {
  31. return {
  32. bottom: `${window.innerHeight - bounds.y - (bounds.height / 2) - (size.height / 2)}px`
  33. };
  34. };
  35. const getLeftRightEndAlign = (bounds: DOMRect, size: DOMRectReadOnly) => {
  36. return {
  37. bottom: `${Math.min(window.innerHeight - bounds.y - bounds.height, window.innerHeight - size.height)}px`
  38. };
  39. };
  40. const getTopBotStartAlign = (bounds: DOMRect) => {
  41. return {
  42. right: `${window.innerWidth - bounds.x - 6}px`
  43. };
  44. };
  45. const getTopBotMidAlign = (bounds: DOMRect, size: DOMRectReadOnly) => {
  46. return {
  47. right: `${window.innerWidth - bounds.x - (bounds.width / 2) - (size.width / 2)}px`
  48. };
  49. };
  50. const getTopBotEndAlign = (bounds: DOMRect) => {
  51. return {
  52. left: `${bounds.x + bounds.width - 6}px`
  53. };
  54. };
  55. /**
  56. * Gets the trigger element's and the context menu's bounds/size info and
  57. * computes the style to apply to the context menu to positioning it correctly
  58. * in regards to the given position info.
  59. *
  60. * @param {DOMRect} triggerBounds -The bounds info of the trigger html element.
  61. * @param {DOMRectReadOnly} dialogSize - The size info of the context menu.
  62. * @param {string} position - The position of the context menu in regards to the trigger element.
  63. *
  64. * @returns {Object} = The style to apply to context menu for positioning it correctly.
  65. */
  66. export const getContextMenuStyle = (triggerBounds: DOMRect,
  67. dialogSize: DOMRectReadOnly,
  68. position: string) => {
  69. const parsed = position.split('-');
  70. switch (parsed[0]) {
  71. case 'top': {
  72. let alignmentStyle = {};
  73. if (parsed[1]) {
  74. alignmentStyle = parsed[1] === 'start'
  75. ? getTopBotStartAlign(triggerBounds)
  76. : getTopBotEndAlign(triggerBounds);
  77. } else {
  78. alignmentStyle = getTopBotMidAlign(triggerBounds, dialogSize);
  79. }
  80. return {
  81. ...getTopAlignedStyle(triggerBounds),
  82. ...alignmentStyle
  83. };
  84. }
  85. case 'bottom': {
  86. let alignmentStyle = {};
  87. if (parsed[1]) {
  88. alignmentStyle = parsed[1] === 'start'
  89. ? getTopBotStartAlign(triggerBounds)
  90. : getTopBotEndAlign(triggerBounds);
  91. } else {
  92. alignmentStyle = getTopBotMidAlign(triggerBounds, dialogSize);
  93. }
  94. return {
  95. ...getBottomAlignedStyle(triggerBounds),
  96. ...alignmentStyle
  97. };
  98. }
  99. case 'left': {
  100. let alignmentStyle = {};
  101. if (parsed[1]) {
  102. alignmentStyle = parsed[1] === 'start'
  103. ? getLeftRightStartAlign(triggerBounds, dialogSize)
  104. : getLeftRightEndAlign(triggerBounds, dialogSize);
  105. } else {
  106. alignmentStyle = getLeftRightMidAlign(triggerBounds, dialogSize);
  107. }
  108. return {
  109. ...getLeftAlignedStyle(triggerBounds),
  110. ...alignmentStyle
  111. };
  112. }
  113. case 'right': {
  114. let alignmentStyle = {};
  115. if (parsed[1]) {
  116. alignmentStyle = parsed[1] === 'start'
  117. ? getLeftRightStartAlign(triggerBounds, dialogSize)
  118. : getLeftRightEndAlign(triggerBounds, dialogSize);
  119. } else {
  120. alignmentStyle = getLeftRightMidAlign(triggerBounds, dialogSize);
  121. }
  122. return {
  123. ...getRightAlignedStyle(triggerBounds),
  124. ...alignmentStyle
  125. };
  126. }
  127. default: {
  128. return {
  129. ...getLeftAlignedStyle(triggerBounds),
  130. ...getLeftRightEndAlign(triggerBounds, dialogSize)
  131. };
  132. }
  133. }
  134. };