You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1 line
22 KiB

11 months ago
{"version":3,"file":"tab-nav.mjs","sources":["../../../../../../packages/components/tabs/src/tab-nav.ts"],"sourcesContent":["import {\n h,\n defineComponent,\n ref,\n inject,\n computed,\n onUpdated,\n onMounted,\n watch,\n} from 'vue'\nimport { NOOP, capitalize } from '@vue/shared'\nimport {\n useResizeObserver,\n useDocumentVisibility,\n useWindowFocus,\n} from '@vueuse/core'\nimport { buildProps, definePropType, mutable } from '@element-plus/utils/props'\nimport { EVENT_CODE } from '@element-plus/utils/aria'\nimport { throwError } from '@element-plus/utils/error'\nimport { ElIcon } from '@element-plus/components/icon'\nimport { ArrowLeft, ArrowRight, Close } from '@element-plus/icons-vue'\nimport { tabsRootContextKey } from '@element-plus/tokens'\nimport TabBar from './tab-bar.vue'\nimport type { ExtractPropTypes, CSSProperties } from 'vue'\nimport type { TabsPaneContext } from '@element-plus/tokens'\nexport interface Scrollable {\n next?: boolean\n prev?: number\n}\n\nexport const tabNavProps = buildProps({\n panes: {\n type: definePropType<TabsPaneContext[]>(Array),\n default: () => mutable([] as const),\n },\n currentName: {\n type: String,\n default: '',\n },\n editable: Boolean,\n onTabClick: {\n type: definePropType<\n (tab: TabsPaneContext, tabName: string, ev: Event) => void\n >(Function),\n default: NOOP,\n },\n onTabRemove: {\n type: definePropType<(tab: TabsPaneContext, ev: Event) => void>(Function),\n default: NOOP,\n },\n type: {\n type: String,\n values: ['card', 'border-card', ''],\n default: '',\n },\n stretch: Boolean,\n} as const)\n\nexport type TabNavProps = ExtractPropTypes<typeof tabNavProps>\n\nconst COMPONENT_NAME = 'ElTabNav'\nexport default defineComponent({\n name: COMPONENT_NAME,\n props: tabNavProps,\n\n setup(props, { expose }) {\n const visibility = useDocumentVisibility()\n const focused = useWindowFocus()\n\n const rootTabs = inject(tabsRootContextKey)\n if (!rootTabs)\n throwError(COMPONENT_NAME, `ElTabNav must be nested inside ElTabs`)\n\n const scrollable = ref<false | Scrollable>(false)\n const navOffset = ref(0)\n const isFocus = ref(false)\n const focusable = ref(true)\n\n const navScroll$ = ref<HTMLDivElement>()\n const nav$ = ref<HTMLDivElement>()\n const el$ = ref<HTMLDivElement>()\n\n const sizeName = computed(() =>\n ['top', 'bottom'].includes(rootTabs.props.tabPosition)\n ? 'width'\n : 'height'\n )\n const navStyle = computed<CSSProperties>(() => {\n const dir = sizeName.value === 'width' ? 'X' : 'Y'\n return {\n transform: `translate${dir}(-${navOffset.value}px)`,\n }\n })\n\n const scrollPrev = () => {\n if (!navScroll$.value) return\n\n const containerSize =\n navScroll$.value[`offset${capitalize(sizeName.value)}`]\n const currentOffset = navOffset.value\n\n if (!currentOffset) return\n\n const newOffset =\n currentOffset > containerSize ? currentOffset - containerSize : 0\n\n navOffset.value = newOffset\n }\n\n const scrollNext = () => {\n if (!navScroll$.value || !nav$.value) return\n\n const navSize = nav$.value[`offset${capitalize(sizeName.value)}`]\n const containerSize =\n navScroll$.value[`offset${capitalize(sizeName.value)}`]\n const currentOffset = navOffset.value\n\n if (navSize - currentOffset <= containerSize) return\n\n const newOffset =\n navSize - currentOffset > containerSize * 2\n ? currentOffset + containerSize\n : navSize - containerSize\n\n navOffset.value = newOffset\n }\n\n const scrollToActiveTab = () => {\n const nav = nav$.value\n if (!scrollable.value || !el$.value || !navScroll$.value || !nav) return\n\n const activeTab = el$.value.querySelector('.is-active')\n if (!activeTab) return\n\n const navScroll = navScroll$.value\n const isHorizontal = ['top', 'bottom'].includes(\n rootTabs.props.tabPosition\n )\n const activ