tabs-view.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <script setup lang="ts">
  2. import type { TabsEmits, TabsProps } from './types';
  3. import { useForwardPropsEmits } from '@vben-core/composables';
  4. import { ChevronLeft, ChevronRight } from '@vben-core/icons';
  5. import { VbenScrollbar } from '@vben-core/shadcn-ui';
  6. import { Tabs, TabsChrome } from './components';
  7. import { useTabsDrag } from './use-tabs-drag';
  8. import { useTabsViewScroll } from './use-tabs-view-scroll';
  9. interface Props extends TabsProps {}
  10. defineOptions({
  11. name: 'TabsView',
  12. });
  13. const props = withDefaults(defineProps<Props>(), {
  14. contentClass: 'vben-tabs-content',
  15. draggable: true,
  16. styleType: 'chrome',
  17. wheelable: true,
  18. });
  19. const emit = defineEmits<TabsEmits>();
  20. const forward = useForwardPropsEmits(props, emit);
  21. const {
  22. handleScrollAt,
  23. handleWheel,
  24. scrollbarRef,
  25. scrollDirection,
  26. scrollIsAtLeft,
  27. scrollIsAtRight,
  28. showScrollButton,
  29. } = useTabsViewScroll(props);
  30. function onWheel(e: WheelEvent) {
  31. if (props.wheelable) {
  32. handleWheel(e);
  33. e.stopPropagation();
  34. e.preventDefault();
  35. }
  36. }
  37. useTabsDrag(props, emit);
  38. </script>
  39. <template>
  40. <div class="flex h-full flex-1 overflow-hidden">
  41. <!-- 左侧滚动按钮 -->
  42. <span
  43. v-show="showScrollButton"
  44. :class="{
  45. 'hover:bg-muted text-muted-foreground cursor-pointer': !scrollIsAtLeft,
  46. 'pointer-events-none opacity-30': scrollIsAtLeft,
  47. }"
  48. class="border-r px-2"
  49. @click="scrollDirection('left')"
  50. >
  51. <ChevronLeft class="size-4 h-full" />
  52. </span>
  53. <div
  54. :class="{
  55. 'pt-[3px]': styleType === 'chrome',
  56. }"
  57. class="size-full flex-1 overflow-hidden"
  58. >
  59. <VbenScrollbar
  60. ref="scrollbarRef"
  61. :shadow-bottom="false"
  62. :shadow-top="false"
  63. class="h-full"
  64. horizontal
  65. scroll-bar-class="z-10 hidden "
  66. shadow
  67. shadow-left
  68. shadow-right
  69. @scroll-at="handleScrollAt"
  70. @wheel="onWheel"
  71. >
  72. <TabsChrome
  73. v-if="styleType === 'chrome'"
  74. v-bind="{ ...forward, ...$attrs, ...$props }"
  75. />
  76. <Tabs v-else v-bind="{ ...forward, ...$attrs, ...$props }" />
  77. </VbenScrollbar>
  78. </div>
  79. <!-- 右侧滚动按钮 -->
  80. <span
  81. v-show="showScrollButton"
  82. :class="{
  83. 'hover:bg-muted text-muted-foreground cursor-pointer': !scrollIsAtRight,
  84. 'pointer-events-none opacity-30': scrollIsAtRight,
  85. }"
  86. class="hover:bg-muted text-muted-foreground cursor-pointer border-l px-2"
  87. @click="scrollDirection('right')"
  88. >
  89. <ChevronRight class="size-4 h-full" />
  90. </span>
  91. </div>
  92. </template>