use-content-style.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import type { CSSProperties } from 'vue';
  2. import { computed, nextTick, onMounted, ref } from 'vue';
  3. import {
  4. CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT,
  5. CSS_VARIABLE_LAYOUT_CONTENT_WIDTH,
  6. getElementVisibleRect,
  7. type VisibleDomRect,
  8. } from '@vben-core/shared';
  9. import { useCssVar, useDebounceFn } from '@vueuse/core';
  10. /**
  11. * @zh_CN content style
  12. */
  13. function useContentStyle() {
  14. const contentElement = ref<HTMLDivElement | null>(null);
  15. const visibleDomRect = ref<null | VisibleDomRect>(null);
  16. const contentHeight = useCssVar(CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT);
  17. const contentWidth = useCssVar(CSS_VARIABLE_LAYOUT_CONTENT_WIDTH);
  18. const overlayStyle = computed((): CSSProperties => {
  19. const { height, left, top, width } = visibleDomRect.value ?? {};
  20. return {
  21. height: `${height}px`,
  22. left: `${left}px`,
  23. position: 'fixed',
  24. top: `${top}px`,
  25. width: `${width}px`,
  26. zIndex: 1000,
  27. };
  28. });
  29. const debouncedCalcHeight = useDebounceFn(
  30. (_entries: ResizeObserverEntry[]) => {
  31. visibleDomRect.value = getElementVisibleRect(contentElement.value);
  32. contentHeight.value = `${visibleDomRect.value.height}px`;
  33. contentWidth.value = `${visibleDomRect.value.width}px`;
  34. },
  35. 100,
  36. );
  37. onMounted(() => {
  38. nextTick(() => {
  39. if (contentElement.value) {
  40. const observer = new ResizeObserver(debouncedCalcHeight);
  41. observer.observe(contentElement.value);
  42. }
  43. });
  44. });
  45. return { contentElement, overlayStyle, visibleDomRect };
  46. }
  47. export { useContentStyle };