Vulture/VApp/node_modules/vuetify/lib/components/VInfiniteScroll/VInfiniteScroll.mjs

240 lines
7.8 KiB
JavaScript

import { createVNode as _createVNode, createTextVNode as _createTextVNode } from "vue";
// Styles
import "./VInfiniteScroll.css";
// Components
import { VBtn } from "../VBtn/index.mjs";
import { VProgressCircular } from "../VProgressCircular/index.mjs"; // Composables
import { makeDimensionProps, useDimension } from "../../composables/dimensions.mjs";
import { useIntersectionObserver } from "../../composables/intersectionObserver.mjs";
import { useLocale } from "../../composables/locale.mjs";
import { makeTagProps } from "../../composables/tag.mjs"; // Utilities
import { computed, nextTick, onMounted, ref, shallowRef, watch } from 'vue';
import { convertToUnit, defineComponent, genericComponent, propsFactory, useRender } from "../../util/index.mjs"; // Types
export const makeVInfiniteScrollProps = propsFactory({
color: String,
direction: {
type: String,
default: 'vertical',
validator: v => ['vertical', 'horizontal'].includes(v)
},
side: {
type: String,
default: 'end',
validator: v => ['start', 'end', 'both'].includes(v)
},
mode: {
type: String,
default: 'intersect',
validator: v => ['intersect', 'manual'].includes(v)
},
margin: [Number, String],
loadMoreText: {
type: String,
default: '$vuetify.infiniteScroll.loadMore'
},
emptyText: {
type: String,
default: '$vuetify.infiniteScroll.empty'
},
...makeDimensionProps(),
...makeTagProps()
}, 'VInfiniteScroll');
export const VInfiniteScrollIntersect = defineComponent({
name: 'VInfiniteScrollIntersect',
props: {
side: {
type: String,
required: true
},
rootRef: null,
rootMargin: String
},
emits: {
intersect: (side, isIntersecting) => true
},
setup(props, _ref) {
let {
emit
} = _ref;
const {
intersectionRef,
isIntersecting
} = useIntersectionObserver(entries => {}, props.rootMargin ? {
rootMargin: props.rootMargin
} : undefined);
watch(isIntersecting, async val => {
emit('intersect', props.side, val);
});
useRender(() => _createVNode("div", {
"class": "v-infinite-scroll-intersect",
"ref": intersectionRef
}, [_createTextVNode("\xA0")]));
return {};
}
});
export const VInfiniteScroll = genericComponent()({
name: 'VInfiniteScroll',
props: makeVInfiniteScrollProps(),
emits: {
load: options => true
},
setup(props, _ref2) {
let {
slots,
emit
} = _ref2;
const rootEl = ref();
const startStatus = shallowRef('ok');
const endStatus = shallowRef('ok');
const margin = computed(() => convertToUnit(props.margin));
const isIntersecting = shallowRef(false);
function setScrollAmount(amount) {
if (!rootEl.value) return;
const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
rootEl.value[property] = amount;
}
function getScrollAmount() {
if (!rootEl.value) return 0;
const property = props.direction === 'vertical' ? 'scrollTop' : 'scrollLeft';
return rootEl.value[property];
}
function getScrollSize() {
if (!rootEl.value) return 0;
const property = props.direction === 'vertical' ? 'scrollHeight' : 'scrollWidth';
return rootEl.value[property];
}
function getContainerSize() {
if (!rootEl.value) return 0;
const property = props.direction === 'vertical' ? 'clientHeight' : 'clientWidth';
return rootEl.value[property];
}
onMounted(() => {
if (!rootEl.value) return;
if (props.side === 'start') {
setScrollAmount(getScrollSize());
} else if (props.side === 'both') {
setScrollAmount(getScrollSize() / 2 - getContainerSize() / 2);
}
});
function setStatus(side, status) {
if (side === 'start') {
startStatus.value = status;
} else if (side === 'end') {
endStatus.value = status;
}
}
function getStatus(side) {
return side === 'start' ? startStatus.value : endStatus.value;
}
let previousScrollSize = 0;
function handleIntersect(side, _isIntersecting) {
isIntersecting.value = _isIntersecting;
if (isIntersecting.value) {
intersecting(side);
}
}
function intersecting(side) {
if (props.mode !== 'manual' && !isIntersecting.value) return;
const status = getStatus(side);
if (!rootEl.value || status === 'loading') return;
previousScrollSize = getScrollSize();
setStatus(side, 'loading');
function done(status) {
setStatus(side, status);
nextTick(() => {
if (status === 'empty' || status === 'error') return;
if (status === 'ok' && side === 'start') {
setScrollAmount(getScrollSize() - previousScrollSize + getScrollAmount());
}
if (props.mode !== 'manual') {
nextTick(() => {
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() => {
intersecting(side);
});
});
});
});
}
});
}
emit('load', {
side,
done
});
}
const {
t
} = useLocale();
function renderSide(side, status) {
if (props.side !== side && props.side !== 'both') return;
const onClick = () => intersecting(side);
const slotProps = {
side,
props: {
onClick,
color: props.color
}
};
if (status === 'error') return slots.error?.(slotProps);
if (status === 'empty') return slots.empty?.(slotProps) ?? _createVNode("div", null, [t(props.emptyText)]);
if (props.mode === 'manual') {
if (status === 'loading') {
return slots.loading?.(slotProps) ?? _createVNode(VProgressCircular, {
"indeterminate": true,
"color": props.color
}, null);
}
return slots['load-more']?.(slotProps) ?? _createVNode(VBtn, {
"variant": "outlined",
"color": props.color,
"onClick": onClick
}, {
default: () => [t(props.loadMoreText)]
});
}
return slots.loading?.(slotProps) ?? _createVNode(VProgressCircular, {
"indeterminate": true,
"color": props.color
}, null);
}
const {
dimensionStyles
} = useDimension(props);
useRender(() => {
const Tag = props.tag;
const hasStartIntersect = props.side === 'start' || props.side === 'both';
const hasEndIntersect = props.side === 'end' || props.side === 'both';
const intersectMode = props.mode === 'intersect';
return _createVNode(Tag, {
"ref": rootEl,
"class": ['v-infinite-scroll', `v-infinite-scroll--${props.direction}`, {
'v-infinite-scroll--start': hasStartIntersect,
'v-infinite-scroll--end': hasEndIntersect
}],
"style": dimensionStyles.value
}, {
default: () => [_createVNode("div", {
"class": "v-infinite-scroll__side"
}, [renderSide('start', startStatus.value)]), rootEl.value && hasStartIntersect && intersectMode && _createVNode(VInfiniteScrollIntersect, {
"key": "start",
"side": "start",
"onIntersect": handleIntersect,
"rootRef": rootEl.value,
"rootMargin": margin.value
}, null), slots.default?.(), rootEl.value && hasEndIntersect && intersectMode && _createVNode(VInfiniteScrollIntersect, {
"key": "end",
"side": "end",
"onIntersect": handleIntersect,
"rootRef": rootEl.value,
"rootMargin": margin.value
}, null), _createVNode("div", {
"class": "v-infinite-scroll__side"
}, [renderSide('end', endStatus.value)])]
});
});
}
});
//# sourceMappingURL=VInfiniteScroll.mjs.map