352 lines
20 KiB
JavaScript
352 lines
20 KiB
JavaScript
import { w as withInstall } from "../badge/index2.js";
|
|
import { defineComponent, useSlots, ref, reactive, computed, provide, shallowRef, watch, nextTick, onMounted, openBlock, createElementBlock, normalizeClass, createElementVNode, normalizeStyle, unref, createCommentVNode, Fragment, renderList, withModifiers, createBlock, createVNode, renderSlot, h, createTextVNode } from "vue";
|
|
import { _ as _sfc_main$2E } from "../checkbox/index2.js";
|
|
import { T as TabInjectKey, _ as _sfc_main$1 } from "../tabItem/index2.js";
|
|
import { R as RenderFunction } from "../dropdown/index2.js";
|
|
import { a as useResizeObserver } from "../_chunks/@vueuse/index.js";
|
|
var index = /* @__PURE__ */ (() => '.layui-tab{display:flex;margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-head>.layui-tab-title{overflow:hidden}.layui-tab.is-left{flex-direction:row}.layui-tab.is-right{flex-direction:row-reverse;justify-content:space-between}.layui-tab.is-top{flex-direction:column}.layui-tab.is-bottom{flex-direction:column-reverse}.layui-tab-head{display:inline-block;overflow:hidden}.layui-tab-card .layui-tab-head{background-color:var(--global-neutral-color-1)}.layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li{display:inline-block;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s;position:relative;line-height:40px;min-width:65px;padding:0 15px;text-align:center;cursor:pointer;user-select:none}.layui-tab-title li a{display:block;padding:0 15px;margin:0 -15px}.layui-tab-head.is-top,.layui-tab-head.is-bottom,.layui-tab-title.is-top,.layui-tab-title.is-bottom{width:100%;position:relative}.layui-tab-title.is-right,.layui-tab-title.is-left{height:100%;min-width:60px;border-bottom-width:0px;border-bottom-style:none}.layui-tab-title.is-left li{display:list-item;margin-right:-1px}.layui-tab-title.is-right li{display:list-item;margin-left:-1px}.layui-tab-title.is-top li,.layui-tab-title.is-bottom li{border-bottom:1px solid #eeeeee}.layui-tab-title.is-right{border-left:1px solid var(--global-neutral-color-3)}.layui-tab-title.is-left{border-right:1px solid var(--global-neutral-color-3)}.layui-tab-title .layui-this{color:#000;background-color:#fff}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:"";width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-title.is-left .layui-this:after{border:1px solid var(--global-neutral-color-3);border-right-color:#fff}.layui-tab-title.is-right .layui-this:after{border:1px solid var(--global-neutral-color-3);border-left-color:#fff}.layui-tab-brief>.layui-tab-head{background-color:transparent}.layui-tab-brief>.layui-tab-head>.layui-tab-title .layui-this{color:var(--global-primary-color)}.layui-tab-brief>.layui-tab-head>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-head>.layui-tab-title .layui-this:after{border:none;border-radius:0}.layui-tab-brief>.layui-tab-head.is-right>.layui-tab-title{border-left:1px solid var(--global-neutral-color-3)}.layui-tab-brief>.layui-tab-head.is-left>.layui-tab-title{border-right:1px solid var(--global-neutral-color-3)}.layui-tab-brief[overflow]>.layui-tab-head>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-brief>.layui-tab-head.is-right>.layui-tab-title li,.layui-tab-brief>.layui-tab-head.is-left>.layui-tab-title li{margin-right:0}.layui-tab-brief>.layui-tab-head.is-top>.layui-tab-title li,.layui-tab-brief>.layui-tab-head.is-top>.layui-tab-title li{margin-top:0;margin-bottom:0}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px #0000001a}.layui-tab-card>.layui-tab-head>.layui-tab-title.is-top{margin-top:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-head>.layui-tab-title.is-right,.layui-tab-card>.layui-tab-head>.layui-tab-title.is-left{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-head>.layui-tab-title.is-bottom li{margin-top:-1px}.layui-tab-card>.layui-tab-head>.layui-tab-title .layui-this:after{border-radius:0}.layui-tab-card>.layui-tab-head>.layui-tab-title.is-bottom{border-top:1px solid var(--global-neutral-color-3);margin-bottom:-2px;margin-left:-1px}.layui-tab-card>.layui-tab-head>.layui-tab-title.is-left li,.layui-tab-card>.layui-tab-head>.layui-tab-title.is-right li{margin-top:-1px;margin-bottom:-1px}.layui-tab-card>.layui-tab-head>.layui-tab-title.is-top .layui-this:after{border:1px solid var(--global-neutral-color-3);border-bottom-color:#fff}.layui-tab-card>.layui-tab-head>.layui-tab-title.is-bottom .layui-this:after{border:1px solid var(--global-neutral-color-3);border-top-color:#fff}.layui-tab-card>.layui-tab-head>.layui-tab-title.is-left .layui-this:after{border:1px solid var(--global-neutral-color-3);border-right-color:#fff}.layui-tab-card>.layui-tab-head>.layui-tab-title.is-right .layui-this:after{border:1px solid var(--global-neutral-color-3);border-left-color:#fff}.layui-tab-card>.layui-tab-head .layui-tab-bar{width:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:var(--global-checked-color)}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar.prev{left:0;right:auto;border-right:1px solid var(--global-neutral-color-3)!important;border-left:none!important}.layui-tab-bar .layui-icon{top:3px;font-size:13.6px;display:inline-block;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:var(--global-neutral-color-3);border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:var(--global-neutral-color-8);transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#ff5722;color:#fff}.layui-tab-content{padding:15px 0;flex:1}.layui-tab.is-right>.layui-tab-content,.layui-tab.is-left>.layui-tab-content{height:100%;padding:0 10px;display:inline-block;vertical-align:top}.layui-tab-active-bar{position:absolute;bottom:0px;left:0;height:1.5px;background-color:var(--global-checked-color);z-index:2;list-style:none;box-sizing:border-box;pointer-events:none}.is-top .layui-tab-active-bar{bottom:-1px;height:1.5px}.is-left .layui-tab-active-bar{left:auto;right:-1px;top:0;bottom:auto;width:1.5px}.is-right .layui-tab-active-bar{left:-1px;right:auto;top:0;bottom:auto;width:1.5px}\n')();
|
|
const _hoisted_1 = ["onClick"];
|
|
const _hoisted_2 = ["onClick"];
|
|
const _hoisted_3 = { class: "layui-tab-content" };
|
|
const __default__ = {
|
|
name: "LayTab"
|
|
};
|
|
const _sfc_main = defineComponent({
|
|
...__default__,
|
|
props: {
|
|
type: null,
|
|
modelValue: null,
|
|
allowClose: { type: Boolean },
|
|
tabPosition: { default: "top" },
|
|
beforeClose: null,
|
|
beforeLeave: null,
|
|
activeBarTransition: { type: Boolean }
|
|
},
|
|
emits: ["update:modelValue", "change", "close"],
|
|
setup(__props, { emit }) {
|
|
const props = __props;
|
|
const slot = useSlots();
|
|
const childrens = ref([]);
|
|
const tabMap = reactive(/* @__PURE__ */ new Map());
|
|
const setItemInstanceBySlot = function(nodes) {
|
|
nodes == null ? void 0 : nodes.map((item) => {
|
|
let component2 = item.type;
|
|
if (item.type.toString() == "Symbol(Fragment)") {
|
|
setItemInstanceBySlot(item.children);
|
|
} else {
|
|
if (component2.name == _sfc_main$1.name) {
|
|
childrens.value.push(item);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
const active = computed({
|
|
get() {
|
|
return props.modelValue;
|
|
},
|
|
set(val) {
|
|
emit("update:modelValue", val);
|
|
}
|
|
});
|
|
const tabItems = computed(() => {
|
|
const tabData = [];
|
|
childrens.value.forEach((item) => {
|
|
var _a;
|
|
const tab = tabMap.get((_a = item.props) == null ? void 0 : _a.id);
|
|
if (tab)
|
|
tabData.push(tab);
|
|
});
|
|
return tabData;
|
|
});
|
|
const addItem = (id, data) => {
|
|
tabMap.set(id, data);
|
|
};
|
|
const removeItem = (id) => {
|
|
tabMap.delete(id);
|
|
};
|
|
provide(TabInjectKey, reactive({
|
|
active,
|
|
addItem,
|
|
removeItem
|
|
}));
|
|
const change = function(id) {
|
|
if (props.beforeLeave && props.beforeLeave(id) === false) {
|
|
return;
|
|
}
|
|
emit("update:modelValue", id);
|
|
emit("change", id);
|
|
};
|
|
const close = function(index2, id) {
|
|
if (props.beforeClose && props.beforeClose(id) === false) {
|
|
return;
|
|
}
|
|
childrens.value.splice(index2, 1);
|
|
if (active.value === id) {
|
|
const nextChildren = childrens.value[index2 === childrens.value.length ? 0 : index2];
|
|
change(nextChildren && nextChildren.props ? nextChildren.props.id : "");
|
|
}
|
|
emit("close", id);
|
|
};
|
|
const activeBarRef = shallowRef(void 0);
|
|
const activeEl = shallowRef(void 0);
|
|
const tabBarStyle = ref();
|
|
const getBarStyle = () => {
|
|
let offset = 0;
|
|
let tabSize = 0;
|
|
const sizeName2 = props.tabPosition === "top" || props.tabPosition === "bottom" ? "width" : "height";
|
|
const axis = sizeName2 === "width" ? "X" : "Y";
|
|
const position = axis === "X" ? "left" : "top";
|
|
const el = activeEl.value;
|
|
const activeElParentElement = navRef.value;
|
|
if (!el || !activeElParentElement)
|
|
return;
|
|
const rect = el == null ? void 0 : el.getBoundingClientRect();
|
|
const parentRect = activeElParentElement == null ? void 0 : activeElParentElement.getBoundingClientRect();
|
|
offset = rect[position] - parentRect[position];
|
|
tabSize = el.getBoundingClientRect()[sizeName2];
|
|
return {
|
|
[sizeName2]: `${tabSize}px`,
|
|
transform: `translate${axis}(${offset}px)`,
|
|
transition: props.activeBarTransition ? `transform .3s` : ""
|
|
};
|
|
};
|
|
const navRef = shallowRef(void 0);
|
|
const scrollable = ref(false);
|
|
const navOffset = ref(0);
|
|
const navStyle = computed(() => {
|
|
var _a, _b;
|
|
const axis = props.tabPosition === "top" || props.tabPosition === "bottom" ? "X" : "Y";
|
|
const position = axis === "X" ? "left" : "top";
|
|
const scrollPrevSize = (_b = (_a = scrollPrevRef.value) == null ? void 0 : _a[`offset${sizeName.value}`]) != null ? _b : 0;
|
|
return {
|
|
transform: `translate${axis}(-${navOffset.value}px)`,
|
|
[position]: scrollable.value ? `${scrollPrevSize}px` : 0
|
|
};
|
|
});
|
|
const sizeName = computed(() => {
|
|
return props.tabPosition === "top" || props.tabPosition === "bottom" ? "Width" : "Height";
|
|
});
|
|
const getNavSize = function() {
|
|
var _a;
|
|
let size = 0;
|
|
const nodeList = (_a = navRef.value) == null ? void 0 : _a.querySelectorAll("li");
|
|
nodeList == null ? void 0 : nodeList.forEach((item) => {
|
|
size += item[`offset${sizeName.value}`];
|
|
});
|
|
return size;
|
|
};
|
|
const scrollPrev = function() {
|
|
if (!navRef.value)
|
|
return;
|
|
const containerSize = navRef.value[`offset${sizeName.value}`];
|
|
const currentOffset = navOffset.value;
|
|
if (!currentOffset)
|
|
return;
|
|
let newOffset = currentOffset > containerSize ? currentOffset - containerSize : 0;
|
|
navOffset.value = newOffset;
|
|
};
|
|
const scrollNextRef = shallowRef(void 0);
|
|
const scrollPrevRef = shallowRef(void 0);
|
|
const scrollNext = function() {
|
|
var _a, _b, _c, _d;
|
|
if (!navRef.value)
|
|
return;
|
|
const navSize = getNavSize();
|
|
const containerSize = navRef.value[`offset${sizeName.value}`];
|
|
const currentOffset = navOffset.value;
|
|
const scrollNextSize = (_b = (_a = scrollNextRef.value) == null ? void 0 : _a[`offset${sizeName.value}`]) != null ? _b : 0;
|
|
const scrollPrevSize = (_d = (_c = scrollPrevRef.value) == null ? void 0 : _c[`offset${sizeName.value}`]) != null ? _d : 0;
|
|
if (navSize - currentOffset <= containerSize)
|
|
return;
|
|
let newOffset = navSize - currentOffset > containerSize * 2 ? currentOffset + containerSize : navSize - containerSize + scrollNextSize + scrollPrevSize;
|
|
navOffset.value = newOffset;
|
|
};
|
|
const headRef = shallowRef(void 0);
|
|
const scrollToActiveTab = function() {
|
|
var _a, _b, _c, _d;
|
|
if (!scrollable.value)
|
|
return;
|
|
const activeTab = activeEl.value;
|
|
const container = headRef.value;
|
|
if (!activeTab || !container)
|
|
return;
|
|
const activeTabRect = activeTab == null ? void 0 : activeTab.getBoundingClientRect();
|
|
const containerRect = container == null ? void 0 : container.getBoundingClientRect();
|
|
const isHorizontal = ["top", "bottom"].includes(props.tabPosition);
|
|
const currentOffset = navOffset.value;
|
|
let newOffset = currentOffset;
|
|
const navSize = getNavSize();
|
|
const scrollNextSize = (_b = (_a = scrollNextRef.value) == null ? void 0 : _a[`offset${sizeName.value}`]) != null ? _b : 0;
|
|
const scrollPrevSize = (_d = (_c = scrollPrevRef.value) == null ? void 0 : _c[`offset${sizeName.value}`]) != null ? _d : 0;
|
|
const maxOffset = isHorizontal ? navSize - containerRect.width + scrollNextSize + scrollPrevSize : navSize - containerRect.height + scrollNextSize + scrollPrevSize;
|
|
if (isHorizontal) {
|
|
if (activeTabRect.left < containerRect.left) {
|
|
newOffset = currentOffset - (containerRect.left - activeTabRect.left);
|
|
newOffset -= scrollPrevSize;
|
|
}
|
|
if (activeTabRect.right > containerRect.right) {
|
|
newOffset = currentOffset + activeTabRect.right - containerRect.right;
|
|
newOffset += scrollNextSize;
|
|
}
|
|
} else {
|
|
if (activeTabRect.top < containerRect.top) {
|
|
newOffset = currentOffset - (containerRect.top - activeTabRect.top);
|
|
}
|
|
if (activeTabRect.bottom > containerRect.bottom) {
|
|
newOffset = currentOffset + (activeTabRect.bottom - containerRect.bottom);
|
|
}
|
|
}
|
|
newOffset = Math.max(newOffset, 0);
|
|
navOffset.value = Math.min(newOffset, maxOffset);
|
|
};
|
|
const update = () => {
|
|
var _a, _b, _c, _d, _e;
|
|
if (!navRef.value)
|
|
return;
|
|
activeEl.value = (_a = navRef.value) == null ? void 0 : _a.querySelector(".layui-this");
|
|
tabBarStyle.value = getBarStyle();
|
|
if (props.tabPosition !== "top" && props.tabPosition !== "bottom")
|
|
return;
|
|
const navSize = getNavSize();
|
|
const containerSize = navRef.value[`offset${sizeName.value}`];
|
|
const currentOffset = navOffset.value;
|
|
const scrollNextSize = (_c = (_b = scrollNextRef.value) == null ? void 0 : _b[`offset${sizeName.value}`]) != null ? _c : 0;
|
|
const scrollPrevSize = (_e = (_d = scrollPrevRef.value) == null ? void 0 : _d[`offset${sizeName.value}`]) != null ? _e : 0;
|
|
if (containerSize < navSize) {
|
|
const currentOffset2 = navOffset.value;
|
|
scrollable.value = true;
|
|
if (navSize - currentOffset2 < containerSize) {
|
|
navOffset.value = navSize - containerSize + scrollNextSize + scrollPrevSize;
|
|
}
|
|
scrollToActiveTab();
|
|
} else {
|
|
scrollable.value = false;
|
|
if (currentOffset > 0) {
|
|
navOffset.value = 0;
|
|
}
|
|
}
|
|
};
|
|
const renderTabIcon = (attrs) => {
|
|
const tab = attrs.tabData;
|
|
if (typeof tab.icon === "function") {
|
|
return tab.icon();
|
|
} else if (typeof tab.icon === "string") {
|
|
return h(_sfc_main$2E, {
|
|
type: tab.icon,
|
|
style: "margin-right: 8px;"
|
|
});
|
|
}
|
|
};
|
|
const renderTabTitle = (attrs) => {
|
|
var _a, _b;
|
|
const tab = attrs.tabData;
|
|
if ((_a = tab.slots) == null ? void 0 : _a.title) {
|
|
return h(Fragment, ((_b = tab.slots) == null ? void 0 : _b.title) && tab.slots.title());
|
|
}
|
|
if (typeof tab.title === "function") {
|
|
return tab.title();
|
|
} else if (typeof tab.title === "string") {
|
|
return createTextVNode(tab.title);
|
|
}
|
|
};
|
|
useResizeObserver(navRef, update);
|
|
watch(tabMap, function() {
|
|
childrens.value = [];
|
|
setItemInstanceBySlot(slot.default && slot.default());
|
|
}, { immediate: true });
|
|
watch(() => [
|
|
props.modelValue,
|
|
props.tabPosition,
|
|
props.type,
|
|
childrens.value.length
|
|
], async () => {
|
|
await nextTick();
|
|
update();
|
|
});
|
|
onMounted(() => {
|
|
update();
|
|
scrollToActiveTab();
|
|
});
|
|
provide("active", active);
|
|
return (_ctx, _cache) => {
|
|
return openBlock(), createElementBlock("div", {
|
|
class: normalizeClass(["layui-tab", [
|
|
__props.type ? "layui-tab-" + __props.type : "",
|
|
props.tabPosition ? `is-${__props.tabPosition}` : ""
|
|
]])
|
|
}, [
|
|
createElementVNode("div", {
|
|
ref_key: "headRef",
|
|
ref: headRef,
|
|
class: normalizeClass(["layui-tab-head", props.tabPosition ? `is-${__props.tabPosition}` : ""])
|
|
}, [
|
|
createElementVNode("ul", {
|
|
ref_key: "navRef",
|
|
ref: navRef,
|
|
class: normalizeClass([
|
|
"layui-tab-title",
|
|
props.tabPosition ? `is-${__props.tabPosition}` : ""
|
|
]),
|
|
style: normalizeStyle(unref(navStyle))
|
|
}, [
|
|
__props.type === "brief" ? (openBlock(), createElementBlock("div", {
|
|
key: 0,
|
|
ref_key: "activeBarRef",
|
|
ref: activeBarRef,
|
|
class: "layui-tab-active-bar",
|
|
style: normalizeStyle(tabBarStyle.value)
|
|
}, null, 4)) : createCommentVNode("", true),
|
|
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(tabItems), (child, index2) => {
|
|
return openBlock(), createElementBlock("li", {
|
|
key: child.id,
|
|
class: normalizeClass([child.id === unref(active) ? "layui-this" : ""]),
|
|
onClick: withModifiers(($event) => change(child.id), ["stop"])
|
|
}, [
|
|
createElementVNode("span", null, [
|
|
child["icon"] ? (openBlock(), createBlock(unref(RenderFunction), {
|
|
key: 0,
|
|
renderFunc: renderTabIcon,
|
|
tabData: child
|
|
}, null, 8, ["tabData"])) : createCommentVNode("", true),
|
|
createVNode(unref(RenderFunction), {
|
|
renderFunc: renderTabTitle,
|
|
tabData: child
|
|
}, null, 8, ["tabData"])
|
|
]),
|
|
__props.allowClose && child.closable != false ? (openBlock(), createElementBlock("i", {
|
|
key: 0,
|
|
class: "layui-icon layui-icon-close layui-unselect layui-tab-close",
|
|
onClick: withModifiers(($event) => close(index2, child.id), ["stop"])
|
|
}, null, 8, _hoisted_2)) : createCommentVNode("", true)
|
|
], 10, _hoisted_1);
|
|
}), 128))
|
|
], 6),
|
|
scrollable.value ? (openBlock(), createElementBlock("span", {
|
|
key: 0,
|
|
ref_key: "scrollPrevRef",
|
|
ref: scrollPrevRef,
|
|
class: "layui-unselect layui-tab-bar prev",
|
|
onClick: scrollPrev
|
|
}, [
|
|
createVNode(unref(_sfc_main$2E), { type: "layui-icon-left" })
|
|
], 512)) : createCommentVNode("", true),
|
|
scrollable.value ? (openBlock(), createElementBlock("span", {
|
|
key: 1,
|
|
ref_key: "scrollNextRef",
|
|
ref: scrollNextRef,
|
|
class: "layui-unselect layui-tab-bar",
|
|
onClick: scrollNext
|
|
}, [
|
|
createVNode(unref(_sfc_main$2E), { type: "layui-icon-right" })
|
|
], 512)) : createCommentVNode("", true)
|
|
], 2),
|
|
createElementVNode("div", _hoisted_3, [
|
|
renderSlot(_ctx.$slots, "default")
|
|
])
|
|
], 2);
|
|
};
|
|
}
|
|
});
|
|
const component = withInstall(_sfc_main);
|
|
export { component as default };
|