affix2.mjs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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 handleScroll = async () => {
  78. updateRoot();
  79. await nextTick();
  80. emit("scroll", {
  81. scrollTop: scrollTop.value,
  82. fixed: fixed.value
  83. });
  84. };
  85. watch(fixed, (val) => emit(CHANGE_EVENT, val));
  86. onMounted(() => {
  87. var _a;
  88. if (props.target) {
  89. target.value = (_a = document.querySelector(props.target)) != null ? _a : void 0;
  90. if (!target.value)
  91. throwError(COMPONENT_NAME, `Target does not exist: ${props.target}`);
  92. } else {
  93. target.value = document.documentElement;
  94. }
  95. scrollContainer.value = getScrollContainer(root.value, true);
  96. updateRoot();
  97. });
  98. useEventListener(scrollContainer, "scroll", handleScroll);
  99. watchEffect(update);
  100. expose({
  101. update,
  102. updateRoot
  103. });
  104. return (_ctx, _cache) => {
  105. return openBlock(), createElementBlock("div", {
  106. ref_key: "root",
  107. ref: root,
  108. class: normalizeClass(unref(ns).b()),
  109. style: normalizeStyle(unref(rootStyle))
  110. }, [
  111. createElementVNode("div", {
  112. class: normalizeClass({ [unref(ns).m("fixed")]: fixed.value }),
  113. style: normalizeStyle(unref(affixStyle))
  114. }, [
  115. renderSlot(_ctx.$slots, "default")
  116. ], 6)
  117. ], 6);
  118. };
  119. }
  120. });
  121. var Affix = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "affix.vue"]]);
  122. export { Affix as default };
  123. //# sourceMappingURL=affix2.mjs.map