From f039dfd09f6ebf7618d346ab045a6bf1cf994029 Mon Sep 17 00:00:00 2001 From: Michael Brevard Date: Mon, 25 Mar 2024 15:07:52 +0200 Subject: [PATCH] feat: provide exported function --- packages/nuxt/src/app/utils.ts | 61 ++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/packages/nuxt/src/app/utils.ts b/packages/nuxt/src/app/utils.ts index 4cc2040ad9..2dd929f23e 100644 --- a/packages/nuxt/src/app/utils.ts +++ b/packages/nuxt/src/app/utils.ts @@ -1,3 +1,64 @@ +import type { + AllowedComponentProps, + AnchorHTMLAttributes, + ComputedRef, + DefineComponent, + InjectionKey, PropType, + VNodeProps +} from 'vue' +import { computed, defineComponent, h, inject, onBeforeUnmount, onMounted, provide, ref, resolveComponent } from 'vue' +import type { RouteLocation, RouteLocationRaw, Router, RouterLinkProps } from '#vue-router' +import { hasProtocol, joinURL, parseQuery, parseURL, withTrailingSlash, withoutTrailingSlash } from 'ufo' +import { preloadRouteComponents } from './composables/preload' +import { onNuxtReady } from './composables/ready' +import { navigateTo, useRouter } from './composables/router' +import { useNuxtApp, useRuntimeConfig } from './nuxt' +import { cancelIdleCallback, requestIdleCallback } from './idle-callback' + export function toArray (value: T | T[]): T[] { return Array.isArray(value) ? value : [value] } + +export type CallbackFn = () => void +type ObserveFn = (element: Element, callback: CallbackFn) => () => void + +function useObserver (): { observe: ObserveFn } | undefined { + if (import.meta.server) { return } + + const nuxtApp = useNuxtApp() + if (nuxtApp._observer) { + return nuxtApp._observer + } + + let observer: IntersectionObserver | null = null + + const callbacks = new Map() + + const observe: ObserveFn = (element, callback) => { + if (!observer) { + observer = new IntersectionObserver((entries) => { + for (const entry of entries) { + const callback = callbacks.get(entry.target) + const isVisible = entry.isIntersecting || entry.intersectionRatio > 0 + if (isVisible && callback) { callback() } + } + }) + } + callbacks.set(element, callback) + observer.observe(element) + return () => { + callbacks.delete(element) + observer!.unobserve(element) + if (callbacks.size === 0) { + observer!.disconnect() + observer = null + } + } + } + + const _observer = nuxtApp._observer = { + observe + } + + return _observer +}