use-layout-style.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import type { CSSProperties } from 'vue';
  2. import type { VisibleDomRect } from '@vben-core/shared/utils';
  3. import { computed, onMounted, onUnmounted, ref } from 'vue';
  4. import {
  5. CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT,
  6. CSS_VARIABLE_LAYOUT_CONTENT_WIDTH,
  7. CSS_VARIABLE_LAYOUT_FOOTER_HEIGHT,
  8. CSS_VARIABLE_LAYOUT_HEADER_HEIGHT,
  9. } from '@vben-core/shared/constants';
  10. import { getElementVisibleRect } from '@vben-core/shared/utils';
  11. import { useCssVar, useDebounceFn } from '@vueuse/core';
  12. /**
  13. * @zh_CN content style
  14. */
  15. export function useLayoutContentStyle() {
  16. let resizeObserver: null | ResizeObserver = null;
  17. const contentElement = ref<HTMLDivElement | null>(null);
  18. const visibleDomRect = ref<null | VisibleDomRect>(null);
  19. const contentHeight = useCssVar(CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT);
  20. const contentWidth = useCssVar(CSS_VARIABLE_LAYOUT_CONTENT_WIDTH);
  21. const overlayStyle = computed((): CSSProperties => {
  22. const { height, left, top, width } = visibleDomRect.value ?? {};
  23. return {
  24. height: `${height}px`,
  25. left: `${left}px`,
  26. position: 'fixed',
  27. top: `${top}px`,
  28. width: `${width}px`,
  29. zIndex: 150,
  30. };
  31. });
  32. const debouncedCalcHeight = useDebounceFn(
  33. (_entries: ResizeObserverEntry[]) => {
  34. visibleDomRect.value = getElementVisibleRect(contentElement.value);
  35. contentHeight.value = `${visibleDomRect.value.height}px`;
  36. contentWidth.value = `${visibleDomRect.value.width}px`;
  37. },
  38. 16,
  39. );
  40. onMounted(() => {
  41. if (contentElement.value && !resizeObserver) {
  42. resizeObserver = new ResizeObserver(debouncedCalcHeight);
  43. resizeObserver.observe(contentElement.value);
  44. }
  45. });
  46. onUnmounted(() => {
  47. resizeObserver?.disconnect();
  48. resizeObserver = null;
  49. });
  50. return { contentElement, overlayStyle, visibleDomRect };
  51. }
  52. export function useLayoutHeaderStyle() {
  53. const headerHeight = useCssVar(CSS_VARIABLE_LAYOUT_HEADER_HEIGHT);
  54. return {
  55. getLayoutHeaderHeight: () => {
  56. return Number.parseInt(`${headerHeight.value}`, 10);
  57. },
  58. setLayoutHeaderHeight: (height: number) => {
  59. headerHeight.value = `${height}px`;
  60. },
  61. };
  62. }
  63. export function useLayoutFooterStyle() {
  64. const footerHeight = useCssVar(CSS_VARIABLE_LAYOUT_FOOTER_HEIGHT);
  65. return {
  66. getLayoutFooterHeight: () => {
  67. return Number.parseInt(`${footerHeight.value}`, 10);
  68. },
  69. setLayoutFooterHeight: (height: number) => {
  70. footerHeight.value = `${height}px`;
  71. },
  72. };
  73. }