@opensig/opendesign
Version:
<p align="center"><img src="../docs/public/opendesign-logo-light.png"/></p> <h1 align="center">opendesign</h1> <p align="center">一个 Vue 3 组件库</p> <p align="center"><b>皮肤可定制,使用 TypeScript</b></p>
302 lines (301 loc) • 10.7 kB
JavaScript
;
const vue = require("vue");
const provide = require("./provide.js");
const icons = require("../_utils/icons.js");
const types = require("./types.js");
const useScreen = require("../hooks/use-screen.js");
const onResize = require("../directives/on-resize.js");
const helper = require("../_utils/helper.js");
const global = require("../_utils/global.js");
const _hoisted_1 = {
key: 0,
class: "o-tab-head-prefix"
};
const _hoisted_2 = { class: "o-tab-navs" };
const _hoisted_3 = {
key: 1,
class: "o-tab-head-suffix"
};
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
__name: "OTab",
props: types.tabProps,
emits: ["update:modelValue", "change", "delete", "add"],
setup(__props, { emit: __emit }) {
const props = __props;
const emits = __emit;
const { isPhonePad } = useScreen.useScreen();
const activeKey = vue.ref(props.modelValue);
const anchorStyle = vue.ref({});
const navWrapRef = vue.ref(null);
const navsRef = vue.ref(null);
const bodyRef = vue.ref(null);
const valueSet = [];
let activeNavEl = null;
const isScroll = vue.ref(false);
const prevDisabled = vue.ref(true);
const nextDisabled = vue.ref(true);
const showArrow = vue.computed(() => {
return !isPhonePad.value && isScroll.value;
});
const scrollActiveNavIntoView = () => {
var _a;
if (isScroll.value && activeNavEl && navWrapRef.value) {
const { offsetLeft } = activeNavEl;
const { scrollLeft, clientWidth } = navWrapRef.value;
const center = scrollLeft + clientWidth / 2;
if (offsetLeft > center || offsetLeft < center) {
(_a = navWrapRef.value) == null ? void 0 : _a.scrollTo({
left: offsetLeft - clientWidth / 2,
behavior: "smooth"
});
}
}
};
const onWrapScroll = helper.debounceRAF(() => {
if (navWrapRef.value) {
const { scrollLeft, scrollWidth, clientWidth } = navWrapRef.value;
prevDisabled.value = scrollLeft === 0;
nextDisabled.value = scrollLeft + 1 >= scrollWidth - clientWidth;
}
});
const updateNavScroll = () => {
if (navWrapRef.value && navsRef.value) {
const { clientWidth: wrapWidth } = navWrapRef.value;
const { clientWidth: width } = navsRef.value;
isScroll.value = wrapWidth < width;
if (isScroll.value) {
vue.nextTick(() => {
onWrapScroll();
scrollActiveNavIntoView();
});
}
}
};
vue.watch(
() => props.modelValue,
(v) => {
activeKey.value = v;
}
);
const updateAnchor = () => {
if (!activeNavEl) {
return;
}
const { clientWidth, offsetLeft } = activeNavEl;
anchorStyle.value = {
transform: `translate3d(${offsetLeft}px, 0px, 0px)`,
width: `${clientWidth}px`
};
};
vue.watch(() => isScroll.value, updateAnchor);
const updateValue = (value, navEl) => {
emits("update:modelValue", value);
activeNavEl = navEl;
if (activeKey.value !== value) {
emits("change", value, activeKey.value);
activeKey.value = value;
}
if (navEl) {
activeNavEl = navEl;
updateAnchor();
scrollActiveNavIntoView();
}
};
const isAdding = vue.ref(false);
const initValue = (value, navEl) => {
if (!valueSet.includes(value)) {
valueSet.push(value);
}
if (activeKey.value === void 0 || isAdding.value) {
updateValue(value, navEl);
isAdding.value = false;
}
if (activeKey.value === value && navEl) {
activeNavEl = navEl;
updateAnchor();
}
};
const onDeletePane = (value) => {
emits("delete", value);
const idx = valueSet.indexOf(value);
if (activeKey.value === value) {
activeKey.value = valueSet[idx > 0 ? idx - 1 : 0];
emits("change", activeKey.value, value);
}
valueSet.splice(idx, 1);
};
const onAddNav = (e) => {
emits("add", e);
if (!props.addInactive) {
isAdding.value = true;
}
};
vue.provide(provide.tabInjectKey, {
lazy: props.lazy,
navsRef,
bodyRef,
activeValue: activeKey,
updateValue,
onDeletePane,
initValue
});
const onHeadResize = helper.debounceRAF(() => {
updateAnchor();
updateNavScroll();
scrollActiveNavIntoView();
});
const navScroll = (to) => {
if (!navWrapRef.value) {
return;
}
const { clientWidth } = navWrapRef.value;
const i = to === "prev" ? -1 : to === "next" ? 1 : 0;
navWrapRef.value.scrollBy({ left: i * clientWidth, behavior: "smooth" });
};
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock(
"div",
{
class: vue.normalizeClass(["o-tab", [`o-tab-${props.variant}`, `o-tab-${props.size || vue.unref(global.defaultSize)}`]])
},
[
vue.createElementVNode(
"div",
{
class: vue.normalizeClass(["o-tab-head", [
{
"with-act": _ctx.$slots.suffix || _ctx.$slots.prefix,
"show-line": props.line
},
props.headerClass
]])
},
[
_ctx.$slots.prefix ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
vue.renderSlot(_ctx.$slots, "prefix")
])), [
[vue.unref(onResize.vOnResize), vue.unref(onHeadResize)]
]) : vue.createCommentVNode("v-if", true),
vue.createElementVNode("div", _hoisted_2, [
vue.createElementVNode(
"div",
{
class: vue.normalizeClass([{ "o-tab-navs-scrollable": isScroll.value }, "o-tab-navs-container"])
},
[
showArrow.value ? (vue.openBlock(), vue.createElementBlock(
"div",
{
key: 0,
class: vue.normalizeClass(["o-tab-nav-btn prev", { "o-tab-nav-btn-disabled": prevDisabled.value }]),
onClick: _cache[0] || (_cache[0] = ($event) => navScroll("prev"))
},
[
vue.createVNode(vue.unref(icons.IconChevronLeft))
],
2
/* CLASS */
)) : vue.createCommentVNode("v-if", true),
vue.createElementVNode(
"div",
{
ref_key: "navWrapRef",
ref: navWrapRef,
class: "o-tab-navs-wrap o-hide-scrollbar",
onScrollPassive: _cache[1] || (_cache[1] = //@ts-ignore
(...args) => vue.unref(onWrapScroll) && vue.unref(onWrapScroll)(...args))
},
[
vue.withDirectives(vue.createElementVNode(
"div",
{
class: "o-tab-nav-list",
ref_key: "navsRef",
ref: navsRef
},
null,
512
/* NEED_PATCH */
), [
[vue.unref(onResize.vOnResize), vue.unref(onHeadResize)]
]),
props.variant === "text" ? (vue.openBlock(), vue.createElementBlock(
"div",
{
key: 0,
class: "o-tab-nav-anchor",
style: vue.normalizeStyle(anchorStyle.value)
},
[
vue.renderSlot(_ctx.$slots, "anchor", {}, () => [
_cache[3] || (_cache[3] = vue.createElementVNode(
"div",
{ class: "o-tab-nav-anchor-line" },
null,
-1
/* HOISTED */
))
])
],
4
/* STYLE */
)) : vue.createCommentVNode("v-if", true)
],
544
/* NEED_HYDRATION, NEED_PATCH */
),
showArrow.value ? (vue.openBlock(), vue.createElementBlock(
"div",
{
key: 1,
class: vue.normalizeClass(["o-tab-nav-btn next", { "o-tab-nav-btn-disabled": nextDisabled.value }]),
onClick: _cache[2] || (_cache[2] = ($event) => navScroll("next"))
},
[
vue.createVNode(vue.unref(icons.IconChevronRight))
],
2
/* CLASS */
)) : vue.createCommentVNode("v-if", true)
],
2
/* CLASS */
),
props.addable ? (vue.openBlock(), vue.createElementBlock("div", {
key: 0,
class: "o-tab-nav-add",
onClick: onAddNav
}, [
vue.createVNode(vue.unref(icons.IconAdd))
])) : vue.createCommentVNode("v-if", true)
]),
_ctx.$slots.suffix ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", _hoisted_3, [
vue.renderSlot(_ctx.$slots, "suffix")
])), [
[vue.unref(onResize.vOnResize), vue.unref(onHeadResize)]
]) : vue.createCommentVNode("v-if", true)
],
2
/* CLASS */
),
vue.createElementVNode(
"div",
{
ref_key: "bodyRef",
ref: bodyRef,
class: "o-tab-body"
},
[
vue.renderSlot(_ctx.$slots, "default")
],
512
/* NEED_PATCH */
)
],
2
/* CLASS */
);
};
}
});
module.exports = _sfc_main;