| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- require("../../../_virtual/_rolldown/runtime.js");
- const require_aria = require("../../../constants/aria.js");
- const require_event = require("../../../utils/dom/event.js");
- const require_raf = require("../../../utils/raf.js");
- const require_error = require("../../../utils/error.js");
- const require_runtime$1 = require("../../../utils/vue/props/runtime.js");
- const require_typescript = require("../../../utils/typescript.js");
- const require_numbers = require("../../../utils/numbers.js");
- const require_index = require("../../../hooks/use-namespace/index.js");
- const require_index$1 = require("../../icon/index.js");
- const require_use_wheel = require("../../virtual-list/src/hooks/use-wheel.js");
- const require_constants = require("./constants.js");
- const require_tab_bar = require("./tab-bar2.js");
- const require_use_tab_nav_touch = require("./composables/use-tab-nav-touch.js");
- let _vueuse_core = require("@vueuse/core");
- let lodash_unified = require("lodash-unified");
- let _element_plus_icons_vue = require("@element-plus/icons-vue");
- let vue = require("vue");
- //#region ../../packages/components/tabs/src/tab-nav.tsx
- const tabNavProps = require_runtime$1.buildProps({
- panes: {
- type: require_runtime$1.definePropType(Array),
- default: () => require_typescript.mutable([])
- },
- currentName: {
- type: [String, Number],
- default: ""
- },
- editable: Boolean,
- type: {
- type: String,
- values: [
- "card",
- "border-card",
- ""
- ],
- default: ""
- },
- stretch: Boolean,
- /**
- * @description tab-nav tabindex
- */
- tabindex: {
- type: [String, Number],
- default: void 0
- }
- });
- const tabNavEmits = {
- tabClick: (tab, tabName, ev) => ev instanceof Event,
- tabRemove: (tab, ev) => ev instanceof Event
- };
- const COMPONENT_NAME = "ElTabNav";
- const TabNav = /* @__PURE__ */ (0, vue.defineComponent)({
- name: COMPONENT_NAME,
- props: tabNavProps,
- emits: tabNavEmits,
- setup(props, { expose, emit }) {
- const rootTabs = (0, vue.inject)(require_constants.tabsRootContextKey);
- if (!rootTabs) require_error.throwError(COMPONENT_NAME, `<el-tabs><tab-nav /></el-tabs>`);
- const ns = require_index.useNamespace("tabs");
- const visibility = (0, _vueuse_core.useDocumentVisibility)();
- const focused = (0, _vueuse_core.useWindowFocus)();
- const navScroll$ = (0, vue.ref)();
- const nav$ = (0, vue.ref)();
- const el$ = (0, vue.ref)();
- const tabRefsMap = (0, vue.ref)({});
- const tabBarRef = (0, vue.ref)();
- const scrollable = (0, vue.ref)(false);
- const navOffset = (0, vue.ref)(0);
- const isFocus = (0, vue.ref)(false);
- const focusable = (0, vue.ref)(true);
- const isWheelScrolling = (0, vue.ref)(false);
- const tracker = (0, vue.shallowRef)();
- const isHorizontal = (0, vue.computed)(() => ["top", "bottom"].includes(rootTabs.props.tabPosition));
- const sizeName = (0, vue.computed)(() => isHorizontal.value ? "width" : "height");
- const navStyle = (0, vue.computed)(() => {
- const dir = sizeName.value === "width" ? "X" : "Y";
- return {
- transition: isWheelScrolling.value || isTouchScrolling.value ? "none" : void 0,
- transform: `translate${dir}(-${navOffset.value}px)`
- };
- });
- const { width: navContainerWidth, height: navContainerHeight } = (0, _vueuse_core.useElementSize)(navScroll$);
- const { width: navWidth, height: navHeight } = (0, _vueuse_core.useElementSize)(nav$, {
- width: 0,
- height: 0
- }, { box: "border-box" });
- const navContainerSize = (0, vue.computed)(() => isHorizontal.value ? navContainerWidth.value : navContainerHeight.value);
- const navSize = (0, vue.computed)(() => isHorizontal.value ? navWidth.value : navHeight.value);
- const { onWheel } = require_use_wheel.default({
- atStartEdge: (0, vue.computed)(() => navOffset.value <= 0),
- atEndEdge: (0, vue.computed)(() => navSize.value - navOffset.value <= navContainerSize.value),
- layout: (0, vue.computed)(() => isHorizontal.value ? "horizontal" : "vertical")
- }, (offset) => {
- navOffset.value = (0, lodash_unified.clamp)(navOffset.value + offset, 0, navSize.value - navContainerSize.value);
- });
- const handleWheel = (event) => {
- isWheelScrolling.value = true;
- onWheel(event);
- require_raf.rAF(() => {
- isWheelScrolling.value = false;
- });
- };
- const { isTouchScrolling, handleTouchStart, handleTouchMove, handleTouchEnd } = require_use_tab_nav_touch.useTabNavTouch({
- scrollable,
- navOffset,
- navSize,
- navContainerSize,
- isHorizontal
- });
- const scrollPrev = () => {
- if (!navScroll$.value) return;
- const containerSize = navScroll$.value.getBoundingClientRect()[sizeName.value];
- const currentOffset = navOffset.value;
- if (!currentOffset) return;
- navOffset.value = currentOffset > containerSize ? currentOffset - containerSize : 0;
- };
- const scrollNext = () => {
- if (!navScroll$.value || !nav$.value) return;
- const navSize = nav$.value.getBoundingClientRect()[sizeName.value];
- const containerSize = navScroll$.value.getBoundingClientRect()[sizeName.value];
- const currentOffset = navOffset.value;
- if (!require_numbers.isGreaterThan(navSize - currentOffset, containerSize)) return;
- navOffset.value = navSize - currentOffset > containerSize * 2 ? currentOffset + containerSize : navSize - containerSize;
- };
- const scrollToActiveTab = async () => {
- const nav = nav$.value;
- if (!scrollable.value || !el$.value || !navScroll$.value || !nav) return;
- await (0, vue.nextTick)();
- const activeTab = tabRefsMap.value[props.currentName];
- if (!activeTab) return;
- const navScroll = navScroll$.value;
- const activeTabBounding = activeTab.getBoundingClientRect();
- const navScrollBounding = navScroll.getBoundingClientRect();
- const navScrollLeft = navScrollBounding.left + 1;
- const navScrollRight = navScrollBounding.right - 1;
- const navBounding = nav.getBoundingClientRect();
- const maxOffset = isHorizontal.value ? navBounding.width - navScrollBounding.width : navBounding.height - navScrollBounding.height;
- const currentOffset = navOffset.value;
- let newOffset = currentOffset;
- if (isHorizontal.value) {
- if (activeTabBounding.left < navScrollLeft) newOffset = currentOffset - (navScrollLeft - activeTabBounding.left);
- if (activeTabBounding.right > navScrollRight) newOffset = currentOffset + activeTabBounding.right - navScrollRight;
- } else {
- if (activeTabBounding.top < navScrollBounding.top) newOffset = currentOffset - (navScrollBounding.top - activeTabBounding.top);
- if (activeTabBounding.bottom > navScrollBounding.bottom) newOffset = currentOffset + (activeTabBounding.bottom - navScrollBounding.bottom);
- }
- newOffset = Math.max(newOffset, 0);
- navOffset.value = Math.min(newOffset, maxOffset);
- };
- const update = () => {
- if (!nav$.value || !navScroll$.value) return;
- props.stretch && tabBarRef.value?.update();
- const navSize = nav$.value.getBoundingClientRect()[sizeName.value];
- const containerSize = navScroll$.value.getBoundingClientRect()[sizeName.value];
- const currentOffset = navOffset.value;
- if (containerSize < navSize) {
- scrollable.value = scrollable.value || {};
- scrollable.value.prev = currentOffset;
- scrollable.value.next = require_numbers.isGreaterThan(navSize, currentOffset + containerSize);
- if (require_numbers.isGreaterThan(containerSize, navSize - currentOffset)) navOffset.value = navSize - containerSize;
- } else {
- scrollable.value = false;
- if (currentOffset > 0) navOffset.value = 0;
- }
- };
- const changeTab = (event) => {
- const code = require_event.getEventCode(event);
- let step = 0;
- switch (code) {
- case require_aria.EVENT_CODE.left:
- case require_aria.EVENT_CODE.up:
- step = -1;
- break;
- case require_aria.EVENT_CODE.right:
- case require_aria.EVENT_CODE.down:
- step = 1;
- break;
- default: return;
- }
- const tabList = Array.from(event.currentTarget.querySelectorAll("[role=tab]:not(.is-disabled)"));
- let nextIndex = tabList.indexOf(event.target) + step;
- if (nextIndex < 0) nextIndex = tabList.length - 1;
- else if (nextIndex >= tabList.length) nextIndex = 0;
- tabList[nextIndex].focus({ preventScroll: true });
- tabList[nextIndex].click();
- setFocus();
- };
- const setFocus = () => {
- if (focusable.value) isFocus.value = true;
- };
- const removeFocus = () => isFocus.value = false;
- const setRefs = (el, key) => {
- tabRefsMap.value[key] = el;
- };
- const focusActiveTab = async () => {
- await (0, vue.nextTick)();
- tabRefsMap.value[props.currentName]?.focus({ preventScroll: true });
- };
- (0, vue.watch)(visibility, (visibility) => {
- if (visibility === "hidden") focusable.value = false;
- else if (visibility === "visible") setTimeout(() => focusable.value = true, 50);
- });
- (0, vue.watch)(focused, (focused) => {
- if (focused) setTimeout(() => focusable.value = true, 50);
- else focusable.value = false;
- });
- (0, _vueuse_core.useResizeObserver)(el$, () => {
- require_raf.rAF(update);
- });
- (0, vue.onMounted)(() => setTimeout(() => scrollToActiveTab(), 0));
- (0, vue.onUpdated)(() => update());
- expose({
- scrollToActiveTab,
- removeFocus,
- focusActiveTab,
- tabListRef: nav$,
- tabBarRef,
- scheduleRender: () => (0, vue.triggerRef)(tracker)
- });
- return () => {
- const scrollBtn = scrollable.value ? [(0, vue.createVNode)("span", {
- "class": [ns.e("nav-prev"), ns.is("disabled", !scrollable.value.prev)],
- "onClick": scrollPrev
- }, [(0, vue.createVNode)(require_index$1.ElIcon, null, { default: () => [(0, vue.createVNode)(_element_plus_icons_vue.ArrowLeft, null, null)] })]), (0, vue.createVNode)("span", {
- "class": [ns.e("nav-next"), ns.is("disabled", !scrollable.value.next)],
- "onClick": scrollNext
- }, [(0, vue.createVNode)(require_index$1.ElIcon, null, { default: () => [(0, vue.createVNode)(_element_plus_icons_vue.ArrowRight, null, null)] })])] : null;
- const tabs = props.panes.map((pane, index) => {
- const uid = pane.uid;
- const disabled = pane.props.disabled;
- const tabName = pane.props.name ?? pane.index ?? `${index}`;
- const closable = !disabled && (pane.isClosable || pane.props.closable !== false && props.editable);
- pane.index = `${index}`;
- const btnClose = closable ? (0, vue.createVNode)(require_index$1.ElIcon, {
- "class": "is-icon-close",
- "onClick": (ev) => emit("tabRemove", pane, ev)
- }, { default: () => [(0, vue.createVNode)(_element_plus_icons_vue.Close, null, null)] }) : null;
- const tabLabelContent = pane.slots.label?.() || pane.props.label;
- const tabindex = !disabled && pane.active ? props.tabindex ?? rootTabs.props.tabindex : -1;
- return (0, vue.createVNode)("div", {
- "ref": (el) => setRefs(el, tabName),
- "class": [
- ns.e("item"),
- ns.is(rootTabs.props.tabPosition),
- ns.is("active", pane.active),
- ns.is("disabled", disabled),
- ns.is("closable", closable),
- ns.is("focus", isFocus.value)
- ],
- "id": `tab-${tabName}`,
- "key": `tab-${uid}`,
- "aria-controls": `pane-${tabName}`,
- "role": "tab",
- "aria-selected": pane.active,
- "tabindex": tabindex,
- "onFocus": () => setFocus(),
- "onBlur": () => removeFocus(),
- "onClick": (ev) => {
- removeFocus();
- emit("tabClick", pane, tabName, ev);
- },
- "onKeydown": (ev) => {
- const code = require_event.getEventCode(ev);
- if (closable && (code === require_aria.EVENT_CODE.delete || code === require_aria.EVENT_CODE.backspace)) emit("tabRemove", pane, ev);
- }
- }, [...[tabLabelContent, btnClose]]);
- });
- tracker.value;
- return (0, vue.createVNode)("div", {
- "ref": el$,
- "class": [
- ns.e("nav-wrap"),
- ns.is("scrollable", !!scrollable.value),
- ns.is(rootTabs.props.tabPosition)
- ]
- }, [scrollBtn, (0, vue.createVNode)("div", {
- "class": ns.e("nav-scroll"),
- "ref": navScroll$
- }, [props.panes.length > 0 ? (0, vue.createVNode)("div", {
- "class": [
- ns.e("nav"),
- ns.is(rootTabs.props.tabPosition),
- ns.is("stretch", props.stretch && ["top", "bottom"].includes(rootTabs.props.tabPosition))
- ],
- "ref": nav$,
- "style": navStyle.value,
- "role": "tablist",
- "onKeydown": changeTab,
- "onWheel": handleWheel,
- "onTouchstart": handleTouchStart,
- "onTouchmove": handleTouchMove,
- "onTouchend": handleTouchEnd,
- "onTouchcancel": handleTouchEnd
- }, [...[!props.type ? (0, vue.createVNode)(require_tab_bar.default, {
- "ref": tabBarRef,
- "tabs": [...props.panes],
- "tabRefs": tabRefsMap.value
- }, null) : null, tabs]]) : null])]);
- };
- }
- });
- //#endregion
- exports.default = TabNav;
- exports.tabNavEmits = tabNavEmits;
- exports.tabNavProps = tabNavProps;
- //# sourceMappingURL=tab-nav.js.map
|