44e042b7a271140e013485940d447bf59ad2a6b05e555d9e1fa917529138bbcdaac5d6cdcd953c118bb25d8b01955bab33cbd7e27aaba7f2d4365fc471f4c2 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import { defineComponent, shallowRef, ref, computed, watch, onMounted, watchEffect, openBlock, createElementBlock, normalizeClass, unref, normalizeStyle, createElementVNode, renderSlot, nextTick } from 'vue';
  2. import { useWindowSize, useElementBounding, useEventListener } from '@vueuse/core';
  3. import { affixProps, affixEmits } from './affix.mjs';
  4. import _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs';
  5. import { useNamespace } from '../../../hooks/use-namespace/index.mjs';
  6. import { getScrollContainer } from '../../../utils/dom/scroll.mjs';
  7. import { addUnit } from '../../../utils/dom/style.mjs';
  8. import { CHANGE_EVENT } from '../../../constants/event.mjs';
  9. import { throwError } from '../../../utils/error.mjs';
  10. const COMPONENT_NAME = "ElAffix";
  11. const __default__ = defineComponent({
  12. name: COMPONENT_NAME
  13. });
  14. const _sfc_main = /* @__PURE__ */ defineComponent({
  15. ...__default__,
  16. props: affixProps,
  17. emits: affixEmits,
  18. setup(__props, { expose, emit }) {
  19. const props = __props;
  20. const ns = useNamespace("affix");
  21. const target = shallowRef();
  22. const root = shallowRef();
  23. const scrollContainer = shallowRef();
  24. const { height: windowHeight } = useWindowSize();
  25. const {
  26. height: rootHeight,
  27. width: rootWidth,
  28. top: rootTop,
  29. bottom: rootBottom,
  30. update: updateRoot
  31. } = useElementBounding(root, { windowScroll: false });
  32. const targetRect = useElementBounding(target);
  33. const fixed = ref(false);
  34. const scrollTop = ref(0);
  35. const transform = ref(0);
  36. const rootStyle = computed(() => {
  37. return {
  38. height: fixed.value ? `${rootHeight.value}px` : "",
  39. width: fixed.value ? `${rootWidth.value}px` : ""
  40. };
  41. });
  42. const affixStyle = computed(() => {
  43. if (!fixed.value)
  44. return {};
  45. const offset = props.offset ? addUnit(props.offset) : 0;
  46. return {
  47. height: `${rootHeight.value}px`,
  48. width: `${rootWidth.value}px`,
  49. top: props.position === "top" ? offset : "",
  50. bottom: props.position === "bottom" ? offset : "",
  51. transform: transform.value ? `translateY(${transform.value}px)` : "",
  52. zIndex: props.zIndex
  53. };
  54. });
  55. const update = () => {
  56. if (!scrollContainer.value)
  57. return;
  58. scrollTop.value = scrollContainer.value instanceof Window ? document.documentElement.scrollTop : scrollContainer.value.scrollTop || 0;
  59. const { position, target: target2, offset } = props;
  60. const rootHeightOffset = offset + rootHeight.value;
  61. if (position === "top") {
  62. if (target2) {
  63. const difference = targetRect.bottom.value - rootHeightOffset;
  64. fixed.value = offset > rootTop.value && targetRect.bottom.value > 0;
  65. transform.value = difference < 0 ? difference : 0;
  66. } else {
  67. fixed.value = offset > rootTop.value;
  68. }
  69. } else if (target2) {
  70. const difference = windowHeight.value - targetRect.top.value - rootHeightOffset;
  71. fixed.value = windowHeight.value - offset < rootBottom.value && windowHeight.value > targetRect.top.value;
  72. transform.value = difference < 0 ? -difference : 0;
  73. } else {
  74. fixed.value = windowHeight.value - offset < rootBottom.value;
  75. }
  76. };
  77. const updateRootRect = async () => {
  78. if (!fixed.value) {
  79. updateRoot();
  80. return;
  81. }
  82. fixed.value = false;
  83. await nextTick();
  84. updateRoot();
  85. fixed.value = true;
  86. };
  87. const handleScroll = async () => {
  88. updateRoot();
  89. await nextTick();
  90. emit("scroll", {
  91. scrollTop: scrollTop.value,
  92. fixed: fixed.value
  93. });
  94. };
  95. watch(fixed, (val) => emit(CHANGE_EVENT, val));
  96. onMounted(() => {
  97. var _a;
  98. if (props.target) {
  99. target.value = (_a = document.querySelector(props.target)) != null ? _a : void 0;
  100. if (!target.value)
  101. throwError(COMPONENT_NAME, `Target does not exist: ${props.target}`);
  102. } else {
  103. target.value = document.documentElement;
  104. }
  105. scrollContainer.value = getScrollContainer(root.value, true);
  106. updateRoot();
  107. });
  108. useEventListener(scrollContainer, "scroll", handleScroll);
  109. watchEffect(update);
  110. expose({
  111. update,
  112. updateRoot: updateRootRect
  113. });
  114. return (_ctx, _cache) => {
  115. return openBlock(), createElementBlock("div", {
  116. ref_key: "root",
  117. ref: root,
  118. class: normalizeClass(unref(ns).b()),
  119. style: normalizeStyle(unref(rootStyle))
  120. }, [
  121. createElementVNode("div", {
  122. class: normalizeClass({ [unref(ns).m("fixed")]: fixed.value }),
  123. style: normalizeStyle(unref(affixStyle))
  124. }, [
  125. renderSlot(_ctx.$slots, "default")
  126. ], 6)
  127. ], 6);
  128. };
  129. }
  130. });
  131. var Affix = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "affix.vue"]]);
  132. export { Affix as default };
  133. //# sourceMappingURL=affix2.mjs.map