Files
MajoorWaldi-ComfyUI-Majoor-…/ui/vue/grid/useInfiniteTrigger.ts
T

80 lines
1.9 KiB
TypeScript

import { getCurrentInstance, onBeforeUnmount, onMounted, ref, unref, watch } from "vue";
function readBool(value: any, fallback = true) {
const resolved = unref(value);
if (resolved == null) return fallback;
return !!resolved;
}
export function useInfiniteTrigger({
rootRef,
enabled = true,
canLoad = true,
loadMore,
rootMargin = "900px",
threshold = 0.01,
}: Record<string, any> = {}) {
const sentinelRef = ref(null);
let observer: any = null;
let loading = false;
function disconnect() {
try {
observer?.disconnect?.();
} catch (e) {
console.debug?.(e);
}
observer = null;
}
async function maybeLoad() {
if (loading) return;
if (!readBool(enabled, true) || !readBool(canLoad, true)) return;
if (typeof loadMore !== "function") return;
loading = true;
try {
await loadMore();
} finally {
loading = false;
}
}
function connect() {
disconnect();
const sentinel = sentinelRef.value;
if (!sentinel || typeof IntersectionObserver !== "function") return;
observer = new IntersectionObserver(
(entries = []) => {
const hit = entries.some((entry) => entry?.isIntersecting);
if (!hit) return;
void maybeLoad();
},
{
root: unref(rootRef) || null,
rootMargin,
threshold,
},
);
observer.observe(sentinel);
}
if (getCurrentInstance()) {
onMounted(connect);
onBeforeUnmount(disconnect);
watch(
() => [unref(rootRef), sentinelRef.value],
() => connect(),
{ flush: "post" },
);
}
return {
sentinelRef,
connect,
disconnect,
maybeLoad,
};
}