super-vue3-tabs
Version:
A vue3 tabs component for showing tabs and tab content.
242 lines (241 loc) • 15.2 kB
JavaScript
(function(){"use strict";try{if(typeof document<"u"){var t=document.createElement("style");t.appendChild(document.createTextNode('*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.absolute{position:absolute}.relative{position:relative}.left-0{left:0}.right-0{right:0}.m-auto{margin:auto}.mb-1{margin-bottom:.25rem}.mb-4{margin-bottom:1rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.h-1{height:.25rem}.h-full{height:100%}.w-1{width:.25rem}.w-6{width:1.5rem}.min-w-max{min-width:-moz-max-content;min-width:max-content}.\\!cursor-default{cursor:default!important}.cursor-pointer{cursor:pointer}.items-center{align-items:center}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.rounded-lg{border-radius:.5rem}.rounded-sm{border-radius:.125rem}.border{border-width:1px}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.p-4{padding:1rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-semibold{font-weight:600}.opacity-50{opacity:.5}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.super-vue3-tabs .tabs{overflow-x:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none;position:relative}.super-vue3-tabs .tabs::-webkit-scrollbar{display:none}.super-vue3-tabs .tabs .underline-marker{position:absolute;bottom:0;left:0;height:3px;transition:left .3s ease;border-radius:16px}.super-vue3-tabs .dropdown{position:absolute;background-color:#f8f8f8;min-width:140px;max-height:300px;overflow:auto;box-shadow:0 4px 20px -2px #0000001a;z-index:1;border-radius:8px}.super-vue3-tabs .dropdown div{padding:8px 12px;margin:4px;text-decoration:none;display:block}.super-vue3-tabs .dropdown div:hover{background-color:#f1f1f1;border-radius:8px}')),document.head.appendChild(t)}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();
import { getCurrentScope as J, onScopeDispose as K, unref as P, ref as f, computed as C, watch as R, getCurrentInstance as Q, onMounted as Y, defineComponent as F, mergeModels as L, useModel as X, provide as W, onUnmounted as Z, openBlock as v, createElementBlock as h, createElementVNode as k, Fragment as I, renderList as S, normalizeClass as ee, normalizeStyle as A, createBlock as N, resolveDynamicComponent as O, createCommentVNode as E, createTextVNode as z, toDisplayString as j, renderSlot as H, inject as G, useSlots as te, onBeforeMount as oe, withDirectives as ne, vShow as le } from "vue";
const se = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='currentColor'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%20class='lucide%20lucide-ellipsis-vertical'%3e%3ccircle%20cx='12'%20cy='12'%20r='1'/%3e%3ccircle%20cx='12'%20cy='5'%20r='1'/%3e%3ccircle%20cx='12'%20cy='19'%20r='1'/%3e%3c/svg%3e";
function re(o) {
return J() ? (K(o), !0) : !1;
}
function U(o) {
return typeof o == "function" ? o() : P(o);
}
const ie = typeof window < "u" && typeof document < "u";
typeof WorkerGlobalScope < "u" && globalThis instanceof WorkerGlobalScope;
const ae = (o) => o != null, $ = () => {
};
function B(o) {
var s;
const a = U(o);
return (s = a == null ? void 0 : a.$el) != null ? s : a;
}
const q = ie ? window : void 0;
function ue() {
const o = f(!1), s = Q();
return s && Y(() => {
o.value = !0;
}, s), o;
}
function ce(o) {
const s = ue();
return C(() => (s.value, !!o()));
}
function de(o, s, a = {}) {
const {
root: b,
rootMargin: u = "0px",
threshold: l = 0.1,
window: d = q,
immediate: c = !0
} = a, t = ce(() => d && "IntersectionObserver" in d), w = C(() => {
const g = U(o);
return (Array.isArray(g) ? g : [g]).map(B).filter(ae);
});
let p = $;
const y = f(c), M = t.value ? R(
() => [w.value, B(b), y.value],
([g, V]) => {
if (p(), !y.value || !g.length)
return;
const _ = new IntersectionObserver(
s,
{
root: B(V),
rootMargin: u,
threshold: l
}
);
g.forEach((e) => e && _.observe(e)), p = () => {
_.disconnect(), p = $;
};
},
{ immediate: c, flush: "post" }
) : $, T = () => {
p(), M(), y.value = !1;
};
return re(T), {
isSupported: t,
isActive: y,
pause() {
p(), y.value = !1;
},
resume() {
y.value = !0;
},
stop: T
};
}
function ve(o, s = {}) {
const { window: a = q, scrollTarget: b, threshold: u = 0 } = s, l = f(!1);
return de(
o,
(d) => {
let c = l.value, t = 0;
for (const w of d)
w.time >= t && (t = w.time, c = w.isIntersecting);
l.value = c;
},
{
root: b,
window: a,
threshold: u
}
), l;
}
const fe = { class: "super-vue3-tabs" }, pe = { class: "flex gap-2" }, me = ["id", "onClick"], he = /* @__PURE__ */ k("img", {
src: se,
width: "16",
class: "m-auto"
}, null, -1), we = [
he
], ye = {
key: 0,
class: "dropdown"
}, be = ["onClick"], ge = { class: "content" }, xe = /* @__PURE__ */ F({
__name: "Tabs",
props: /* @__PURE__ */ L({
themeColor: { default: "#3b82f6" }
}, {
modelValue: { default: "" },
modelModifiers: {}
}),
emits: /* @__PURE__ */ L(["change"], ["update:modelValue"]),
setup(o, { emit: s }) {
const a = o, b = s, u = f(null), l = f([]), d = f({ id: "", value: "" }), c = X(o, "modelValue"), t = f([]), w = f({}), p = f(!1), y = () => {
for (let e in t.value) {
const r = ve(
t.value[e]
);
w.value[l.value[e].id] = r;
}
}, M = C(() => l.value.filter((e) => !w.value[e.id])), T = C(() => {
var m, i;
const e = l.value.findIndex(
(x) => x.id === d.value.id
), r = t.value[e];
return r ? { width: ((m = r == null ? void 0 : r.parentElement) == null ? void 0 : m.offsetWidth) + "px", left: ((i = r == null ? void 0 : r.parentElement) == null ? void 0 : i.offsetLeft) + "px" } : { width: "0px", left: "0px" };
});
W("addTabs", (e) => {
l.value.push(e);
}), W("activeTab", d), R(t.value, y);
const V = function(e) {
e.deltaY == 0 || !u.value || (e.preventDefault(), u.value.scrollLeft += e.deltaY);
}, _ = ({ tab: e, tabValue: r }) => {
var x;
if (!e && r && (e = l.value.find((D) => D.value === r)), !e)
return;
p.value = !1;
const n = e.id, m = l.value.findIndex((D) => D.id === n), i = t.value[m];
i && ((x = i == null ? void 0 : i.parentElement) == null || x.scrollIntoView({
behavior: "smooth",
block: "nearest"
})), d.value = e, c.value = e.value, b("change", e);
};
return Y(() => {
var e;
if ((e = u.value) == null || e.addEventListener("wheel", V), !!l.value.length) {
if (c.value)
return _({ tabValue: c.value });
_({ tab: l.value[0] });
}
}), Z(() => {
var e;
(e = u.value) == null || e.removeEventListener("wheel", V);
}), (e, r) => (v(), h("div", fe, [
k("div", pe, [
k("div", {
class: "flex gap-3 tabs",
ref_key: "tabsContainerRef",
ref: u
}, [
(v(!0), h(I, null, S(l.value, (n, m) => (v(), h("div", {
key: m,
id: n.id,
class: ee(["relative flex items-center px-3 py-2 rounded-sm cursor-pointer min-w-max", {
"opacity-50 !cursor-default": n.disabled
}]),
style: A({
color: d.value.id === n.id ? a.themeColor : "",
borderBottomColor: d.value.id === n.id ? a.themeColor : ""
}),
onClick: (i) => n.disabled ? "" : _({ tab: n })
}, [
k("div", {
class: "absolute left-0 right-0 w-1 h-1 m-auto tracker-element",
ref_for: !0,
ref: (i) => {
t.value[m] = i;
}
}, null, 512),
n.icon ? (v(!0), h(I, { key: 0 }, S(n.icon(), (i, x) => (v(), N(O(i), { key: x }))), 128)) : E("", !0),
z(" " + j(n.value), 1)
], 14, me))), 128)),
k("div", {
class: "underline-marker",
style: A({
width: T.value.width,
left: T.value.left,
backgroundColor: a.themeColor
})
}, null, 4)
], 512),
M.value.length ? (v(), h("div", {
key: 0,
onMouseleave: r[1] || (r[1] = (n) => p.value = !1)
}, [
k("button", {
class: "w-6 h-full",
onMouseover: r[0] || (r[0] = (n) => p.value = !0)
}, we, 32),
p.value ? (v(), h("div", ye, [
(v(!0), h(I, null, S(M.value, (n) => (v(), h("div", {
key: n.id,
onClick: (m) => _({ tab: n }),
class: "cursor-pointer"
}, [
n.icon ? (v(!0), h(I, { key: 0 }, S(n.icon(), (m, i) => (v(), N(O(m), { key: i }))), 128)) : E("", !0),
z(" " + j(n.value), 1)
], 8, be))), 128))
])) : E("", !0)
], 32)) : E("", !0)
]),
k("div", ge, [
H(e.$slots, "default")
])
]));
}
}), _e = { class: "mt-4" }, Ce = /* @__PURE__ */ F({
__name: "Tab",
props: {
id: {},
value: {},
disabled: { type: Boolean }
},
setup(o) {
const s = o, a = f({}), b = G("addTabs", (t) => {
console.log(t);
}), u = G("activeTab", f({ id: "", value: "" })), l = C(() => s.id || s.value.toLowerCase().replace(/ /g, "-") + "_" + Math.floor(Math.random() * 11)), d = C(() => {
var t;
return ((t = u == null ? void 0 : u.value) == null ? void 0 : t.id) === l.value;
}), c = te();
return oe(() => {
let t = { ...s, icon: c == null ? void 0 : c.icon };
t.id || (t.id = l.value), a.value = t, b(t);
}), (t, w) => ne((v(), h("div", _e, [
H(t.$slots, "default")
], 512)), [
[le, d.value]
]);
}
});
export {
Ce as Tab,
xe as Tabs
};