sub-menu-content.vue 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <script lang="ts" setup>
  2. import type { MenuItemProps } from '../interface';
  3. import { computed } from 'vue';
  4. import { useNamespace } from '@vben-core/hooks';
  5. import {
  6. IcRoundChevronRight,
  7. IcRoundKeyboardArrowDown,
  8. } from '@vben-core/iconify';
  9. import { VbenIcon } from '@vben-core/shadcn-ui';
  10. import { useMenuContext } from '../hooks';
  11. interface Props extends MenuItemProps {
  12. isMenuMore: boolean;
  13. isTopLevelMenuSubmenu: boolean;
  14. level?: number;
  15. }
  16. defineOptions({ name: 'SubMenuContent' });
  17. const props = withDefaults(defineProps<Props>(), {
  18. isMenuMore: false,
  19. level: 0,
  20. });
  21. const rootMenu = useMenuContext();
  22. const { b, e, is } = useNamespace('sub-menu-content');
  23. const nsMenu = useNamespace('menu');
  24. const opened = computed(() => {
  25. return rootMenu?.openedMenus.includes(props.path);
  26. });
  27. const collapse = computed(() => {
  28. return rootMenu.props.collapse;
  29. });
  30. const isFirstLevel = computed(() => {
  31. return props.level === 1;
  32. });
  33. const getCollapseShowTitle = computed(() => {
  34. return (
  35. rootMenu.props.collapseShowTitle && isFirstLevel.value && collapse.value
  36. );
  37. });
  38. const mode = computed(() => {
  39. return rootMenu?.props.mode;
  40. });
  41. const showArrowIcon = computed(() => {
  42. return mode.value === 'horizontal' || !(isFirstLevel.value && collapse.value);
  43. });
  44. const hiddenTitle = computed(() => {
  45. return (
  46. mode.value === 'vertical' &&
  47. isFirstLevel.value &&
  48. collapse.value &&
  49. !getCollapseShowTitle.value
  50. );
  51. });
  52. const iconComp = computed(() => {
  53. return (mode.value === 'horizontal' && !isFirstLevel.value) ||
  54. (mode.value === 'vertical' && collapse.value)
  55. ? IcRoundChevronRight
  56. : IcRoundKeyboardArrowDown;
  57. });
  58. const iconArrowStyle = computed(() => {
  59. return opened.value ? { transform: `rotate(180deg)` } : {};
  60. });
  61. </script>
  62. <template>
  63. <div
  64. :class="[
  65. b(),
  66. is('collapse-show-title', getCollapseShowTitle),
  67. is('more', isMenuMore),
  68. ]"
  69. >
  70. <slot></slot>
  71. <VbenIcon
  72. v-if="!isMenuMore"
  73. :class="nsMenu.e('icon')"
  74. :icon="icon"
  75. fallback
  76. />
  77. <div v-if="!hiddenTitle" :class="[e('title')]">
  78. <slot name="title"></slot>
  79. </div>
  80. <component
  81. :is="iconComp"
  82. v-if="!isMenuMore"
  83. v-show="showArrowIcon"
  84. :class="[e('icon-arrow')]"
  85. :style="iconArrowStyle"
  86. />
  87. </div>
  88. </template>