ant-design-vue/components/_util/hooks/_vueuse/useElementSize.ts
2023-04-05 22:03:02 +08:00

66 lines
1.6 KiB
TypeScript

import { shallowRef, watch } from 'vue';
import type { MaybeComputedElementRef } from './unrefElement';
import type { UseResizeObserverOptions } from './useResizeObserver';
import { useResizeObserver } from './useResizeObserver';
import { unrefElement } from './unrefElement';
export interface ElementSize {
width: number;
height: number;
}
/**
* Reactive size of an HTML element.
*
* @see https://vueuse.org/useElementSize
* @param target
* @param callback
* @param options
*/
export function useElementSize(
target: MaybeComputedElementRef,
initialSize: ElementSize = { width: 0, height: 0 },
options: UseResizeObserverOptions = {},
) {
const { box = 'content-box' } = options;
const width = shallowRef(initialSize.width);
const height = shallowRef(initialSize.height);
useResizeObserver(
target,
([entry]) => {
const boxSize =
box === 'border-box'
? entry.borderBoxSize
: box === 'content-box'
? entry.contentBoxSize
: entry.devicePixelContentBoxSize;
if (boxSize) {
width.value = boxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0);
height.value = boxSize.reduce((acc, { blockSize }) => acc + blockSize, 0);
} else {
// fallback
width.value = entry.contentRect.width;
height.value = entry.contentRect.height;
}
},
options,
);
watch(
() => unrefElement(target),
ele => {
width.value = ele ? initialSize.width : 0;
height.value = ele ? initialSize.height : 0;
},
);
return {
width,
height,
};
}
export type UseElementSizeReturn = ReturnType<typeof useElementSize>;