scrollLocker.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import getScrollBarSize from '../../_util/getScrollBarSize';
  2. import setStyle from '../../_util/setStyle';
  3. let locks = [];
  4. const scrollingEffectClassName = 'ant-scrolling-effect';
  5. const scrollingEffectClassNameReg = new RegExp(`${scrollingEffectClassName}`, 'g');
  6. let uuid = 0;
  7. // https://github.com/ant-design/ant-design/issues/19340
  8. // https://github.com/ant-design/ant-design/issues/19332
  9. const cacheStyle = new Map();
  10. export default class ScrollLocker {
  11. constructor(options) {
  12. this.getContainer = () => {
  13. var _a;
  14. return (_a = this.options) === null || _a === void 0 ? void 0 : _a.container;
  15. };
  16. // if options change...
  17. this.reLock = options => {
  18. const findLock = locks.find(_ref => {
  19. let {
  20. target
  21. } = _ref;
  22. return target === this.lockTarget;
  23. });
  24. if (findLock) {
  25. this.unLock();
  26. }
  27. this.options = options;
  28. if (findLock) {
  29. findLock.options = options;
  30. this.lock();
  31. }
  32. };
  33. this.lock = () => {
  34. var _a;
  35. // If lockTarget exist return
  36. if (locks.some(_ref2 => {
  37. let {
  38. target
  39. } = _ref2;
  40. return target === this.lockTarget;
  41. })) {
  42. return;
  43. }
  44. // If same container effect, return
  45. if (locks.some(_ref3 => {
  46. let {
  47. options
  48. } = _ref3;
  49. var _a;
  50. return (options === null || options === void 0 ? void 0 : options.container) === ((_a = this.options) === null || _a === void 0 ? void 0 : _a.container);
  51. })) {
  52. locks = [...locks, {
  53. target: this.lockTarget,
  54. options: this.options
  55. }];
  56. return;
  57. }
  58. let scrollBarSize = 0;
  59. const container = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.container) || document.body;
  60. if (container === document.body && window.innerWidth - document.documentElement.clientWidth > 0 || container.scrollHeight > container.clientHeight) {
  61. scrollBarSize = getScrollBarSize();
  62. }
  63. const containerClassName = container.className;
  64. if (locks.filter(_ref4 => {
  65. let {
  66. options
  67. } = _ref4;
  68. var _a;
  69. return (options === null || options === void 0 ? void 0 : options.container) === ((_a = this.options) === null || _a === void 0 ? void 0 : _a.container);
  70. }).length === 0) {
  71. cacheStyle.set(container, setStyle({
  72. width: scrollBarSize !== 0 ? `calc(100% - ${scrollBarSize}px)` : undefined,
  73. overflow: 'hidden',
  74. overflowX: 'hidden',
  75. overflowY: 'hidden'
  76. }, {
  77. element: container
  78. }));
  79. }
  80. // https://github.com/ant-design/ant-design/issues/19729
  81. if (!scrollingEffectClassNameReg.test(containerClassName)) {
  82. const addClassName = `${containerClassName} ${scrollingEffectClassName}`;
  83. container.className = addClassName.trim();
  84. }
  85. locks = [...locks, {
  86. target: this.lockTarget,
  87. options: this.options
  88. }];
  89. };
  90. this.unLock = () => {
  91. var _a;
  92. const findLock = locks.find(_ref5 => {
  93. let {
  94. target
  95. } = _ref5;
  96. return target === this.lockTarget;
  97. });
  98. locks = locks.filter(_ref6 => {
  99. let {
  100. target
  101. } = _ref6;
  102. return target !== this.lockTarget;
  103. });
  104. if (!findLock || locks.some(_ref7 => {
  105. let {
  106. options
  107. } = _ref7;
  108. var _a;
  109. return (options === null || options === void 0 ? void 0 : options.container) === ((_a = findLock.options) === null || _a === void 0 ? void 0 : _a.container);
  110. })) {
  111. return;
  112. }
  113. // Remove Effect
  114. const container = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.container) || document.body;
  115. const containerClassName = container.className;
  116. if (!scrollingEffectClassNameReg.test(containerClassName)) return;
  117. setStyle(cacheStyle.get(container), {
  118. element: container
  119. });
  120. cacheStyle.delete(container);
  121. container.className = container.className.replace(scrollingEffectClassNameReg, '').trim();
  122. };
  123. // eslint-disable-next-line no-plusplus
  124. this.lockTarget = uuid++;
  125. this.options = options;
  126. }
  127. }