12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- // Utilities
- import { computed, onBeforeUnmount, onMounted, shallowRef, watch } from 'vue';
- import { convertToUnit } from "../../util/index.mjs"; // Types
- export function useSticky(_ref) {
- let {
- rootEl,
- isSticky,
- layoutItemStyles
- } = _ref;
- const isStuck = shallowRef(false);
- const stuckPosition = shallowRef(0);
- const stickyStyles = computed(() => {
- const side = typeof isStuck.value === 'boolean' ? 'top' : isStuck.value;
- return [isSticky.value ? {
- top: 'auto',
- bottom: 'auto',
- height: undefined
- } : undefined, isStuck.value ? {
- [side]: convertToUnit(stuckPosition.value)
- } : {
- top: layoutItemStyles.value.top
- }];
- });
- onMounted(() => {
- watch(isSticky, val => {
- if (val) {
- window.addEventListener('scroll', onScroll, {
- passive: true
- });
- } else {
- window.removeEventListener('scroll', onScroll);
- }
- }, {
- immediate: true
- });
- });
- onBeforeUnmount(() => {
- window.removeEventListener('scroll', onScroll);
- });
- let lastScrollTop = 0;
- function onScroll() {
- const direction = lastScrollTop > window.scrollY ? 'up' : 'down';
- const rect = rootEl.value.getBoundingClientRect();
- const layoutTop = parseFloat(layoutItemStyles.value.top ?? 0);
- const top = window.scrollY - Math.max(0, stuckPosition.value - layoutTop);
- const bottom = rect.height + Math.max(stuckPosition.value, layoutTop) - window.scrollY - window.innerHeight;
- const bodyScroll = parseFloat(getComputedStyle(rootEl.value).getPropertyValue('--v-body-scroll-y')) || 0;
- if (rect.height < window.innerHeight - layoutTop) {
- isStuck.value = 'top';
- stuckPosition.value = layoutTop;
- } else if (direction === 'up' && isStuck.value === 'bottom' || direction === 'down' && isStuck.value === 'top') {
- stuckPosition.value = window.scrollY + rect.top - bodyScroll;
- isStuck.value = true;
- } else if (direction === 'down' && bottom <= 0) {
- stuckPosition.value = 0;
- isStuck.value = 'bottom';
- } else if (direction === 'up' && top <= 0) {
- if (!bodyScroll) {
- stuckPosition.value = rect.top + top;
- isStuck.value = 'top';
- } else if (isStuck.value !== 'top') {
- stuckPosition.value = -top + bodyScroll + layoutTop;
- isStuck.value = 'top';
- }
- }
- lastScrollTop = window.scrollY;
- }
- return {
- isStuck,
- stickyStyles
- };
- }
- //# sourceMappingURL=sticky.mjs.map
|