ranui
Version:
UI Component library based on `Web Component`
309 lines (308 loc) • 14.3 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { d as createDocumentFragment, a as addClassToElement } from "./plus-BQnIzzvi.js";
import { i as isDisabled, r as removeClassToElementChild } from "./index-9tJmVuyv.js";
const f7170ee498e0dd32cbdcb63fba8f75cc = '.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}.ran-tab ::slotted(r-tab){box-sizing:border-box;width:100%;height:100%;padding:10px;flex-shrink:0;overflow:auto;text-align:start}.ran-tab-header{position:relative;overflow:hidden;scroll-behavior:smooth}.ran-tab-header-nav{display:flex;flex-flow:row nowrap;justify-content:flex-start;align-items:center}.ran-tab-header-nav::-webkit-scrollbar{display:none}.ran-tab-header-nav-item{flex-shrink:0}.ran-tab-header-nav .active{color:var(--active-color, #1890ff)}.ran-tab-header-line{position:absolute;width:0;margin-top:-2px;height:2px;border-radius:2px;background:var(--line-color, #1890ff);transition:.2s}.ran-tab-content{overflow:hidden}.ran-tab-content-wrap{display:flex;width:100%;height:100%;transition:.2s}:host([type="line"]) .ran-tab-header-nav-item{border:solid 1px transparent}:host([type="line"]) .ran-tab-header-nav .active{color:var(--line-color, #1890ff);border:solid 1px transparent;border-color:var(--border-color, rgba(0, 0, 0, .2)) var(--border-color, rgba(0, 0, 0, .2)) transparent;border-radius:var(--border-radius, .25em) var(--border-radius, .25em) 0 0}:host([type="line"]) .ran-tab-header-line{transition:none;visibility:hidden}:host([type="line"]) .ran-tab-header-line:after,:host([type="line"]) .ran-tab-header-line:before{content:"";position:absolute;visibility:visible;width:9999px;height:1px;bottom:0;background:var(--border-color, rgba(0, 0, 0, .2))}:host([type="line"]) .ran-tab-header-line:after{left:100%}:host([type="line"]) .ran-tab-header-line:before{right:100%}:host([align="center"]) .ran-tab-header-nav{justify-content:center}:host([align="center"]) .ran-tab-header-line{left:50%}:host([align="end"]) .ran-tab-header-nav{justify-content:flex-end}';
function CustomElement() {
if (typeof window !== "undefined" && !customElements.get("r-tabs")) {
class Tabs extends HTMLElement {
constructor() {
super();
__publicField(this, "_container");
__publicField(this, "_header");
__publicField(this, "_nav");
__publicField(this, "_line");
__publicField(this, "_content");
__publicField(this, "_wrap");
__publicField(this, "_slot");
__publicField(this, "tabHeaderKeyMapIndex");
/**
* @description: 构建 tabPane 组件 key 值和 index 的映射,同时判断一个 tabs 下的 tabPane key 值不能重复
* @param {string} key
* @param {number} index
*/
__publicField(this, "initTabHeaderKeyMapIndex", (key, index2) => {
const value = this.tabHeaderKeyMapIndex[key];
if (value) {
throw new Error("tab 组件的 key 值存在重复,或者某个 tab 组件缺少 key 属性");
} else {
this.tabHeaderKeyMapIndex[key] = index2;
}
});
/**
* @description: 初始化 tabLine 的位置,主要是当 tabs 的 align 属性为 center 时需要处理
*/
__publicField(this, "initTabLineAlignCenter", () => {
const { length } = this._nav.children;
let left = 0;
for (let i = 0; i < length; i++) {
const { width = 0 } = this._nav.children[i].getBoundingClientRect();
left += width;
}
this._line.style.setProperty("left", `calc(50% - ${left / 2}px)`);
});
/**
* @description: 初始化tabLine的位置,主要是当tabs的align属性为end时需要处理
*/
__publicField(this, "initTabLineAlignEnd", () => {
const { length } = this._nav.children;
let left = 0;
for (let i = 0; i < length; i++) {
const { width = 0 } = this._nav.children[i].getBoundingClientRect();
left += width;
}
this._line.style.setProperty("left", `calc(100% - ${left}px)`);
});
/**
* @description: 通过key值设置tabLine的位置
* @param {string} key
*/
__publicField(this, "setTabLine", (key) => {
if (key) {
const index2 = this.tabHeaderKeyMapIndex[key];
const TabHeader = this._nav.children[index2];
const { width = 0 } = TabHeader.getBoundingClientRect();
this._line.style.setProperty("width", `${width}px`);
let distance = 0;
for (let i = 0; i < index2; i++) {
const item = this._nav.children[i];
const { width: width2 = 0 } = item.getBoundingClientRect();
distance += width2;
}
this._line.style.setProperty("transform", `translateX(${distance}px)`);
}
});
/**
* @description: 通过传入的key值设置tabContent
*/
__publicField(this, "setTabContent", (key) => {
if (key) {
const index2 = this.tabHeaderKeyMapIndex[key];
this._wrap.style.setProperty("transform", `translateX(${index2 * -100}%)`);
}
});
/**
* @description: 根据点击设置 tabLine 的位置
* @param {Event} e
* @param {number} index
* @param {number} width
*/
__publicField(this, "clickTabHead", (e) => {
const tabHeader = e.target;
const key = tabHeader.getAttribute("r-key");
const disabled = isDisabled(tabHeader);
if (!disabled && key) {
this.setAttribute("active", key);
this.setTabLine(key);
this.setTabContent(key);
removeClassToElementChild(this._nav, "active");
addClassToElement(tabHeader, "active");
}
});
/**
* @description: tabPane 设置属性,需要在 tabs 上展示时触发
* @param {string} key
* @param {string} value
*/
__publicField(this, "updateAttribute", (key, attribute, value = "") => {
var _a, _b;
const index2 = this.tabHeaderKeyMapIndex[key];
if (key && value && this._nav.children[index2]) {
(_a = this._nav.children[index2]) == null ? void 0 : _a.setAttribute(attribute, value);
} else {
(_b = this._nav.children[index2]) == null ? void 0 : _b.removeAttribute(attribute);
}
});
/**
* @description: 初始化 tabs 的 active 属性和 tabLine,tabContent
*/
__publicField(this, "initActive", () => {
const tabHeaderList = [...this._nav.children];
const initTabList = tabHeaderList.filter((item) => !isDisabled(item));
let initTabHeader;
if (this.active != null) {
initTabHeader = initTabList.find((item) => item.getAttribute("r-key") === this.active);
initTabHeader == null ? void 0 : initTabHeader.setAttribute("r-key", this.active);
}
if (!initTabHeader) {
initTabHeader = initTabList.shift();
}
if (!initTabHeader) return;
const index2 = tabHeaderList.findIndex((item) => item === initTabHeader);
const key = (initTabHeader == null ? void 0 : initTabHeader.getAttribute("r-key")) || `${index2}`;
if (key != null) {
this.setAttribute("active", `${key}`);
addClassToElement(initTabHeader, "active");
this.setTabContent(key);
setTimeout(() => {
this.setTabLine(key);
}, 200);
}
});
/**
* @description: 监听 slot 组件的添加/删除/替换操作,进行 tabs 初始化
* @return {*}
*/
__publicField(this, "listenSlotChange", () => {
const slots = this._slot.assignedElements();
slots.forEach((item, index2) => {
const tabPane = this.createTabHeader(item, index2);
this._nav.appendChild(tabPane);
tabPane.addEventListener("click", this.clickTabHead);
});
this.initActive();
if (this.align) {
if (this.align === "center") this.initTabLineAlignCenter();
if (this.align === "end") this.initTabLineAlignEnd();
}
});
/**
* @description: 初始化 tab
*/
__publicField(this, "initTab", () => {
this._slot.addEventListener("slotchange", this.listenSlotChange);
});
/**
* @description: 卸载 tab
*/
__publicField(this, "unloadTab", () => {
this._slot.removeEventListener("slotchange", this.listenSlotChange);
});
this._container = document.createElement("div");
this._container.setAttribute("class", "ran-tab");
this._header = document.createElement("div");
this._header.setAttribute("class", "ran-tab-header");
this._nav = document.createElement("div");
this._nav.setAttribute("class", "ran-tab-header-nav");
this._line = document.createElement("div");
this._line.setAttribute("class", "ran-tab-header-line");
this._content = document.createElement("div");
this._content.setAttribute("class", "ran-tab-content");
this._wrap = document.createElement("div");
this._wrap.setAttribute("class", "ran-tab-content-wrap");
this._slot = document.createElement("slot");
this._wrap.appendChild(this._slot);
this._content.appendChild(this._wrap);
this._header.appendChild(createDocumentFragment([this._nav, this._line]));
this._container.appendChild(createDocumentFragment([this._header, this._content]));
this.tabHeaderKeyMapIndex = {};
const shadowRoot = this.attachShadow({ mode: "closed" });
const F7170EE498E0DD32CBDCB63FBA8F75CC = document.createElement("style");
F7170EE498E0DD32CBDCB63FBA8F75CC.textContent = f7170ee498e0dd32cbdcb63fba8f75cc;
shadowRoot.appendChild(F7170EE498E0DD32CBDCB63FBA8F75CC);
shadowRoot.appendChild(this._container);
}
static get observedAttributes() {
return ["active", "forceRender", "type", "align", "effect"];
}
get align() {
return this.getAttribute("align") || "start";
}
set align(value) {
this.setAttribute("align", value);
}
set type(value) {
this.setAttribute("type", value);
}
get type() {
return this.getAttribute("type") || "flat";
}
get active() {
return this.getAttribute("active");
}
set active(value) {
if (value) {
this.setAttribute("active", value);
this.setTabLine(value);
this.setTabContent(value);
} else {
this.removeAttribute("active");
}
}
get effect() {
return this.getAttribute("effect");
}
set effect(value) {
if (!value || value === "false") {
this.removeAttribute("effect");
} else {
this.setAttribute("effect", value);
}
}
/**
* @description: 根据传入的 tabPane 生成 tabs 的头部
* @param {Element} tabPane
* @param {number} index
* @return {Element}
*/
createTabHeader(tabPane, index2) {
const label = tabPane.getAttribute("label") || "";
const icon = tabPane.getAttribute("icon") || "";
const iconSize = tabPane.getAttribute("iconSize") || "";
const key = tabPane.getAttribute("r-key") || `${index2}`;
const type = tabPane.getAttribute("type") || "text";
this.initTabHeaderKeyMapIndex(key, index2);
const tabHeader = document.createElement("r-button");
tabHeader.setAttribute("class", "tab-header-nav-item");
tabHeader.setAttribute("type", type);
icon && tabHeader.setAttribute("icon", icon);
iconSize && tabHeader.setAttribute("iconSize", iconSize);
isDisabled(tabPane) && tabHeader.setAttribute("disabled", "");
tabHeader.setAttribute("r-key", key);
if (this.effect) {
tabPane.setAttribute("effect", this.effect);
this._line.style.setProperty("display", "none");
}
tabPane.setAttribute("r-key", key);
tabHeader.innerHTML = label;
return tabHeader;
}
connectedCallback() {
this.initTab();
}
disconnectCallback() {
this.unloadTab();
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this.dispatchEvent(
new CustomEvent("change", {
detail: {
active: this.active
}
})
);
if (name === "align") {
if (newValue === "center") this.initTabLineAlignCenter();
if (newValue === "end") this.initTabLineAlignEnd();
}
if (name === "effect") {
const tabHeaderList = [...this._nav.children];
tabHeaderList.forEach((item) => {
if (!this.effect || this.effect === "false") {
item.removeAttribute("effect");
} else {
item.setAttribute("effect", newValue);
}
});
}
if (name === "active") {
this.setAttribute(name, newValue);
}
}
}
}
customElements.define("r-tabs", Tabs);
return Tabs;
}
}
const index = CustomElement();
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
default: index
}, Symbol.toStringTag, { value: "Module" }));
export {
index as a,
index$1 as i
};