tabs-view.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <script setup lang="ts">
  2. import type { TabsEmits, TabsProps } from './types';
  3. import { useForwardPropsEmits } from '@vben-core/composables';
  4. import { ChevronsLeft, ChevronsRight } 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. // @ts-expect-error unused
  25. scrollbarRef,
  26. scrollDirection,
  27. scrollIsAtLeft,
  28. scrollIsAtRight,
  29. showScrollButton,
  30. } = useTabsViewScroll(props);
  31. function onWheel(e: WheelEvent) {
  32. if (props.wheelable) {
  33. handleWheel(e);
  34. e.stopPropagation();
  35. e.preventDefault();
  36. }
  37. }
  38. useTabsDrag(props, emit);
  39. </script>
  40. <template>
  41. <div class="flex h-full flex-1 overflow-hidden">
  42. <!-- 左侧滚动按钮 -->
  43. <span
  44. v-show="showScrollButton"
  45. :class="{
  46. 'cursor-pointer text-muted-foreground hover:bg-muted': !scrollIsAtLeft,
  47. 'pointer-events-none opacity-30': scrollIsAtLeft,
  48. }"
  49. class="border-r px-2"
  50. @click="scrollDirection('left')"
  51. >
  52. <ChevronsLeft class="size-4 h-full" />
  53. </span>
  54. <div
  55. :class="{
  56. 'pt-0.75': styleType === 'chrome',
  57. }"
  58. class="size-full flex-1 overflow-hidden"
  59. >
  60. <VbenScrollbar
  61. ref="scrollbarRef"
  62. :shadow-bottom="false"
  63. :shadow-top="false"
  64. class="h-full"
  65. horizontal
  66. scroll-bar-class="z-10 hidden "
  67. shadow
  68. shadow-left
  69. shadow-right
  70. @scroll-at="handleScrollAt"
  71. @wheel="onWheel"
  72. >
  73. <TabsChrome
  74. v-if="styleType === 'chrome'"
  75. v-bind="{ ...forward, ...$attrs, ...$props }"
  76. />
  77. <Tabs v-else v-bind="{ ...forward, ...$attrs, ...$props }" />
  78. </VbenScrollbar>
  79. </div>
  80. <!-- 右侧滚动按钮 -->
  81. <span
  82. v-show="showScrollButton"
  83. :class="{
  84. 'cursor-pointer text-muted-foreground hover:bg-muted': !scrollIsAtRight,
  85. 'pointer-events-none opacity-30': scrollIsAtRight,
  86. }"
  87. class="cursor-pointer border-l px-2 text-muted-foreground hover:bg-muted"
  88. @click="scrollDirection('right')"
  89. >
  90. <ChevronsRight class="size-4 h-full" />
  91. </span>
  92. </div>
  93. </template>