placementArrow.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import { roundedArrow } from './roundedArrow';
  3. function connectArrowCls(classList) {
  4. let showArrowCls = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
  5. return classList.map(cls => `${showArrowCls}${cls}`).join(',');
  6. }
  7. export const MAX_VERTICAL_CONTENT_RADIUS = 8;
  8. export function getArrowOffset(options) {
  9. const maxVerticalContentRadius = MAX_VERTICAL_CONTENT_RADIUS;
  10. const {
  11. sizePopupArrow,
  12. contentRadius,
  13. borderRadiusOuter,
  14. limitVerticalRadius
  15. } = options;
  16. const arrowInnerOffset = sizePopupArrow / 2 - Math.ceil(borderRadiusOuter * (Math.sqrt(2) - 1));
  17. const dropdownArrowOffset = (contentRadius > 12 ? contentRadius + 2 : 12) - arrowInnerOffset;
  18. const dropdownArrowOffsetVertical = limitVerticalRadius ? maxVerticalContentRadius - arrowInnerOffset : dropdownArrowOffset;
  19. return {
  20. dropdownArrowOffset,
  21. dropdownArrowOffsetVertical
  22. };
  23. }
  24. export default function getArrowStyle(token, options) {
  25. const {
  26. componentCls,
  27. sizePopupArrow,
  28. marginXXS,
  29. borderRadiusXS,
  30. borderRadiusOuter,
  31. boxShadowPopoverArrow
  32. } = token;
  33. const {
  34. colorBg,
  35. showArrowCls,
  36. contentRadius = token.borderRadiusLG,
  37. limitVerticalRadius
  38. } = options;
  39. const {
  40. dropdownArrowOffsetVertical,
  41. dropdownArrowOffset
  42. } = getArrowOffset({
  43. sizePopupArrow,
  44. contentRadius,
  45. borderRadiusOuter,
  46. limitVerticalRadius
  47. });
  48. const dropdownArrowDistance = sizePopupArrow / 2 + marginXXS;
  49. return {
  50. [componentCls]: {
  51. // ============================ Basic ============================
  52. [`${componentCls}-arrow`]: [_extends(_extends({
  53. position: 'absolute',
  54. zIndex: 1,
  55. display: 'block'
  56. }, roundedArrow(sizePopupArrow, borderRadiusXS, borderRadiusOuter, colorBg, boxShadowPopoverArrow)), {
  57. '&:before': {
  58. background: colorBg
  59. }
  60. })],
  61. // ========================== Placement ==========================
  62. // Here handle the arrow position and rotate stuff
  63. // >>>>> Top
  64. [[`&-placement-top ${componentCls}-arrow`, `&-placement-topLeft ${componentCls}-arrow`, `&-placement-topRight ${componentCls}-arrow`].join(',')]: {
  65. bottom: 0,
  66. transform: 'translateY(100%) rotate(180deg)'
  67. },
  68. [`&-placement-top ${componentCls}-arrow`]: {
  69. left: {
  70. _skip_check_: true,
  71. value: '50%'
  72. },
  73. transform: 'translateX(-50%) translateY(100%) rotate(180deg)'
  74. },
  75. [`&-placement-topLeft ${componentCls}-arrow`]: {
  76. left: {
  77. _skip_check_: true,
  78. value: dropdownArrowOffset
  79. }
  80. },
  81. [`&-placement-topRight ${componentCls}-arrow`]: {
  82. right: {
  83. _skip_check_: true,
  84. value: dropdownArrowOffset
  85. }
  86. },
  87. // >>>>> Bottom
  88. [[`&-placement-bottom ${componentCls}-arrow`, `&-placement-bottomLeft ${componentCls}-arrow`, `&-placement-bottomRight ${componentCls}-arrow`].join(',')]: {
  89. top: 0,
  90. transform: `translateY(-100%)`
  91. },
  92. [`&-placement-bottom ${componentCls}-arrow`]: {
  93. left: {
  94. _skip_check_: true,
  95. value: '50%'
  96. },
  97. transform: `translateX(-50%) translateY(-100%)`
  98. },
  99. [`&-placement-bottomLeft ${componentCls}-arrow`]: {
  100. left: {
  101. _skip_check_: true,
  102. value: dropdownArrowOffset
  103. }
  104. },
  105. [`&-placement-bottomRight ${componentCls}-arrow`]: {
  106. right: {
  107. _skip_check_: true,
  108. value: dropdownArrowOffset
  109. }
  110. },
  111. // >>>>> Left
  112. [[`&-placement-left ${componentCls}-arrow`, `&-placement-leftTop ${componentCls}-arrow`, `&-placement-leftBottom ${componentCls}-arrow`].join(',')]: {
  113. right: {
  114. _skip_check_: true,
  115. value: 0
  116. },
  117. transform: 'translateX(100%) rotate(90deg)'
  118. },
  119. [`&-placement-left ${componentCls}-arrow`]: {
  120. top: {
  121. _skip_check_: true,
  122. value: '50%'
  123. },
  124. transform: 'translateY(-50%) translateX(100%) rotate(90deg)'
  125. },
  126. [`&-placement-leftTop ${componentCls}-arrow`]: {
  127. top: dropdownArrowOffsetVertical
  128. },
  129. [`&-placement-leftBottom ${componentCls}-arrow`]: {
  130. bottom: dropdownArrowOffsetVertical
  131. },
  132. // >>>>> Right
  133. [[`&-placement-right ${componentCls}-arrow`, `&-placement-rightTop ${componentCls}-arrow`, `&-placement-rightBottom ${componentCls}-arrow`].join(',')]: {
  134. left: {
  135. _skip_check_: true,
  136. value: 0
  137. },
  138. transform: 'translateX(-100%) rotate(-90deg)'
  139. },
  140. [`&-placement-right ${componentCls}-arrow`]: {
  141. top: {
  142. _skip_check_: true,
  143. value: '50%'
  144. },
  145. transform: 'translateY(-50%) translateX(-100%) rotate(-90deg)'
  146. },
  147. [`&-placement-rightTop ${componentCls}-arrow`]: {
  148. top: dropdownArrowOffsetVertical
  149. },
  150. [`&-placement-rightBottom ${componentCls}-arrow`]: {
  151. bottom: dropdownArrowOffsetVertical
  152. },
  153. // =========================== Offset ============================
  154. // Offset the popover to account for the dropdown arrow
  155. // >>>>> Top
  156. [connectArrowCls([`&-placement-topLeft`, `&-placement-top`, `&-placement-topRight`].map(cls => cls += ':not(&-arrow-hidden)'), showArrowCls)]: {
  157. paddingBottom: dropdownArrowDistance
  158. },
  159. // >>>>> Bottom
  160. [connectArrowCls([`&-placement-bottomLeft`, `&-placement-bottom`, `&-placement-bottomRight`].map(cls => cls += ':not(&-arrow-hidden)'), showArrowCls)]: {
  161. paddingTop: dropdownArrowDistance
  162. },
  163. // >>>>> Left
  164. [connectArrowCls([`&-placement-leftTop`, `&-placement-left`, `&-placement-leftBottom`].map(cls => cls += ':not(&-arrow-hidden)'), showArrowCls)]: {
  165. paddingRight: {
  166. _skip_check_: true,
  167. value: dropdownArrowDistance
  168. }
  169. },
  170. // >>>>> Right
  171. [connectArrowCls([`&-placement-rightTop`, `&-placement-right`, `&-placement-rightBottom`].map(cls => cls += ':not(&-arrow-hidden)'), showArrowCls)]: {
  172. paddingLeft: {
  173. _skip_check_: true,
  174. value: dropdownArrowDistance
  175. }
  176. }
  177. }
  178. };
  179. }