chore: remove tab drag sortable runtime
This commit is contained in:
@@ -37,10 +37,6 @@
|
||||
"dependencies": {
|
||||
"@vben-core/shared": "workspace:*",
|
||||
"@vueuse/core": "catalog:",
|
||||
"sortablejs": "catalog:",
|
||||
"vue": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/sortablejs": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import type { SortableOptions } from 'sortablejs';
|
||||
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { useSortable } from '../use-sortable';
|
||||
|
||||
describe('useSortable', () => {
|
||||
beforeEach(() => {
|
||||
vi.mock('sortablejs/modular/sortable.complete.esm.js', () => ({
|
||||
default: {
|
||||
create: vi.fn(),
|
||||
},
|
||||
}));
|
||||
});
|
||||
it('should call Sortable.create with the correct options', async () => {
|
||||
// Create a mock element
|
||||
const mockElement = document.createElement('div') as HTMLDivElement;
|
||||
|
||||
// Define custom options
|
||||
const customOptions: SortableOptions = {
|
||||
group: 'test-group',
|
||||
sort: false,
|
||||
};
|
||||
|
||||
// Use the useSortable function
|
||||
const { initializeSortable } = useSortable(mockElement, customOptions);
|
||||
|
||||
// Initialize sortable
|
||||
await initializeSortable();
|
||||
|
||||
// Import sortablejs to access the mocked create function
|
||||
const Sortable =
|
||||
await import('sortablejs/modular/sortable.complete.esm.js');
|
||||
|
||||
// Verify that Sortable.create was called with the correct parameters
|
||||
expect(Sortable.default.create).toHaveBeenCalledTimes(1);
|
||||
expect(Sortable.default.create).toHaveBeenCalledWith(
|
||||
mockElement,
|
||||
expect.objectContaining({
|
||||
animation: 300,
|
||||
delay: 400,
|
||||
delayOnTouchOnly: true,
|
||||
...customOptions,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -5,4 +5,3 @@ export * from './use-namespace';
|
||||
export * from './use-priority-value';
|
||||
export * from './use-scroll-lock';
|
||||
export * from './use-simple-locale';
|
||||
export * from './use-sortable';
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import type { SortableOptions } from 'sortablejs';
|
||||
import type Sortable from 'sortablejs';
|
||||
|
||||
function useSortable<T extends HTMLElement>(
|
||||
sortableContainer: T,
|
||||
options: SortableOptions = {},
|
||||
) {
|
||||
const initializeSortable = async () => {
|
||||
const Sortable = await import(
|
||||
// @ts-expect-error - This is a dynamic import
|
||||
'sortablejs/modular/sortable.complete.esm.js'
|
||||
);
|
||||
const sortable = Sortable?.default?.create?.(sortableContainer, {
|
||||
animation: 300,
|
||||
delay: 400,
|
||||
delayOnTouchOnly: true,
|
||||
...options,
|
||||
});
|
||||
return sortable as Sortable;
|
||||
};
|
||||
|
||||
return {
|
||||
initializeSortable,
|
||||
};
|
||||
}
|
||||
|
||||
export { useSortable };
|
||||
|
||||
export type { Sortable };
|
||||
@@ -6,7 +6,6 @@ import { ChevronLeft, ChevronRight } from '@vben-core/icons';
|
||||
import { VbenScrollbar } from '@vben-core/shadcn-ui';
|
||||
|
||||
import { Tabs, TabsChrome } from './components';
|
||||
import { useTabsDrag } from './use-tabs-drag';
|
||||
import { useTabsViewScroll } from './use-tabs-view-scroll';
|
||||
|
||||
interface Props extends TabsProps {}
|
||||
@@ -43,8 +42,6 @@ function onWheel(e: WheelEvent) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
useTabsDrag(props, emit);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
import type { Sortable } from '@vben-core/composables';
|
||||
import type { EmitType } from '@vben-core/typings';
|
||||
|
||||
import type { TabsProps } from './types';
|
||||
|
||||
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
|
||||
import { useIsMobile, useSortable } from '@vben-core/composables';
|
||||
|
||||
// 可能会找到拖拽的子元素,这里需要确保拖拽的dom时tab元素
|
||||
function findParentElement(element: HTMLElement) {
|
||||
const parentCls = 'group';
|
||||
return element.classList.contains(parentCls)
|
||||
? element
|
||||
: element.closest(`.${parentCls}`);
|
||||
}
|
||||
|
||||
export function useTabsDrag(props: TabsProps, emit: EmitType) {
|
||||
const sortableInstance = ref<null | Sortable>(null);
|
||||
|
||||
async function initTabsSortable() {
|
||||
await nextTick();
|
||||
|
||||
const el = document.querySelectorAll(
|
||||
`.${props.contentClass}`,
|
||||
)?.[0] as HTMLElement;
|
||||
|
||||
if (!el) {
|
||||
console.warn('Element not found for sortable initialization');
|
||||
return;
|
||||
}
|
||||
|
||||
const resetElState = async () => {
|
||||
el.style.cursor = 'default';
|
||||
// el.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');
|
||||
return !draggable || !props.draggable;
|
||||
},
|
||||
onEnd(evt) {
|
||||
const { newIndex, oldIndex } = evt;
|
||||
// const fromElement = evt.item;
|
||||
const { srcElement } = (evt as any).originalEvent;
|
||||
|
||||
if (!srcElement) {
|
||||
resetElState();
|
||||
return;
|
||||
}
|
||||
|
||||
const srcParent = findParentElement(srcElement);
|
||||
|
||||
if (!srcParent) {
|
||||
resetElState();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!srcParent.classList.contains('draggable')) {
|
||||
resetElState();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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');
|
||||
// 不允许在固定的tab和非固定的tab之间互相拖拽
|
||||
return isCurrentAffix === isRelatedAffix;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onStart: () => {
|
||||
el.style.cursor = 'grabbing';
|
||||
el.querySelector('.draggable')?.classList.add('dragging');
|
||||
// el.classList.add('dragging');
|
||||
},
|
||||
});
|
||||
|
||||
sortableInstance.value = await initializeSortable();
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const { isMobile } = useIsMobile();
|
||||
|
||||
// 移动端下tab不需要拖拽
|
||||
if (isMobile.value) {
|
||||
return;
|
||||
}
|
||||
await nextTick();
|
||||
initTabsSortable();
|
||||
}
|
||||
|
||||
onMounted(init);
|
||||
|
||||
watch(
|
||||
() => props.styleType,
|
||||
() => {
|
||||
sortableInstance.value?.destroy();
|
||||
init();
|
||||
},
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
sortableInstance.value?.destroy();
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user