Align.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  2. import _typeof from "@babel/runtime/helpers/esm/typeof";
  3. import { nextTick, defineComponent, ref, computed, onMounted, onUpdated, watch, onUnmounted } from 'vue';
  4. import { alignElement, alignPoint } from 'dom-align';
  5. import addEventListener from '../vc-util/Dom/addEventListener';
  6. import { cloneElement } from '../_util/vnode';
  7. import isVisible from '../vc-util/Dom/isVisible';
  8. import { isSamePoint, restoreFocus, monitorResize } from './util';
  9. import useBuffer from './hooks/useBuffer';
  10. import isEqual from 'lodash-es/isEqual';
  11. export var alignProps = {
  12. align: Object,
  13. target: [Object, Function],
  14. onAlign: Function,
  15. monitorBufferTime: Number,
  16. monitorWindowResize: Boolean,
  17. disabled: Boolean
  18. };
  19. function getElement(func) {
  20. if (typeof func !== 'function') return null;
  21. return func();
  22. }
  23. function getPoint(point) {
  24. if (_typeof(point) !== 'object' || !point) return null;
  25. return point;
  26. }
  27. export default defineComponent({
  28. compatConfig: {
  29. MODE: 3
  30. },
  31. name: 'Align',
  32. props: alignProps,
  33. emits: ['align'],
  34. setup: function setup(props, _ref) {
  35. var expose = _ref.expose,
  36. slots = _ref.slots;
  37. var cacheRef = ref({});
  38. var nodeRef = ref();
  39. var _useBuffer = useBuffer(function () {
  40. var latestDisabled = props.disabled,
  41. latestTarget = props.target,
  42. latestAlign = props.align,
  43. latestOnAlign = props.onAlign;
  44. if (!latestDisabled && latestTarget && nodeRef.value) {
  45. var source = nodeRef.value;
  46. var result;
  47. var element = getElement(latestTarget);
  48. var point = getPoint(latestTarget);
  49. cacheRef.value.element = element;
  50. cacheRef.value.point = point;
  51. cacheRef.value.align = latestAlign;
  52. // IE lose focus after element realign
  53. // We should record activeElement and restore later
  54. var _document = document,
  55. activeElement = _document.activeElement;
  56. // We only align when element is visible
  57. if (element && isVisible(element)) {
  58. result = alignElement(source, element, latestAlign);
  59. } else if (point) {
  60. result = alignPoint(source, point, latestAlign);
  61. }
  62. restoreFocus(activeElement, source);
  63. if (latestOnAlign && result) {
  64. latestOnAlign(source, result);
  65. }
  66. return true;
  67. }
  68. return false;
  69. }, computed(function () {
  70. return props.monitorBufferTime;
  71. })),
  72. _useBuffer2 = _slicedToArray(_useBuffer, 2),
  73. _forceAlign = _useBuffer2[0],
  74. cancelForceAlign = _useBuffer2[1];
  75. // ===================== Effect =====================
  76. // Listen for target updated
  77. var resizeMonitor = ref({
  78. cancel: function cancel() {}
  79. });
  80. // Listen for source updated
  81. var sourceResizeMonitor = ref({
  82. cancel: function cancel() {}
  83. });
  84. var goAlign = function goAlign() {
  85. var target = props.target;
  86. var element = getElement(target);
  87. var point = getPoint(target);
  88. if (nodeRef.value !== sourceResizeMonitor.value.element) {
  89. sourceResizeMonitor.value.cancel();
  90. sourceResizeMonitor.value.element = nodeRef.value;
  91. sourceResizeMonitor.value.cancel = monitorResize(nodeRef.value, _forceAlign);
  92. }
  93. if (cacheRef.value.element !== element || !isSamePoint(cacheRef.value.point, point) || !isEqual(cacheRef.value.align, props.align)) {
  94. _forceAlign();
  95. // Add resize observer
  96. if (resizeMonitor.value.element !== element) {
  97. resizeMonitor.value.cancel();
  98. resizeMonitor.value.element = element;
  99. resizeMonitor.value.cancel = monitorResize(element, _forceAlign);
  100. }
  101. }
  102. };
  103. onMounted(function () {
  104. nextTick(function () {
  105. goAlign();
  106. });
  107. });
  108. onUpdated(function () {
  109. nextTick(function () {
  110. goAlign();
  111. });
  112. });
  113. // Listen for disabled change
  114. watch(function () {
  115. return props.disabled;
  116. }, function (disabled) {
  117. if (!disabled) {
  118. _forceAlign();
  119. } else {
  120. cancelForceAlign();
  121. }
  122. }, {
  123. immediate: true,
  124. flush: 'post'
  125. });
  126. // Listen for window resize
  127. var winResizeRef = ref(null);
  128. watch(function () {
  129. return props.monitorWindowResize;
  130. }, function (monitorWindowResize) {
  131. if (monitorWindowResize) {
  132. if (!winResizeRef.value) {
  133. winResizeRef.value = addEventListener(window, 'resize', _forceAlign);
  134. }
  135. } else if (winResizeRef.value) {
  136. winResizeRef.value.remove();
  137. winResizeRef.value = null;
  138. }
  139. }, {
  140. flush: 'post'
  141. });
  142. onUnmounted(function () {
  143. resizeMonitor.value.cancel();
  144. sourceResizeMonitor.value.cancel();
  145. if (winResizeRef.value) winResizeRef.value.remove();
  146. cancelForceAlign();
  147. });
  148. expose({
  149. forceAlign: function forceAlign() {
  150. return _forceAlign(true);
  151. }
  152. });
  153. return function () {
  154. var child = slots === null || slots === void 0 ? void 0 : slots.default();
  155. if (child) {
  156. return cloneElement(child[0], {
  157. ref: nodeRef
  158. }, true, true);
  159. }
  160. return null;
  161. };
  162. }
  163. });