mirror of
https://github.com/certd/certd.git
synced 2026-07-30 01:07:38 +08:00
chore: code format
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
export { default as TabsChrome } from './tabs-chrome/tabs.vue';
|
||||
export { default as Tabs } from './tabs/tabs.vue';
|
||||
export { default as TabsChrome } from "./tabs-chrome/tabs.vue";
|
||||
export { default as Tabs } from "./tabs/tabs.vue";
|
||||
|
||||
@@ -13,14 +13,14 @@ interface Props extends TabsProps {}
|
||||
defineOptions({
|
||||
name: "VbenTabsChrome",
|
||||
// eslint-disable-next-line perfectionist/sort-objects
|
||||
inheritAttrs: false
|
||||
inheritAttrs: false,
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
contentClass: "vben-tabs-content",
|
||||
contextMenus: () => [],
|
||||
gap: 7,
|
||||
tabs: () => []
|
||||
tabs: () => [],
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -35,12 +35,12 @@ const tabRef = ref();
|
||||
const style = computed(() => {
|
||||
const { gap } = props;
|
||||
return {
|
||||
"--gap": `${gap}px`
|
||||
"--gap": `${gap}px`,
|
||||
};
|
||||
});
|
||||
|
||||
const tabsView = computed(() => {
|
||||
return props.tabs.map((tab) => {
|
||||
return props.tabs.map(tab => {
|
||||
const { fullPath, meta, name, path } = tab || {};
|
||||
const { affixTab, icon, newTabTitle, tabClosable, title } = meta || {};
|
||||
return {
|
||||
@@ -52,7 +52,7 @@ const tabsView = computed(() => {
|
||||
meta,
|
||||
name,
|
||||
path,
|
||||
title: (newTabTitle || title || name) as string
|
||||
title: (newTabTitle || title || name) as string,
|
||||
} as TabConfig;
|
||||
});
|
||||
});
|
||||
@@ -77,8 +77,8 @@ function onMouseDown(e: MouseEvent, tab: TabConfig) {
|
||||
{
|
||||
'is-active': tab.key === active,
|
||||
draggable: !tab.affixTab,
|
||||
'affix-tab': tab.affixTab
|
||||
}
|
||||
'affix-tab': tab.affixTab,
|
||||
},
|
||||
]"
|
||||
:data-active-tab="active"
|
||||
:data-index="i"
|
||||
|
||||
@@ -13,12 +13,12 @@ interface Props extends TabsProps {}
|
||||
defineOptions({
|
||||
name: "VbenTabs",
|
||||
// @ts-ignore
|
||||
inheritAttrs: false
|
||||
inheritAttrs: false,
|
||||
});
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
contentClass: "vben-tabs-content",
|
||||
contextMenus: () => [],
|
||||
tabs: () => []
|
||||
tabs: () => [],
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -30,21 +30,21 @@ const active = defineModel<string>("active");
|
||||
const typeWithClass = computed(() => {
|
||||
const typeClasses: Record<string, { content: string }> = {
|
||||
brisk: {
|
||||
content: `h-full after:content-[''] after:absolute after:bottom-0 after:left-0 after:w-full after:h-[1.5px] after:bg-primary after:scale-x-0 after:transition-[transform] after:ease-out after:duration-300 hover:after:scale-x-100 after:origin-left [&.is-active]:after:scale-x-100 [&:not(:first-child)]:border-l last:border-r last:border-r border-border`
|
||||
content: `h-full after:content-[''] after:absolute after:bottom-0 after:left-0 after:w-full after:h-[1.5px] after:bg-primary after:scale-x-0 after:transition-[transform] after:ease-out after:duration-300 hover:after:scale-x-100 after:origin-left [&.is-active]:after:scale-x-100 [&:not(:first-child)]:border-l last:border-r last:border-r border-border`,
|
||||
},
|
||||
card: {
|
||||
content: "h-[calc(100%-6px)] rounded-md ml-2 border border-border transition-all"
|
||||
content: "h-[calc(100%-6px)] rounded-md ml-2 border border-border transition-all",
|
||||
},
|
||||
plain: {
|
||||
content: "h-full [&:not(:first-child)]:border-l last:border-r border-border"
|
||||
}
|
||||
content: "h-full [&:not(:first-child)]:border-l last:border-r border-border",
|
||||
},
|
||||
};
|
||||
|
||||
return typeClasses[props.styleType || "plain"] || { content: "" };
|
||||
});
|
||||
|
||||
const tabsView = computed(() => {
|
||||
return props.tabs.map((tab) => {
|
||||
return props.tabs.map(tab => {
|
||||
const { fullPath, meta, name, path } = tab || {};
|
||||
const { affixTab, icon, newTabTitle, tabClosable, title } = meta || {};
|
||||
return {
|
||||
@@ -56,7 +56,7 @@ const tabsView = computed(() => {
|
||||
meta,
|
||||
name,
|
||||
path,
|
||||
title: (newTabTitle || title || name) as string
|
||||
title: (newTabTitle || title || name) as string,
|
||||
} as TabConfig;
|
||||
});
|
||||
});
|
||||
@@ -80,9 +80,9 @@ function onMouseDown(e: MouseEvent, tab: TabConfig) {
|
||||
{
|
||||
'is-active dark:bg-accent bg-primary/15': tab.key === active,
|
||||
draggable: !tab.affixTab,
|
||||
'affix-tab': tab.affixTab
|
||||
'affix-tab': tab.affixTab,
|
||||
},
|
||||
typeWithClass.content
|
||||
typeWithClass.content,
|
||||
]"
|
||||
:data-index="i"
|
||||
class="tab-item [&:not(.is-active)]:hover:bg-accent translate-all group relative flex cursor-pointer select-none"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './components/widgets';
|
||||
export { default as TabsView } from './tabs-view.vue';
|
||||
export type { IContextMenuItem } from '/@/vben/shadcn-ui';
|
||||
export * from "./components/widgets";
|
||||
export { default as TabsView } from "./tabs-view.vue";
|
||||
export type { IContextMenuItem } from "/@/vben/shadcn-ui";
|
||||
|
||||
@@ -12,14 +12,14 @@ import { useTabsViewScroll } from "./use-tabs-view-scroll";
|
||||
interface Props extends TabsProps {}
|
||||
|
||||
defineOptions({
|
||||
name: "TabsView"
|
||||
name: "TabsView",
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
contentClass: "vben-tabs-content",
|
||||
draggable: true,
|
||||
styleType: "chrome",
|
||||
wheelable: true
|
||||
wheelable: true,
|
||||
});
|
||||
|
||||
const emit = defineEmits<TabsEmits>();
|
||||
@@ -46,7 +46,7 @@ useTabsDrag(props, emit);
|
||||
v-show="showScrollButton"
|
||||
:class="{
|
||||
'hover:bg-muted text-muted-foreground cursor-pointer': !scrollIsAtLeft,
|
||||
'pointer-events-none opacity-30': scrollIsAtLeft
|
||||
'pointer-events-none opacity-30': scrollIsAtLeft,
|
||||
}"
|
||||
class="border-r px-2"
|
||||
@click="scrollDirection('left')"
|
||||
@@ -56,7 +56,7 @@ useTabsDrag(props, emit);
|
||||
|
||||
<div
|
||||
:class="{
|
||||
'pt-[3px]': styleType === 'chrome'
|
||||
'pt-[3px]': styleType === 'chrome',
|
||||
}"
|
||||
class="size-full flex-1 overflow-hidden"
|
||||
>
|
||||
@@ -72,7 +72,7 @@ useTabsDrag(props, emit);
|
||||
v-show="showScrollButton"
|
||||
:class="{
|
||||
'hover:bg-muted text-muted-foreground cursor-pointer': !scrollIsAtRight,
|
||||
'pointer-events-none opacity-30': scrollIsAtRight
|
||||
'pointer-events-none opacity-30': scrollIsAtRight,
|
||||
}"
|
||||
class="hover:bg-muted text-muted-foreground cursor-pointer border-l px-2"
|
||||
@click="scrollDirection('right')"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { IContextMenuItem } from '/@/vben/shadcn-ui';
|
||||
import type { TabDefinition, TabsStyleType } from '/@/vben/typings';
|
||||
import type { IContextMenuItem } from "/@/vben/shadcn-ui";
|
||||
import type { TabDefinition, TabsStyleType } from "/@/vben/typings";
|
||||
|
||||
export type TabsEmits = {
|
||||
close: [string];
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import type { Sortable } from '/@/vben/composables';
|
||||
import type { EmitType } from '/@/vben/typings';
|
||||
import type { Sortable } from "/@/vben/composables";
|
||||
import type { EmitType } from "/@/vben/typings";
|
||||
|
||||
import type { TabsProps } from './types';
|
||||
import type { TabsProps } from "./types";
|
||||
|
||||
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
||||
|
||||
import { useIsMobile, useSortable } from '/@/vben/composables';
|
||||
import { useIsMobile, useSortable } from "/@/vben/composables";
|
||||
|
||||
// 可能会找到拖拽的子元素,这里需要确保拖拽的dom时tab元素
|
||||
function findParentElement(element: HTMLElement) {
|
||||
const parentCls = 'group';
|
||||
return element.classList.contains(parentCls)
|
||||
? element
|
||||
: element.closest(`.${parentCls}`);
|
||||
const parentCls = "group";
|
||||
return element.classList.contains(parentCls) ? element : element.closest(`.${parentCls}`);
|
||||
}
|
||||
|
||||
export function useTabsDrag(props: TabsProps, emit: EmitType) {
|
||||
@@ -21,25 +19,23 @@ export function useTabsDrag(props: TabsProps, emit: EmitType) {
|
||||
async function initTabsSortable() {
|
||||
await nextTick();
|
||||
|
||||
const el = document.querySelectorAll(
|
||||
`.${props.contentClass}`,
|
||||
)?.[0] as HTMLElement;
|
||||
const el = document.querySelectorAll(`.${props.contentClass}`)?.[0] as HTMLElement;
|
||||
|
||||
if (!el) {
|
||||
console.warn('Element not found for sortable initialization');
|
||||
console.warn("Element not found for sortable initialization");
|
||||
return;
|
||||
}
|
||||
|
||||
const resetElState = async () => {
|
||||
el.style.cursor = 'default';
|
||||
el.style.cursor = "default";
|
||||
// el.classList.remove('dragging');
|
||||
el.querySelector('.draggable')?.classList.remove('dragging');
|
||||
el.querySelector(".draggable")?.classList.remove("dragging");
|
||||
};
|
||||
|
||||
const { initializeSortable } = useSortable(el, {
|
||||
filter: (_evt, target: HTMLElement) => {
|
||||
const parent = findParentElement(target);
|
||||
const draggable = parent?.classList.contains('draggable');
|
||||
const draggable = parent?.classList.contains("draggable");
|
||||
return !draggable || !props.draggable;
|
||||
},
|
||||
onEnd(evt) {
|
||||
@@ -59,28 +55,22 @@ export function useTabsDrag(props: TabsProps, emit: EmitType) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!srcParent.classList.contains('draggable')) {
|
||||
if (!srcParent.classList.contains("draggable")) {
|
||||
resetElState();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
oldIndex !== undefined &&
|
||||
newIndex !== undefined &&
|
||||
!Number.isNaN(oldIndex) &&
|
||||
!Number.isNaN(newIndex) &&
|
||||
oldIndex !== newIndex
|
||||
) {
|
||||
emit('sortTabs', oldIndex, newIndex);
|
||||
if (oldIndex !== undefined && newIndex !== undefined && !Number.isNaN(oldIndex) && !Number.isNaN(newIndex) && oldIndex !== newIndex) {
|
||||
emit("sortTabs", oldIndex, newIndex);
|
||||
}
|
||||
resetElState();
|
||||
},
|
||||
onMove(evt) {
|
||||
const parent = findParentElement(evt.related);
|
||||
if (parent?.classList.contains('draggable') && props.draggable) {
|
||||
const isCurrentAffix = evt.dragged.classList.contains('affix-tab');
|
||||
const isRelatedAffix = evt.related.classList.contains('affix-tab');
|
||||
if (parent?.classList.contains("draggable") && props.draggable) {
|
||||
const isCurrentAffix = evt.dragged.classList.contains("affix-tab");
|
||||
const isRelatedAffix = evt.related.classList.contains("affix-tab");
|
||||
// 不允许在固定的tab和非固定的tab之间互相拖拽
|
||||
return isCurrentAffix === isRelatedAffix;
|
||||
} else {
|
||||
@@ -88,8 +78,8 @@ export function useTabsDrag(props: TabsProps, emit: EmitType) {
|
||||
}
|
||||
},
|
||||
onStart: () => {
|
||||
el.style.cursor = 'grabbing';
|
||||
el.querySelector('.draggable')?.classList.add('dragging');
|
||||
el.style.cursor = "grabbing";
|
||||
el.querySelector(".draggable")?.classList.add("dragging");
|
||||
// el.classList.add('dragging');
|
||||
},
|
||||
});
|
||||
@@ -115,7 +105,7 @@ export function useTabsDrag(props: TabsProps, emit: EmitType) {
|
||||
() => {
|
||||
sortableInstance.value?.destroy();
|
||||
init();
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { TabsProps } from './types';
|
||||
import type { TabsProps } from "./types";
|
||||
|
||||
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
||||
|
||||
import { VbenScrollbar } from '/@/vben/shadcn-ui';
|
||||
import { VbenScrollbar } from "/@/vben/shadcn-ui";
|
||||
|
||||
import { useDebounceFn } from '@vueuse/core';
|
||||
import { useDebounceFn } from "@vueuse/core";
|
||||
|
||||
type DomElement = Element | null | undefined;
|
||||
|
||||
@@ -31,10 +31,7 @@ export function useTabsViewScroll(props: TabsProps) {
|
||||
};
|
||||
}
|
||||
|
||||
function scrollDirection(
|
||||
direction: 'left' | 'right',
|
||||
distance: number = 150,
|
||||
) {
|
||||
function scrollDirection(direction: "left" | "right", distance: number = 150) {
|
||||
const { scrollbarWidth, scrollViewWidth } = getScrollClientWidth();
|
||||
|
||||
if (!scrollbarWidth || !scrollViewWidth) return;
|
||||
@@ -42,11 +39,8 @@ export function useTabsViewScroll(props: TabsProps) {
|
||||
if (scrollbarWidth > scrollViewWidth) return;
|
||||
|
||||
scrollViewportEl.value?.scrollBy({
|
||||
behavior: 'smooth',
|
||||
left:
|
||||
direction === 'left'
|
||||
? -(scrollbarWidth - distance)
|
||||
: +(scrollbarWidth - distance),
|
||||
behavior: "smooth",
|
||||
left: direction === "left" ? -(scrollbarWidth - distance) : +(scrollbarWidth - distance),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,9 +52,7 @@ export function useTabsViewScroll(props: TabsProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
const viewportEl = scrollbarEl?.querySelector(
|
||||
'div[data-radix-scroll-area-viewport]',
|
||||
);
|
||||
const viewportEl = scrollbarEl?.querySelector("div[data-radix-scroll-area-viewport]");
|
||||
|
||||
scrollViewportEl.value = viewportEl;
|
||||
calcShowScrollbarButton();
|
||||
@@ -74,7 +66,7 @@ export function useTabsViewScroll(props: TabsProps) {
|
||||
useDebounceFn((_entries: ResizeObserverEntry[]) => {
|
||||
calcShowScrollbarButton();
|
||||
scrollToActiveIntoView();
|
||||
}, 100),
|
||||
}, 100)
|
||||
);
|
||||
resizeObserver.observe(viewportEl);
|
||||
|
||||
@@ -82,9 +74,7 @@ export function useTabsViewScroll(props: TabsProps) {
|
||||
mutationObserver?.disconnect();
|
||||
// 使用 MutationObserver 仅监听子节点数量变化
|
||||
mutationObserver = new MutationObserver(() => {
|
||||
const count = viewportEl.querySelectorAll(
|
||||
`div[data-tab-item="true"]`,
|
||||
).length;
|
||||
const count = viewportEl.querySelectorAll(`div[data-tab-item="true"]`).length;
|
||||
|
||||
if (count > tabItemCount) {
|
||||
scrollToActiveIntoView();
|
||||
@@ -118,8 +108,8 @@ export function useTabsViewScroll(props: TabsProps) {
|
||||
}
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
const activeItem = viewportEl?.querySelector('.is-active');
|
||||
activeItem?.scrollIntoView({ behavior: 'smooth', inline: 'start' });
|
||||
const activeItem = viewportEl?.querySelector(".is-active");
|
||||
activeItem?.scrollIntoView({ behavior: "smooth", inline: "start" });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -133,8 +123,7 @@ export function useTabsViewScroll(props: TabsProps) {
|
||||
|
||||
const { scrollbarWidth } = getScrollClientWidth();
|
||||
|
||||
showScrollButton.value =
|
||||
scrollViewportEl.value.scrollWidth > scrollbarWidth;
|
||||
showScrollButton.value = scrollViewportEl.value.scrollWidth > scrollbarWidth;
|
||||
}
|
||||
|
||||
const handleScrollAt = useDebounceFn(({ left, right }) => {
|
||||
@@ -158,8 +147,8 @@ export function useTabsViewScroll(props: TabsProps) {
|
||||
// }, 300);
|
||||
},
|
||||
{
|
||||
flush: 'post',
|
||||
},
|
||||
flush: "post",
|
||||
}
|
||||
);
|
||||
|
||||
// watch(
|
||||
@@ -177,7 +166,7 @@ export function useTabsViewScroll(props: TabsProps) {
|
||||
() => props.styleType,
|
||||
() => {
|
||||
initScrollbar();
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(initScrollbar);
|
||||
|
||||
Reference in New Issue
Block a user