UNPKG

vue-tui-components

Version:

TUI-styled Vue3 components with Pip-Boy aesthetics - retro terminal UI components for Vue 3

1,639 lines 84.5 kB
import { ref as $, computed as V, createElementBlock as o, openBlock as l, normalizeClass as _, createCommentVNode as h, toDisplayString as g, useSlots as ce, renderSlot as Y, createBlock as Z, Transition as X, withCtx as W, createElementVNode as s, normalizeStyle as K, onMounted as J, onUnmounted as le, createVNode as ae, Fragment as N, renderList as L, watch as G, withDirectives as te, vModelText as se, withModifiers as U, Teleport as de, withKeys as F, nextTick as j, createTextVNode as H, unref as ue, createStaticVNode as he, vModelCheckbox as oe, h as ge, render as be } from "vue"; const D = (e, u) => { const a = e.__vccOpts || e; for (const [t, n] of u) a[t] = n; return a; }, ke = ["aria-label"], $e = ["src", "alt"], we = { key: 1, class: "avatar-initials" }, Te = { key: 2, class: "avatar-icon" }, Se = { key: 3, class: "avatar-placeholder" }, _e = ["aria-label"], Ie = { __name: "TuiAvatar", props: { src: { type: String, default: "" }, alt: { type: String, default: "Avatar" }, initials: { type: String, default: "" }, icon: { type: String, default: "" }, size: { type: String, default: "medium", validator: (e) => ["small", "medium", "large", "xlarge"].includes(e) }, shape: { type: String, default: "circle", validator: (e) => ["circle", "square"].includes(e) }, status: { type: String, default: "", validator: (e) => !e || ["online", "offline", "away", "busy"].includes(e) } }, setup(e) { const u = e, a = $(!1), t = V(() => u.initials ? u.initials.slice(0, 2).toUpperCase() : ""), n = V(() => u.alt !== "Avatar" ? u.alt : u.initials ? `Avatar: ${u.initials}` : u.icon ? `Avatar with icon: ${u.icon}` : "Avatar"), i = () => { a.value = !0; }; return (p, c) => (l(), o("div", { class: _(["tui-avatar", [e.size, e.shape, { "has-status": e.status }]]), "aria-label": n.value }, [ e.src ? (l(), o("img", { key: 0, src: e.src, alt: e.alt, class: "avatar-image", onError: i }, null, 40, $e)) : e.initials ? (l(), o("span", we, g(t.value), 1)) : e.icon ? (l(), o("span", Te, g(e.icon), 1)) : (l(), o("span", Se, "?")), e.status ? (l(), o("span", { key: 4, class: _(["avatar-status", e.status]), "aria-label": `Status: ${e.status}` }, null, 10, _e)) : h("", !0) ], 10, ke)); } }, xe = /* @__PURE__ */ D(Ie, [["__scopeId", "data-v-84d07ae3"]]), Ce = ["aria-label"], De = { key: 0, class: "badge-content" }, Be = { key: 0 }, Ve = { key: 1 }, Me = { __name: "TuiBadge", props: { content: { type: [String, Number], default: "" }, variant: { type: String, default: "primary", validator: (e) => ["primary", "secondary", "success", "error", "warning", "info"].includes(e) }, size: { type: String, default: "medium", validator: (e) => ["small", "medium", "large"].includes(e) }, placement: { type: String, default: "top-right", validator: (e) => ["top-right", "top-left", "bottom-right", "bottom-left"].includes(e) }, max: { type: Number, default: 99 }, dot: { type: Boolean, default: !1 }, icon: { type: String, default: "" }, visible: { type: Boolean, default: !0 } }, setup(e) { const u = e, a = ce(), t = V(() => !!a.default), n = V(() => typeof u.content == "number" && u.content > u.max ? `${u.max}+` : u.content), i = V(() => u.dot ? "Notification indicator" : u.icon ? `Badge with icon: ${u.icon}` : `Badge: ${n.value}`); return (p, c) => (l(), o("span", { class: _(["tui-badge-wrapper", { standalone: !t.value }]) }, [ Y(p.$slots, "default", {}, void 0, !0), e.visible ? (l(), o("span", { key: 0, class: _(["tui-badge", [e.variant, e.size, e.placement, { dot: e.dot }]]), "aria-label": i.value }, [ e.dot ? h("", !0) : (l(), o("span", De, [ e.icon ? (l(), o("span", Be, g(e.icon), 1)) : e.content ? (l(), o("span", Ve, g(n.value), 1)) : h("", !0) ])) ], 10, Ce)) : h("", !0) ], 2)); } }, Ae = /* @__PURE__ */ D(Me, [["__scopeId", "data-v-bd1fb1e4"]]), Ee = { class: "banner-content" }, Ne = { key: 0, class: "banner-icon" }, Le = { class: "banner-message" }, ze = { key: 0, class: "banner-title" }, Re = { class: "banner-text" }, Oe = { class: "banner-actions" }, qe = ["href"], Pe = { __name: "TuiBanner", props: { message: { type: String, required: !0 }, title: { type: String, default: "" }, variant: { type: String, default: "info", validator: (e) => ["primary", "success", "error", "warning", "info"].includes(e) }, icon: { type: String, default: "" }, dismissible: { type: Boolean, default: !0 }, linkText: { type: String, default: "" }, linkUrl: { type: String, default: "" }, modelValue: { type: Boolean, default: !0 } }, emits: ["update:modelValue", "dismiss", "link-click"], setup(e, { emit: u }) { const a = e, t = u, n = $(a.modelValue), i = () => { n.value = !1, t("update:modelValue", !1), t("dismiss"); }, p = (c) => { t("link-click", c); }; return (c, d) => (l(), Z(X, { name: "banner-slide" }, { default: W(() => [ n.value ? (l(), o("div", { key: 0, class: _(["tui-banner", e.variant]), role: "banner" }, [ s("div", Ee, [ e.icon ? (l(), o("span", Ne, g(e.icon), 1)) : h("", !0), s("div", Le, [ e.title ? (l(), o("strong", ze, g(e.title), 1)) : h("", !0), s("span", Re, g(e.message), 1) ]) ]), s("div", Oe, [ Y(c.$slots, "actions", {}, () => [ e.linkText && e.linkUrl ? (l(), o("a", { key: 0, href: e.linkUrl, class: "banner-link", onClick: p }, g(e.linkText), 9, qe)) : h("", !0) ], !0), e.dismissible ? (l(), o("button", { key: 0, class: "banner-close", type: "button", onClick: i, "aria-label": "Dismiss banner" }, " ✕ ")) : h("", !0) ]) ], 2)) : h("", !0) ]), _: 3 })); } }, Ye = /* @__PURE__ */ D(Pe, [["__scopeId", "data-v-c1d3534c"]]), Fe = ["disabled"], Ue = { class: "button-text" }, He = { __name: "TuiButton", props: { label: { type: String, required: !0 }, variant: { type: String, default: "primary", validator: (e) => ["primary", "warning", "info", "success", "secondary", "danger"].includes(e) }, disabled: { type: Boolean, default: !1 }, pulse: { type: Boolean, default: !1 } }, emits: ["click"], setup(e) { return (u, a) => (l(), o("button", { class: _(["tui-button", [e.variant, { disabled: e.disabled, pulse: e.pulse }]]), disabled: e.disabled, onClick: a[0] || (a[0] = (t) => u.$emit("click", t)) }, [ a[1] || (a[1] = s("span", { class: "button-brackets" }, "[", -1)), s("span", Ue, g(e.label), 1), a[2] || (a[2] = s("span", { class: "button-brackets" }, "]", -1)) ], 10, Fe)); } }, ie = /* @__PURE__ */ D(He, [["__scopeId", "data-v-9ad134c2"]]), Ke = { key: 0, class: "card-header" }, Ge = { key: 0, class: "card-title" }, We = ["title", "aria-expanded", "aria-label"], je = ["aria-hidden"], Xe = { class: "card-body" }, Je = { key: 0, class: "card-footer" }, Qe = { __name: "TuiCard", props: { title: { type: String, default: "" }, glowing: { type: Boolean, default: !1 }, fadeIn: { type: Boolean, default: !1 }, slideIn: { type: Boolean, default: !1 }, animationDelay: { type: Number, default: 0 }, animationDuration: { type: Number, default: 500 }, minimizable: { type: Boolean, default: !1 } }, setup(e) { const u = e, a = ce(), t = V(() => { var d; const c = (d = a.footer) == null ? void 0 : d.call(a); return Array.isArray(c) ? c.length > 0 : !!c; }), n = $(!1), i = () => { n.value = !n.value; }, p = V(() => !u.fadeIn && !u.slideIn ? {} : { animationDelay: `${u.animationDelay}ms`, animationDuration: `${u.animationDuration}ms` }); return (c, d) => (l(), o("div", { class: _(["tui-card", { glowing: e.glowing, "animate-fade-in": e.fadeIn, "animate-slide-in": e.slideIn, minimized: n.value }]), style: K(p.value) }, [ e.title || e.minimizable ? (l(), o("div", Ke, [ e.title ? (l(), o("h3", Ge, g(e.title), 1)) : h("", !0), e.minimizable ? (l(), o("button", { key: 1, class: "minimize-button", type: "button", onClick: i, title: n.value ? "Expand" : "Minimize", "aria-expanded": (!n.value).toString(), "aria-label": n.value ? "Expand card" : "Minimize card" }, g(n.value ? "▼" : "▲"), 9, We)) : h("", !0) ])) : h("", !0), s("div", { class: _(["card-content", { collapsed: n.value }]), "aria-hidden": n.value ? "true" : "false" }, [ s("div", Xe, [ Y(c.$slots, "default", {}, void 0, !0) ]), t.value ? (l(), o("div", Je, [ Y(c.$slots, "footer", {}, void 0, !0) ])) : h("", !0) ], 10, je) ], 6)); } }, Ze = /* @__PURE__ */ D(Qe, [["__scopeId", "data-v-d497e929"]]), et = { class: "tui-carousel" }, tt = { class: "carousel-container" }, at = ["disabled"], lt = { class: "carousel-viewport" }, st = { class: "carousel-track" }, nt = ["src", "alt"], ot = { key: 1, class: "carousel-caption" }, it = ["disabled"], rt = { key: 0, class: "carousel-indicators" }, ut = ["onClick", "aria-label", "aria-current"], ct = { __name: "TuiCarousel", props: { items: { type: Array, required: !0 }, autoplay: { type: Boolean, default: !1 }, interval: { type: Number, default: 3e3 }, loop: { type: Boolean, default: !0 }, showControls: { type: Boolean, default: !0 }, showIndicators: { type: Boolean, default: !0 }, transition: { type: String, default: "slide", validator: (e) => ["slide", "fade"].includes(e) } }, emits: ["change"], setup(e, { emit: u }) { const a = e, t = u, n = $(0), i = $("next"); let p = null; const c = V(() => a.transition === "fade" ? "carousel-fade" : i.value === "next" ? "carousel-slide-next" : "carousel-slide-prev"), d = () => { n.value < a.items.length - 1 ? (i.value = "next", n.value++, t("change", n.value)) : a.loop && (i.value = "next", n.value = 0, t("change", n.value)); }, y = () => { n.value > 0 ? (i.value = "prev", n.value--, t("change", n.value)) : a.loop && (i.value = "prev", n.value = a.items.length - 1, t("change", n.value)); }, b = (r) => { i.value = r > n.value ? "next" : "prev", n.value = r, t("change", n.value); }, v = () => { a.autoplay && (p = setInterval(() => { d(); }, a.interval)); }, f = () => { p && (clearInterval(p), p = null); }; return J(() => { v(); }), le(() => { f(); }), (r, m) => (l(), o("div", et, [ s("div", tt, [ e.showControls ? (l(), o("button", { key: 0, class: "carousel-control prev", onClick: y, "aria-label": "Previous slide", disabled: n.value === 0 && !e.loop }, " ◄ ", 8, at)) : h("", !0), s("div", lt, [ s("div", st, [ ae(X, { name: c.value, mode: "out-in" }, { default: W(() => [ (l(), o("div", { key: n.value, class: "carousel-slide" }, [ Y(r.$slots, "default", { item: e.items[n.value], index: n.value }, () => [ e.items[n.value].image ? (l(), o("img", { key: 0, src: e.items[n.value].image, alt: e.items[n.value].caption || "", class: "carousel-image" }, null, 8, nt)) : h("", !0), e.items[n.value].caption ? (l(), o("div", ot, g(e.items[n.value].caption), 1)) : h("", !0) ], !0) ])) ]), _: 3 }, 8, ["name"]) ]) ]), e.showControls ? (l(), o("button", { key: 1, class: "carousel-control next", onClick: d, "aria-label": "Next slide", disabled: n.value === e.items.length - 1 && !e.loop }, " ► ", 8, it)) : h("", !0) ]), e.showIndicators ? (l(), o("div", rt, [ (l(!0), o(N, null, L(e.items, (k, B) => (l(), o("button", { key: B, class: _(["indicator", { active: B === n.value }]), onClick: (T) => b(B), "aria-label": `Go to slide ${B + 1}`, "aria-current": B === n.value }, " ■ ", 10, ut))), 128)) ])) : h("", !0) ])); } }, dt = /* @__PURE__ */ D(ct, [["__scopeId", "data-v-27747afa"]]), vt = { class: "tui-checkbox" }, mt = ["checked"], pt = { class: "checkbox-box" }, ft = { key: 0, class: "checkbox-check" }, yt = { key: 1, class: "checkbox-empty" }, ht = { class: "checkbox-label" }, gt = { __name: "TuiCheckbox", props: { modelValue: { type: Boolean, default: !1 }, label: { type: String, required: !0 } }, emits: ["update:modelValue"], setup(e) { return (u, a) => (l(), o("label", vt, [ s("input", { type: "checkbox", checked: e.modelValue, onChange: a[0] || (a[0] = (t) => u.$emit("update:modelValue", t.target.checked)), class: "checkbox-input" }, null, 40, mt), s("span", pt, [ e.modelValue ? (l(), o("span", ft, "✓")) : (l(), o("span", yt, "[ ]")) ]), s("span", ht, g(e.label), 1) ])); } }, bt = /* @__PURE__ */ D(gt, [["__scopeId", "data-v-7e8d4e28"]]), kt = { key: 0, class: "chip-icon" }, $t = { key: 1, class: "chip-avatar" }, wt = ["src", "alt"], Tt = { key: 1 }, St = { class: "chip-label" }, _t = { __name: "TuiChip", props: { label: { type: String, required: !0 }, variant: { type: String, default: "primary", validator: (e) => ["primary", "secondary", "success", "error", "warning", "info"].includes(e) }, size: { type: String, default: "medium", validator: (e) => ["small", "medium", "large"].includes(e) }, closable: { type: Boolean, default: !1 }, icon: { type: String, default: "" }, avatar: { type: Boolean, default: !1 }, avatarSrc: { type: String, default: "" }, avatarText: { type: String, default: "" } }, emits: ["close"], setup(e, { emit: u }) { const a = u, t = (n) => { n.stopPropagation(), a("close"); }; return (n, i) => (l(), o("div", { class: _(["tui-chip", [e.variant, e.size, { closable: e.closable }]]) }, [ e.icon ? (l(), o("span", kt, g(e.icon), 1)) : h("", !0), e.avatar ? (l(), o("span", $t, [ e.avatarSrc ? (l(), o("img", { key: 0, src: e.avatarSrc, alt: e.label }, null, 8, wt)) : (l(), o("span", Tt, g(e.avatarText), 1)) ])) : h("", !0), s("span", St, g(e.label), 1), e.closable ? (l(), o("button", { key: 2, class: "chip-close", type: "button", onClick: t, "aria-label": "Remove chip" }, " ✕ ")) : h("", !0) ], 2)); } }, It = /* @__PURE__ */ D(_t, [["__scopeId", "data-v-87d00535"]]), xt = { class: "tui-datepicker" }, Ct = { key: 0, class: "datepicker-label" }, Dt = { class: "datepicker-input-wrapper" }, Bt = ["placeholder"], Vt = { class: "datepicker-header" }, Mt = { class: "current-month" }, At = { class: "datepicker-calendar" }, Et = { class: "calendar-weekdays" }, Nt = { class: "calendar-days" }, Lt = ["disabled", "onClick"], zt = { __name: "TuiDatepicker", props: { modelValue: { type: [Date, Array, null], default: null }, label: { type: String, default: "" }, placeholder: { type: String, default: "Select date" }, format: { type: String, default: "YYYY-MM-DD" }, range: { type: Boolean, default: !1 } }, emits: ["update:modelValue", "change"], setup(e, { emit: u }) { const a = e, t = u, n = $(!1), i = $(""), p = $((/* @__PURE__ */ new Date()).getMonth()), c = $((/* @__PURE__ */ new Date()).getFullYear()), d = $(a.modelValue), y = $(null), b = $(null), v = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], f = V(() => new Date(c.value, p.value).toLocaleDateString("en-US", { month: "long", year: "numeric" })), r = V(() => { const w = [], S = new Date(c.value, p.value, 1), A = new Date(c.value, p.value + 1, 0), O = new Date(c.value, p.value, 0), ne = S.getDay(), fe = A.getDate(), re = O.getDate(); for (let q = ne - 1; q >= 0; q--) w.push({ date: re - q, month: p.value - 1, year: c.value, currentMonth: !1, key: `prev-${re - q}` }); for (let q = 1; q <= fe; q++) w.push({ date: q, month: p.value, year: c.value, currentMonth: !0, key: `current-${q}` }); const ye = 42 - w.length; for (let q = 1; q <= ye; q++) w.push({ date: q, month: p.value + 1, year: c.value, currentMonth: !1, key: `next-${q}` }); return w; }), m = (w) => { if (!w) return ""; const S = new Date(w), A = S.getFullYear(), O = String(S.getMonth() + 1).padStart(2, "0"), ne = String(S.getDate()).padStart(2, "0"); return a.format.replace("YYYY", A).replace("MM", O).replace("DD", ne); }, k = () => { a.range && y.value ? b.value ? i.value = `${m(y.value)} - ${m(b.value)}` : i.value = m(y.value) : d.value ? i.value = m(d.value) : i.value = ""; }, B = (w) => { if (!w.currentMonth) return !1; const S = new Date(w.year, w.month, w.date); if (a.range) { if (y.value && b.value) { const A = new Date(y.value), O = new Date(b.value); return A.setHours(0, 0, 0, 0), O.setHours(0, 0, 0, 0), S.setHours(0, 0, 0, 0), S.getTime() === A.getTime() || S.getTime() === O.getTime(); } return y.value && S.getTime() === new Date(y.value).setHours(0, 0, 0, 0); } return d.value && S.getTime() === new Date(d.value).setHours(0, 0, 0, 0); }, T = (w) => { if (!w.currentMonth) return !1; const S = /* @__PURE__ */ new Date(); return w.date === S.getDate() && w.month === S.getMonth() && w.year === S.getFullYear(); }, I = (w) => { if (!a.range || !y.value || !b.value || !w.currentMonth) return !1; const S = new Date(w.year, w.month, w.date), A = new Date(y.value), O = new Date(b.value); return S.setHours(0, 0, 0, 0), A.setHours(0, 0, 0, 0), O.setHours(0, 0, 0, 0), S > A && S < O; }, x = (w) => { const S = new Date(w.year, w.month, w.date); a.range ? !y.value || y.value && b.value ? (y.value = S, b.value = null) : (S < y.value ? (b.value = y.value, y.value = S) : b.value = S, t("update:modelValue", [y.value, b.value]), t("change", [y.value, b.value])) : (d.value = S, t("update:modelValue", S), t("change", S), ee()), k(); }, z = () => { p.value === 0 ? (p.value = 11, c.value--) : p.value--; }, P = () => { p.value === 11 ? (p.value = 0, c.value++) : p.value++; }, E = () => { n.value = !0; }, ee = () => { n.value = !1; }, R = () => { n.value = !n.value; }, C = () => { setTimeout(() => { n.value = !1; }, 200); }, M = () => { d.value = null, y.value = null, b.value = null, i.value = "", t("update:modelValue", null), t("change", null); }; return G(() => a.modelValue, (w) => { a.range && Array.isArray(w) ? (y.value = w[0] || null, b.value = w[1] || null) : d.value = w, k(); }, { immediate: !0 }), (w, S) => (l(), o("div", xt, [ e.label ? (l(), o("label", Ct, g(e.label), 1)) : h("", !0), s("div", Dt, [ te(s("input", { "onUpdate:modelValue": S[0] || (S[0] = (A) => i.value = A), type: "text", class: "datepicker-input", placeholder: e.placeholder, onFocus: E, onBlur: C, readonly: "" }, null, 40, Bt), [ [se, i.value] ]), s("button", { type: "button", class: "datepicker-toggle", onClick: R, "aria-label": "Toggle date picker" }, " ▼ ") ]), ae(X, { name: "picker-fade" }, { default: W(() => [ n.value ? (l(), o("div", { key: 0, class: "datepicker-popup", onMousedown: S[1] || (S[1] = U(() => { }, ["prevent"])) }, [ s("div", Vt, [ s("button", { type: "button", onClick: z, class: "nav-button", "aria-label": "Previous month" }, "◄"), s("span", Mt, g(f.value), 1), s("button", { type: "button", onClick: P, class: "nav-button", "aria-label": "Next month" }, "►") ]), s("div", At, [ s("div", Et, [ (l(), o(N, null, L(v, (A) => s("span", { key: A, class: "weekday" }, g(A), 1)), 64)) ]), s("div", Nt, [ (l(!0), o(N, null, L(r.value, (A) => (l(), o("button", { key: A.key, type: "button", class: _(["calendar-day", { "other-month": !A.currentMonth, selected: B(A), today: T(A), "in-range": I(A) }]), disabled: !A.currentMonth, onClick: (O) => x(A) }, g(A.date), 11, Lt))), 128)) ]) ]), s("div", { class: "datepicker-actions" }, [ s("button", { type: "button", onClick: M, class: "action-button" }, "Clear"), s("button", { type: "button", onClick: ee, class: "action-button primary" }, "Done") ]) ], 32)) : h("", !0) ]), _: 1 }) ])); } }, Rt = /* @__PURE__ */ D(zt, [["__scopeId", "data-v-cba7510f"]]), Ot = ["aria-labelledby"], qt = { key: 0, class: "dialog-header" }, Pt = { key: 0, id: "dialog-title", class: "dialog-title" }, Yt = { class: "dialog-body" }, Ft = { key: 1, class: "dialog-footer" }, Ut = { key: 0, class: "dialog-actions" }, Ht = { __name: "TuiDialog", props: { modelValue: { type: Boolean, default: !1 }, title: { type: String, default: "" }, closable: { type: Boolean, default: !0 }, closeOnOverlay: { type: Boolean, default: !0 }, overlayOpacity: { type: Number, default: 0.8 }, showActions: { type: Boolean, default: !0 }, showConfirm: { type: Boolean, default: !0 }, showCancel: { type: Boolean, default: !0 }, confirmText: { type: String, default: "Confirm" }, cancelText: { type: String, default: "Cancel" }, confirmVariant: { type: String, default: "primary", validator: (e) => ["primary", "success", "danger", "warning", "info"].includes(e) } }, emits: ["update:modelValue", "confirm", "cancel", "close"], setup(e, { emit: u }) { const a = e, t = u, n = () => { t("update:modelValue", !1), t("close"); }, i = () => { a.closeOnOverlay && a.closable && n(); }, p = () => { t("confirm"), n(); }, c = () => { t("cancel"), n(); }; return G(() => a.modelValue, (d) => { d ? document.body.style.overflow = "hidden" : document.body.style.overflow = ""; }), (d, y) => (l(), Z(de, { to: "body" }, [ ae(X, { name: "dialog-fade" }, { default: W(() => [ e.modelValue ? (l(), o("div", { key: 0, class: "tui-dialog-overlay", style: K({ "--overlay-opacity": e.overlayOpacity }), onClick: U(i, ["self"]) }, [ s("div", { class: _(["tui-dialog", { "no-close": !e.closable }]), role: "dialog", "aria-modal": "true", "aria-labelledby": e.title ? "dialog-title" : void 0 }, [ e.title || e.closable ? (l(), o("div", qt, [ e.title ? (l(), o("h3", Pt, g(e.title), 1)) : h("", !0), e.closable ? (l(), o("button", { key: 1, class: "dialog-close", type: "button", onClick: n, "aria-label": "Close dialog" }, " ✕ ")) : h("", !0) ])) : h("", !0), s("div", Yt, [ Y(d.$slots, "default", {}, void 0, !0) ]), d.$slots.footer || e.showActions ? (l(), o("div", Ft, [ Y(d.$slots, "footer", {}, () => [ e.showActions ? (l(), o("div", Ut, [ e.showCancel ? (l(), Z(ie, { key: 0, label: e.cancelText, variant: "secondary", onClick: c }, null, 8, ["label"])) : h("", !0), e.showConfirm ? (l(), Z(ie, { key: 1, label: e.confirmText, variant: e.confirmVariant, onClick: p }, null, 8, ["label", "variant"])) : h("", !0) ])) : h("", !0) ], !0) ])) : h("", !0) ], 10, Ot) ], 4)) : h("", !0) ]), _: 3 }) ])); } }, Kt = /* @__PURE__ */ D(Ht, [["__scopeId", "data-v-ecc5e202"]]), Gt = ["onKeydown", "tabindex"], Wt = { class: "default-trigger" }, jt = { class: "dropdown-inner" }, Xt = ["onClick", "onMouseenter"], Jt = { key: 0, class: "dropdown-separator" }, Qt = { key: 0, class: "item-icon" }, Zt = { class: "item-label" }, ea = { key: 1, class: "item-shortcut" }, ta = { key: 2, class: "item-arrow" }, aa = { __name: "TuiDropdown", props: { label: { type: String, default: "" }, items: { type: Array, required: !0 }, disabled: { type: Boolean, default: !1 }, align: { type: String, default: "left", // 'left' or 'right' validator: (e) => ["left", "right"].includes(e) } }, emits: ["item-click", "open", "close"], setup(e, { expose: u, emit: a }) { const t = e, n = a, i = $(null), p = $(null), c = $(!1), d = $(-1), y = $({}), b = () => { t.disabled || (c.value ? f() : v()); }, v = async () => { if (!t.disabled) { if (i.value) { const T = i.value.querySelector(".dropdown-trigger").getBoundingClientRect(); y.value = { position: "fixed", top: `${T.bottom + 2}px`, left: `${T.left}px`, minWidth: `${T.width}px`, zIndex: 9999 }; } c.value = !0, d.value = -1, n("open"), await j(), requestAnimationFrame(() => { requestAnimationFrame(() => { m(); }); }), document.addEventListener("click", r); } }, f = () => { c.value = !1, d.value = -1, n("close"), document.removeEventListener("click", r); }, r = (T) => { i.value && !i.value.contains(T.target) && p.value && !p.value.contains(T.target) && f(); }, m = () => { if (!i.value || !p.value) return; const T = i.value.querySelector(".dropdown-trigger").getBoundingClientRect(), I = p.value.getBoundingClientRect(); if (I.width === 0 || I.height === 0) { requestAnimationFrame(() => m()); return; } const x = window.innerWidth, z = window.innerHeight; let P = T.bottom + 2, E = T.left; t.align === "right" && (E = T.right - I.width), E + I.width > x && (E = x - I.width - 10), E < 10 && (E = 10), P + I.height > z && (P = T.top - I.height - 2, P < 10 && (P = 10)), y.value = { position: "fixed", top: `${P}px`, left: `${E}px`, minWidth: `${T.width}px`, zIndex: 9999 }; }, k = (T) => { T.disabled || T.separator || (n("item-click", T), T.action && T.action(), T.submenu || f()); }, B = (T) => { if (!c.value) { v(); return; } let I = d.value + T; for (; I >= 0 && I < t.items.length; ) { const x = t.items[I]; if (!x.separator && !x.disabled) { d.value = I; return; } I += T; } I < 0 ? d.value = t.items.length - 1 : I >= t.items.length && (d.value = 0); }; return J(() => { window.addEventListener("resize", m); }), le(() => { document.removeEventListener("click", r), window.removeEventListener("resize", m); }), u({ open: v, close: f, toggle: b }), (T, I) => (l(), o("div", { class: "tui-dropdown", ref_key: "dropdownRef", ref: i }, [ s("div", { class: _(["dropdown-trigger", { "is-open": c.value, "is-disabled": e.disabled }]), onClick: b, onKeydown: [ F(f, ["escape"]), F(U(b, ["prevent"]), ["enter"]), F(U(b, ["prevent"]), ["space"]), I[0] || (I[0] = F(U((x) => B(-1), ["prevent"]), ["up"])), I[1] || (I[1] = F(U((x) => B(1), ["prevent"]), ["down"])) ], tabindex: e.disabled ? -1 : 0 }, [ Y(T.$slots, "trigger", { isOpen: c.value }, () => [ s("span", Wt, g(e.label), 1) ], !0) ], 42, Gt), (l(), Z(de, { to: "body" }, [ ae(X, { name: "dropdown" }, { default: W(() => [ c.value ? (l(), o("div", { key: 0, class: "dropdown-menu", style: K(y.value), ref_key: "menuRef", ref: p }, [ s("div", jt, [ (l(!0), o(N, null, L(e.items, (x, z) => (l(), o("div", { key: x.id || z, class: _(["dropdown-item", { "is-highlighted": z === d.value, "is-disabled": x.disabled, "is-separator": x.separator, "has-submenu": x.submenu }]), onClick: (P) => !x.disabled && !x.separator && k(x), onMouseenter: (P) => d.value = z }, [ x.separator ? (l(), o("div", Jt)) : (l(), o(N, { key: 1 }, [ x.icon ? (l(), o("span", Qt, g(x.icon), 1)) : h("", !0), s("span", Zt, g(x.label), 1), x.shortcut ? (l(), o("span", ea, g(x.shortcut), 1)) : h("", !0), x.submenu ? (l(), o("span", ta, "►")) : h("", !0) ], 64)) ], 42, Xt))), 128)) ]) ], 4)) : h("", !0) ]), _: 1 }) ])) ], 512)); } }, ve = /* @__PURE__ */ D(aa, [["__scopeId", "data-v-d6fd60c2"]]), la = { class: "tui-header" }, sa = { class: "header-content" }, na = { class: "header-title" }, oa = { key: 0, class: "header-subtitle" }, ia = { class: "header-timestamp" }, ra = { __name: "TuiHeader", props: { title: { type: String, required: !0 }, subtitle: { type: String, default: "" } }, setup(e) { const u = $(""), a = () => { const n = /* @__PURE__ */ new Date(); u.value = n.toLocaleString("en-US", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: !1 }); }; let t; return J(() => { a(), t = setInterval(a, 1e3); }), le(() => { clearInterval(t); }), (n, i) => (l(), o("header", la, [ i[0] || (i[0] = s("div", { class: "header-top" }, [ s("span", { class: "corner" }, "╔"), s("div", { class: "header-line" }), s("span", { class: "corner" }, "╗") ], -1)), s("div", sa, [ s("h1", na, g(e.title), 1), e.subtitle ? (l(), o("p", oa, g(e.subtitle), 1)) : h("", !0), s("div", ia, g(u.value), 1) ]), i[1] || (i[1] = s("div", { class: "header-bottom" }, [ s("span", { class: "corner" }, "╚"), s("div", { class: "header-line" }), s("span", { class: "corner" }, "╝") ], -1)) ])); } }, ua = /* @__PURE__ */ D(ra, [["__scopeId", "data-v-40df859c"]]), ca = ["aria-label", "role"], da = { __name: "TuiIcon", props: { icon: { type: String, required: !0 }, type: { type: String, default: "unicode", validator: (e) => ["unicode", "material"].includes(e) }, materialVariant: { type: String, default: "outlined", validator: (e) => ["filled", "outlined", "round", "sharp"].includes(e) }, size: { type: String, default: "medium", validator: (e) => ["small", "medium", "large", "xlarge"].includes(e) }, variant: { type: String, default: "primary", validator: (e) => ["primary", "secondary", "success", "error", "warning", "info", "inherit"].includes(e) }, spin: { type: Boolean, default: !1 }, pulse: { type: Boolean, default: !1 }, ariaLabel: { type: String, default: "" }, customSize: { type: String, default: "" } }, setup(e) { const u = e, a = V(() => u.type === "material" ? { filled: "material-icons", outlined: "material-icons-outlined", round: "material-icons-round", sharp: "material-icons-sharp" }[u.materialVariant] : ""), t = V(() => u.customSize ? { fontSize: u.customSize } : {}); return (n, i) => (l(), o("span", { class: _(["tui-icon", [ e.size, e.variant, { spin: e.spin, pulse: e.pulse }, a.value ]]), style: K(t.value), "aria-label": e.ariaLabel, role: e.ariaLabel ? "img" : void 0 }, g(e.icon), 15, ca)); } }, va = /* @__PURE__ */ D(da, [["__scopeId", "data-v-48751b1e"]]), ma = ["src", "alt"], pa = { key: 1, class: "image-placeholder" }, fa = { class: "loading-text" }, ya = { key: 2, class: "image-loading" }, ha = { key: 3, class: "image-error" }, ga = { class: "error-text" }, ba = { key: 0, class: "image-caption" }, ka = { __name: "TuiImage", props: { src: { type: String, required: !0 }, alt: { type: String, default: "" }, lazy: { type: Boolean, default: !1 }, aspectRatio: { type: String, default: "", validator: (e) => !e || ["1:1", "4:3", "16:9", "21:9", "3:2"].includes(e) }, overlay: { type: Boolean, default: !1 }, overlayOpacity: { type: Number, default: 0.7 }, caption: { type: String, default: "" }, loadingText: { type: String, default: "Loading..." }, errorText: { type: String, default: "Failed to load image" } }, emits: ["load", "error"], setup(e, { emit: u }) { const a = e, t = u, n = $(!a.lazy), i = $(!1), p = $(!1); let c = null; const d = V(() => a.aspectRatio ? { paddingBottom: { "1:1": "100%", "4:3": "75%", "16:9": "56.25%", "21:9": "42.86%", "3:2": "66.67%" }[a.aspectRatio], position: "relative" } : {}), y = V(() => ({ backgroundColor: `rgba(0, 0, 0, ${a.overlayOpacity})` })), b = () => { i.value = !0, t("load"); }, v = () => { p.value = !0, i.value = !1, t("error"); }; return J(() => { if (a.lazy && "IntersectionObserver" in window) { c = new IntersectionObserver((r) => { r.forEach((m) => { m.isIntersecting && (n.value = !0, c == null || c.disconnect()); }); }, { rootMargin: "50px" }); const f = document.querySelector(".tui-image"); f && c.observe(f); } }), le(() => { c == null || c.disconnect(); }), (f, r) => (l(), o("div", { class: _(["tui-image", { "has-overlay": e.overlay || e.caption }]), style: K(d.value) }, [ !e.lazy || n.value ? (l(), o("img", { key: 0, src: e.src, alt: e.alt, class: _(["image-element", { loaded: i.value, error: p.value }]), onLoad: b, onError: v }, null, 42, ma)) : (l(), o("div", pa, [ s("span", fa, g(e.loadingText), 1) ])), !i.value && !p.value ? (l(), o("div", ya, [...r[0] || (r[0] = [ s("span", { class: "loading-spinner" }, "◐", -1) ])])) : h("", !0), p.value ? (l(), o("div", ha, [ r[1] || (r[1] = s("span", null, "✕", -1)), s("span", ga, g(e.errorText), 1) ])) : h("", !0), (e.overlay || e.caption) && i.value ? (l(), o("div", { key: 4, class: "image-overlay", style: K(y.value) }, [ Y(f.$slots, "overlay", {}, () => [ e.caption ? (l(), o("div", ba, g(e.caption), 1)) : h("", !0) ], !0) ], 4)) : h("", !0) ], 6)); } }, $a = /* @__PURE__ */ D(ka, [["__scopeId", "data-v-29b0ea40"]]), wa = { class: "tui-input-wrapper" }, Ta = { key: 0, class: "tui-label" }, Sa = { class: "input-container" }, _a = ["type", "value", "placeholder", "disabled"], Ia = { __name: "TuiInput", props: { modelValue: { type: [String, Number], default: "" }, label: { type: String, default: "" }, type: { type: String, default: "text" }, placeholder: { type: String, default: "" }, disabled: { type: Boolean, default: !1 } }, emits: ["update:modelValue"], setup(e) { return (u, a) => (l(), o("div", wa, [ e.label ? (l(), o("label", Ta, [ a[1] || (a[1] = s("span", { class: "label-bracket" }, ">", -1)), H(" " + g(e.label), 1) ])) : h("", !0), s("div", Sa, [ a[2] || (a[2] = s("span", { class: "input-prompt" }, ">>", -1)), s("input", { type: e.type, value: e.modelValue, placeholder: e.placeholder, disabled: e.disabled, class: "tui-input", onInput: a[0] || (a[0] = (t) => u.$emit("update:modelValue", t.target.value)) }, null, 40, _a), a[3] || (a[3] = s("span", { class: "input-cursor" }, "_", -1)) ]) ])); } }, xa = /* @__PURE__ */ D(Ia, [["__scopeId", "data-v-808aff2f"]]), Ca = { class: "menubar-inner" }, Da = { class: "menubar-left" }, Ba = { class: "menu-label" }, Va = { key: 0, class: "menubar-right" }, Ma = { __name: "TuiMenubar", props: { menus: { type: Array, required: !0 }, compact: { type: Boolean, default: !1 } }, emits: ["menu-item-click"], setup(e, { emit: u }) { const a = u, t = (n) => { a("menu-item-click", n); }; return (n, i) => (l(), o("div", { class: _(["tui-menubar", { "is-compact": e.compact }]) }, [ s("div", Ca, [ s("div", Da, [ (l(!0), o(N, null, L(e.menus, (p) => (l(), Z(ve, { key: p.id, items: p.items, onItemClick: t, class: "menubar-item" }, { trigger: W(({ isOpen: c }) => [ s("div", { class: _(["menu-trigger", { "is-open": c }]) }, [ i[0] || (i[0] = s("span", { class: "menu-prompt" }, "►", -1)), s("span", Ba, g(p.label), 1) ], 2) ]), _: 2 }, 1032, ["items"]))), 128)) ]), n.$slots.right ? (l(), o("div", Va, [ Y(n.$slots, "right", {}, void 0, !0) ])) : h("", !0) ]) ], 2)); } }, Aa = /* @__PURE__ */ D(Ma, [["__scopeId", "data-v-ca7b423d"]]), Ea = { class: "otp-inputs" }, Na = ["onUpdate:modelValue", "aria-label", "onInput", "onKeydown", "disabled"], La = { key: 0, class: "otp-error" }, za = { __name: "TuiOTP", props: { modelValue: { type: String, default: "" }, length: { type: Number, default: 6, validator: (e) => e > 0 && e <= 10 }, masked: { type: Boolean, default: !1 }, disabled: { type: Boolean, default: !1 }, error: { type: String, default: "" }, autoFocus: { type: Boolean, default: !0 } }, emits: ["update:modelValue", "complete"], setup(e, { emit: u }) { const a = e, t = u, n = $(Array(a.length).fill("")), i = $([]), p = $(!1); G(() => a.modelValue, (v) => { if (v) { const f = v.split("").slice(0, a.length); n.value = [...f, ...Array(a.length - f.length).fill("")]; } }, { immediate: !0 }), G(() => a.error, (v) => { p.value = !!v; }); const c = (v, f) => { const r = f.target.value; if (!/^\d*$/.test(r)) { n.value[v] = ""; return; } n.value[v] = r.slice(-1), b(), r && v < a.length - 1 && j(() => { var m; (m = i.value[v + 1]) == null || m.focus(); }); }, d = (v, f) => { var r, m; f.key === "Backspace" ? !n.value[v] && v > 0 ? j(() => { var k; (k = i.value[v - 1]) == null || k.focus(); }) : (n.value[v] = "", b()) : f.key === "ArrowLeft" && v > 0 ? (f.preventDefault(), (r = i.value[v - 1]) == null || r.focus()) : f.key === "ArrowRight" && v < a.length - 1 && (f.preventDefault(), (m = i.value[v + 1]) == null || m.focus()); }, y = (v) => { var m; v.preventDefault(); const r = (((m = v.clipboardData) == null ? void 0 : m.getData("text")) || "").replace(/\D/g, "").slice(0, a.length); if (r) { const k = r.split(""); n.value = [...k, ...Array(a.length - k.length).fill("")], b(); const B = Math.min(k.length, a.length - 1); j(() => { var T; (T = i.value[B]) == null || T.focus(); }); } }, b = () => { const v = n.value.join(""); t("update:modelValue", v), v.length === a.length && t("complete", v); }; return J(() => { a.autoFocus && j(() => { var v; (v = i.value[0]) == null || v.focus(); }); }), (v, f) => (l(), o("div", { class: _(["tui-otp", { error: p.value }]) }, [ s("div", Ea, [ (l(!0), o(N, null, L(n.value, (r, m) => te((l(), o("input", { key: m, ref_for: !0, ref: (k) => i.value[m] = k, "onUpdate:modelValue": (k) => n.value[m] = k, type: "text", inputmode: "numeric", maxlength: "1", class: _(["otp-input", { filled: n.value[m] }]), "aria-label": `Digit ${m + 1}`, onInput: (k) => c(m, k), onKeydown: (k) => d(m, k), onPaste: y, disabled: e.disabled }, null, 42, Na)), [ [se, n.value[m]] ])), 128)) ]), e.error ? (l(), o("p", La, g(e.error), 1)) : h("", !0) ], 2)); } }, Ra = /* @__PURE__ */ D(za, [["__scopeId", "data-v-ca0fbb71"]]), Oa = { class: "tui-progress-wrapper" }, qa = { key: 0, class: "progress-header" }, Pa = { class: "progress-label" }, Ya = { class: "progress-value" }, Fa = { class: "progress-bar-container" }, Ua = { class: "progress-segments" }, Ha = { __name: "TuiProgressBar", props: { value: { type: Number, required: !0, validator: (e) => e >= 0 && e <= 100 }, label: { type: String, default: "" }, animated: { type: Boolean, default: !0 } }, setup(e) { return (u, a) => (l(), o("div", Oa, [ e.label ? (l(), o("div", qa, [ s("span", Pa, g(e.label), 1), s("span", Ya, g(e.value) + "%", 1) ])) : h("", !0), s("div", Fa, [ s("div", { class: "progress-bar", style: K({ width: e.value + "%" }) }, [ s("div", { class: _(["progress-fill", { animated: e.animated }]) }, null, 2) ], 4), s("div", Ua, [ (l(), o(N, null, L(20, (t) => s("span", { key: t, class: "segment" })), 64)) ]) ]) ])); } }, Ka = /* @__PURE__ */ D(Ha, [["__scopeId", "data-v-06bb074d"]]), Ga = { class: "tui-radio-group" }, Wa = { key: 0, class: "group-label" }, ja = ["value", "checked", "onChange"], Xa = { class: "radio-circle" }, Ja = { key: 0, class: "radio-dot" }, Qa = { key: 1, class: "radio-empty" }, Za = { class: "radio-label" }, el = { __name: "TuiRadio", props: { modelValue: { type: [String, Number], default: "" }, options: { type: Array, required: !0 }, groupLabel: { type: String, default: "" } }, emits: ["update:modelValue"], setup(e) { return (u, a) => (l(), o("div", Ga, [ e.groupLabel ? (l(), o("label", Wa, [ a[0] || (a[0] = s("span", { class: "label-bracket" }, ">", -1)), H(" " + g(e.groupLabel), 1) ])) : h("", !0), (l(!0), o(N, null, L(e.options, (t) => (l(), o("label", { key: t.value, class: "tui-radio" }, [ s("input", { type: "radio", value: t.value, checked: e.modelValue === t.value, onChange: (n) => u.$emit("update:modelValue", t.value), class: "radio-input" }, null, 40, ja), s("span", Xa, [ e.modelValue === t.value ? (l(), o("span", Ja, "●")) : (l(), o("span", Qa, "○")) ]), s("span", Za, g(t.label), 1) ]))), 128)) ])); } }, tl = /* @__PURE__ */ D(el, [["__scopeId", "data-v-75d211d9"]]), al = { key: 0, class: "tui-label" }, ll = ["onKeydown"], sl = { class: "select-display" }, nl = { key: 0, class: "dropdown-menu" }, ol = { class: "dropdown-inner" }, il = ["onClick", "onMouseenter"], rl = { class: "option-bracket" }, ul = { __name: "TuiSelect", props: { modelValue: { type: [String, Number], default: "" }, label: { type: String, default: "" }, options: { type: Array, required: !0 }, placeholder: { type: String, default: "SELECT OPTION" } }, emits: ["update:modelValue"], setup(e, { emit: u }) { const a = e, t = u, n = $(!1), i = $(-1), p = $(null), c = V(() => { if (!a.modelValue) return a.placeholder; const f = a.options.find((r) => r.value === a.modelValue); return f ? f.label : a.placeholder; }), d = () => { if (n.value = !n.value, n.value) { const f = a.options.findIndex((r) => r.value === a.modelValue); i.value = f >= 0 ? f : 0; } }, y = () => { n.value = !1, i.value = -1; }, b = (f) => { t("update:modelValue", f), y(); }, v = (f) => { if (!n.value) { n.value = !0, i.value = 0; return; } i.value += f, i.value < 0 ? i.value = a.options.length - 1 : i.value >= a.options.length && (i.value = 0), i.value >= 0 && i.value < a.options.length && t("update:modelValue", a.options[i.value].value); }; return G(() => a.modelValue, () => { if (n.value) { const f = a.options.findIndex((r) => r.value === a.modelValue); f >= 0 && (i.value = f); } }), (f, r) => (l(), o("div", { class: "tui-select-wrapper", ref_key: "selectWrapper", ref: p }, [ e.label ? (l(), o("label", al, [ r[2] || (r[2] = s("span", { class: "label-bracket" }, ">", -1)), H(" " + g(e.label), 1) ])) : h("", !0), s("div", { class: _(["select-container", { "is-open": n.value }]), onClick: d, tabindex: "0", onBlur: y, onKeydown: [ F(y, ["escape"]), F(U(d, ["prevent"]), ["enter"]), F(U(d, ["prevent"]), ["space"]), r[0] || (r[0] = F(U((m) => v(-1), ["prevent"]), ["up"])), r[1] || (r[1] = F(U((m) => v(1), ["prevent"]), ["down"])) ] }, [ r[3] || (r[3] = s("span", { class: "select-prompt" }, ">>", -1)), s("div", sl, g(c.value), 1), s("span", { class: _(["select-arrow", { "is-open": n.value }]) }, "▼", 2) ], 42, ll), ae(X,