ant-design-vue/components/_util/hooks/_vueuse/useResizeObserver.ts
2022-11-07 13:42:51 +08:00

95 lines
2.5 KiB
TypeScript

import { tryOnScopeDispose } from './tryOnScopeDispose';
import { watch } from 'vue';
import type { MaybeComputedElementRef } from './unrefElement';
import { unrefElement } from './unrefElement';
import { useSupported } from './useSupported';
import type { ConfigurableWindow } from './_configurable';
import { defaultWindow } from './_configurable';
export interface ResizeObserverSize {
readonly inlineSize: number;
readonly blockSize: number;
}
export interface ResizeObserverEntry {
readonly target: Element;
readonly contentRect: DOMRectReadOnly;
readonly borderBoxSize?: ReadonlyArray<ResizeObserverSize>;
readonly contentBoxSize?: ReadonlyArray<ResizeObserverSize>;
readonly devicePixelContentBoxSize?: ReadonlyArray<ResizeObserverSize>;
}
export type ResizeObserverCallback = (
entries: ReadonlyArray<ResizeObserverEntry>,
observer: ResizeObserver,
) => void;
export interface UseResizeObserverOptions extends ConfigurableWindow {
/**
* Sets which box model the observer will observe changes to. Possible values
* are `content-box` (the default), `border-box` and `device-pixel-content-box`.
*
* @default 'content-box'
*/
box?: ResizeObserverBoxOptions;
}
declare class ResizeObserver {
constructor(callback: ResizeObserverCallback);
disconnect(): void;
observe(target: Element, options?: UseResizeObserverOptions): void;
unobserve(target: Element): void;
}
/**
* Reports changes to the dimensions of an Element's content or the border-box
*
* @see https://vueuse.org/useResizeObserver
* @param target
* @param callback
* @param options
*/
export function useResizeObserver(
target: MaybeComputedElementRef,
callback: ResizeObserverCallback,
options: UseResizeObserverOptions = {},
) {
const { window = defaultWindow, ...observerOptions } = options;
let observer: ResizeObserver | undefined;
const isSupported = useSupported(() => window && 'ResizeObserver' in window);
const cleanup = () => {
if (observer) {
observer.disconnect();
observer = undefined;
}
};
const stopWatch = watch(
() => unrefElement(target),
el => {
cleanup();
if (isSupported.value && window && el) {
observer = new ResizeObserver(callback);
observer!.observe(el, observerOptions);
}
},
{ immediate: true, flush: 'post' },
);
const stop = () => {
cleanup();
stopWatch();
};
tryOnScopeDispose(stop);
return {
isSupported,
stop,
};
}
export type UseResizeObserverReturn = ReturnType<typeof useResizeObserver>;