sub-menu-content.vue 2.3 KB

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