use-layout-style.ts 2.4 KB

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