vue-smart-ui
Version:
A collection of Vue 3 smart and highly customizable UI components for modern web applications
1,633 lines (1,632 loc) • 47 kB
JavaScript
import { computed as S, ref as $, provide as ie, createElementBlock as d, openBlock as r, unref as q, normalizeClass as _, renderSlot as B, inject as re, onMounted as A, onUnmounted as U, watch as W, createElementVNode as p, createCommentVNode as b, createTextVNode as X, toDisplayString as T, normalizeStyle as N, Fragment as j, nextTick as ue, createVNode as le, Transition as de, withCtx as ne, withDirectives as ce, vShow as fe, useSlots as me, createBlock as Z, Teleport as ve, withModifiers as Y, renderList as J, resolveDynamicComponent as pe, createApp as ye, h as ge, TransitionGroup as be, mergeProps as he } from "vue";
let ee = 0;
function P(e = "base", f) {
const t = () => (ee++, `${e}-${ee}`);
return {
autoId: S(() => f.id || t())
};
}
const ke = ["id"], we = {
__name: "BaseAccordion",
props: {
id: {
type: String,
default: ""
},
multiple: {
type: Boolean,
default: !1
},
variant: {
type: String,
default: "default",
validator: (e) => ["default", "bordered", "minimal"].includes(e)
}
},
setup(e) {
const f = e, { autoId: t } = P("accordion", f), l = $([]);
return ie("accordion", {
activeItems: l,
toggleItem: (a) => {
if (f.multiple) {
const c = l.value.indexOf(a);
c === -1 ? l.value.push(a) : l.value.splice(c, 1);
} else
l.value = l.value.includes(a) ? [] : [a];
},
variant: f.variant
}), (a, c) => (r(), d("div", {
class: _(["vsui base-accordion", `base-accordion--${e.variant}`]),
id: q(t)
}, [
B(a.$slots, "default")
], 10, ke));
}
}, $e = ["disabled", "aria-expanded"], xe = { class: "base-accordion-item__body" }, Be = {
__name: "BaseAccordionItem",
props: {
title: {
type: String,
required: !0
},
disabled: {
type: Boolean,
default: !1
}
},
setup(e) {
const f = e, t = re("accordion"), l = $(Symbol()), o = $("0px"), a = $(null), c = S(() => t.activeItems.value.includes(l.value)), i = S(() => t.variant), u = () => {
f.disabled || t.toggleItem(l.value);
}, y = () => {
a.value && (o.value = c.value ? `${a.value.scrollHeight}px` : "0px");
}, V = new ResizeObserver(y);
return A(() => {
a.value && (V.observe(a.value), y());
}), U(() => {
V.disconnect();
}), W(c, y), (h, x) => (r(), d("div", {
class: _(["vsui base-accordion-item", [
`base-accordion-item--${i.value}`,
{
"base-accordion-item--active": c.value,
"base-accordion-item--disabled": e.disabled
}
]])
}, [
p("button", {
class: "base-accordion-item__header",
onClick: u,
disabled: e.disabled,
"aria-expanded": c.value
}, [
h.$slots.icon ? B(h.$slots, "icon", { key: 0 }) : b("", !0),
B(h.$slots, "title", {}, () => [
X(T(e.title), 1)
]),
B(h.$slots, "chevron", {}, () => [
x[0] || (x[0] = p("svg", {
class: "base-accordion-item__chevron",
viewBox: "0 0 24 24",
width: "1.2em",
height: "1.2em"
}, [
p("path", {
fill: "currentColor",
d: "M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"
})
], -1))
])
], 8, $e),
p("div", {
class: "base-accordion-item__content",
ref_key: "contentRef",
ref: a,
style: N({ height: o.value })
}, [
p("div", xe, [
B(h.$slots, "default")
])
], 4)
], 2));
}
}, Se = ["id", "disabled"], Ve = {
key: 0,
class: "spinner"
}, _e = {
key: 0,
class: "spinner"
}, Ie = {
key: 3,
class: "spinner"
}, Ce = {
__name: "BaseButton",
props: {
id: {
type: String,
default: ""
},
type: {
type: String,
default: "button",
validator: (e) => ["button", "submit", "reset"].includes(e)
},
variant: {
type: String,
default: "primary",
validator: (e) => ["primary", "secondary", "gray", "outline", "ghost"].includes(e)
},
size: {
type: String,
default: "medium",
validator: (e) => ["small", "medium", "large", "auto"].includes(e)
},
block: {
type: Boolean,
default: !1
},
disabled: {
type: Boolean,
default: !1
},
loading: {
type: Boolean,
default: !1
},
iconOnly: {
type: Boolean,
default: !1
}
},
emits: ["click"],
setup(e) {
const f = e, { autoId: t } = P("button", f);
return (l, o) => (r(), d("button", {
id: q(t),
class: _(["vsui base-button", [
`base-button--${e.variant}`,
`base-button--${e.size}`,
{
"base-button--block": e.block,
"base-button--disabled": e.disabled || e.loading,
"base-button--icon-only": e.iconOnly
}
]]),
disabled: e.disabled || e.loading,
onClick: o[0] || (o[0] = (a) => l.$emit("click", a))
}, [
l.$slots.prefix ? (r(), d(j, { key: 0 }, [
e.loading ? (r(), d("div", Ve)) : B(l.$slots, "prefix", { key: 1 })
], 64)) : b("", !0),
e.iconOnly ? b("", !0) : B(l.$slots, "default", { key: 1 }),
l.$slots.suffix ? (r(), d(j, { key: 2 }, [
e.loading ? (r(), d("div", _e)) : B(l.$slots, "suffix", { key: 1 })
], 64)) : b("", !0),
e.loading && !l.$slots.prefix && !l.$slots.suffix ? (r(), d("div", Ie)) : b("", !0)
], 10, Se));
}
}, Te = ["id", "checked", "disabled", "indeterminate"], Me = { class: "base-checkbox__checkmark" }, Ee = {
key: 0,
viewBox: "0 0 14 14",
fill: "none",
xmlns: "http://www.w3.org/2000/svg"
}, Re = {
key: 1,
viewBox: "0 0 14 14",
fill: "none",
xmlns: "http://www.w3.org/2000/svg"
}, qe = {
key: 0,
class: "base-checkbox__label"
}, Le = {
__name: "BaseCheckbox",
props: {
id: {
type: String,
default: ""
},
modelValue: {
type: [Boolean, Array],
default: !1
},
value: {
type: [String, Number, Boolean, Object],
default: null
},
label: {
type: String,
default: ""
},
size: {
type: String,
default: "medium",
validator: (e) => ["small", "medium", "large"].includes(e)
},
disabled: {
type: Boolean,
default: !1
},
error: {
type: Boolean,
default: !1
},
indeterminate: {
type: Boolean,
default: !1
}
},
emits: ["update:modelValue"],
setup(e, { emit: f }) {
const t = e, { autoId: l } = P("checkbox", t), o = f, a = S(() => Array.isArray(t.modelValue) ? t.modelValue.includes(t.value) : t.modelValue), c = (i) => {
if (Array.isArray(t.modelValue)) {
const u = [...t.modelValue];
if (i.target.checked)
u.push(t.value);
else {
const y = u.indexOf(t.value);
y > -1 && u.splice(y, 1);
}
o("update:modelValue", u);
} else
o("update:modelValue", i.target.checked);
};
return (i, u) => (r(), d("label", {
class: _([
"vsui base-checkbox",
`base-checkbox--${e.size}`,
{
"base-checkbox--disabled": e.disabled,
"base-checkbox--error": e.error
}
])
}, [
p("input", {
id: q(l),
type: "checkbox",
checked: a.value,
disabled: e.disabled,
indeterminate: e.indeterminate,
class: "base-checkbox__input",
onChange: c
}, null, 40, Te),
p("span", Me, [
B(i.$slots, "checkmark", {}, () => [
a.value && !e.indeterminate ? (r(), d("svg", Ee, u[0] || (u[0] = [
p("path", {
d: "M11.6666 3.5L5.24992 9.91667L2.33325 7",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
}, null, -1)
]))) : b("", !0),
e.indeterminate ? (r(), d("svg", Re, u[1] || (u[1] = [
p("path", {
d: "M2.91675 7H11.0834",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
}, null, -1)
]))) : b("", !0)
])
]),
i.$slots.default || e.label ? (r(), d("span", qe, [
B(i.$slots, "default", {}, () => [
X(T(e.label), 1)
])
])) : b("", !0)
], 2));
}
}, Oe = ["id"], Ae = {
__name: "BaseDropdown",
props: {
id: {
type: String,
default: ""
},
modelValue: {
type: Boolean,
default: !1
},
variant: {
type: String,
default: "default",
validator: (e) => ["default", "white", "dark"].includes(e)
},
width: {
type: String,
default: "auto"
},
closeOnClick: {
type: Boolean,
default: !0
},
closeOnClickOutside: {
type: Boolean,
default: !0
}
},
emits: ["update:modelValue"],
setup(e, { emit: f }) {
const t = e, { autoId: l } = P("dropdown", t), o = f, a = $(null), c = $(null), i = $(t.modelValue), u = () => {
if (!c.value || !a.value) return;
const h = c.value.getBoundingClientRect(), x = a.value.getBoundingClientRect(), I = {
width: window.innerWidth,
height: window.innerHeight
};
c.value.style.top = "100%", c.value.style.bottom = "auto", c.value.style.left = "auto", c.value.style.right = "0", x.right + h.width > I.width && (c.value.style.right = "0", c.value.style.left = "auto"), x.right - h.width < 0 && (c.value.style.left = "0", c.value.style.right = "auto"), x.bottom + h.height > I.height && (c.value.style.bottom = "100%", c.value.style.top = "auto", c.value.style.marginTop = "0", c.value.style.marginBottom = "0.5rem");
};
W(
() => t.modelValue,
(h) => {
i.value = h, h ? (document.addEventListener("click", y), ue(() => {
u();
})) : document.removeEventListener("click", y);
}
);
const y = (h) => {
t.closeOnClickOutside && a.value && !a.value.contains(h.target) && o("update:modelValue", !1);
}, V = (h) => {
t.closeOnClick && !h.target.closest("[data-prevent-close]") && o("update:modelValue", !1);
};
return A(() => {
t.modelValue && document.addEventListener("click", y), window.addEventListener("scroll", u, !0), window.addEventListener("resize", u);
}), U(() => {
document.removeEventListener("click", y), window.removeEventListener("scroll", u, !0), window.removeEventListener("resize", u);
}), (h, x) => (r(), d("div", {
ref_key: "dropdownRef",
ref: a,
class: "vsui base-dropdown",
id: q(l)
}, [
p("div", {
class: "base-dropdown__trigger",
onClick: x[0] || (x[0] = (I) => o("update:modelValue", !e.modelValue))
}, [
B(h.$slots, "trigger")
]),
le(de, { name: "dropdown" }, {
default: ne(() => [
ce(p("div", {
ref_key: "menuRef",
ref: c,
class: _(["base-dropdown__menu", `base-dropdown__menu--${e.variant}`]),
style: N({ width: e.width }),
onClick: V
}, [
B(h.$slots, "default")
], 6), [
[fe, i.value]
])
]),
_: 3
})
], 8, Oe));
}
}, ze = { class: "vsui infinite-scroll" }, Fe = { class: "infinite-scroll__loader" }, Ne = { key: 0 }, je = {
key: 0,
class: "infinite-scroll__end"
}, Pe = {
__name: "BaseInfiniteScroll",
props: {
loading: {
type: Boolean,
default: !1
},
disabled: {
type: Boolean,
default: !1
},
threshold: {
type: Number,
default: 20
// pixels before the end to trigger
},
container: {
type: String,
default: null
// If null, uses window
},
loadingText: {
type: String,
default: "Loading more items..."
},
endText: {
type: String,
default: "There are no more items to load"
}
},
emits: ["load-more"],
setup(e, { emit: f }) {
const t = e, l = f, o = $(null), a = $(null), c = () => {
o.value && o.value.disconnect(), o.value = new IntersectionObserver(
(i) => {
i[0].isIntersecting && !t.loading && !t.disabled && l("load-more");
},
{
threshold: 0,
root: t.container ? document.querySelector(t.container) : null,
rootMargin: `0px 0px ${t.threshold}px 0px`
}
), a.value && o.value.observe(a.value);
};
return W(
() => t.loading,
(i, u) => {
u === !0 && i === !1 && setTimeout(() => {
c();
}, 100);
}
), A(() => {
c();
}), U(() => {
o.value && o.value.disconnect();
}), (i, u) => (r(), d("div", ze, [
B(i.$slots, "default"),
p("div", {
ref_key: "bottomElement",
ref: a,
class: "infinite-scroll__trigger"
}, [
e.loading ? B(i.$slots, "loading", { key: 0 }, () => [
p("div", Fe, [
u[0] || (u[0] = p("div", { class: "spinner" }, null, -1)),
e.loadingText ? (r(), d("span", Ne, T(e.loadingText), 1)) : b("", !0)
])
]) : e.disabled ? B(i.$slots, "disabled", { key: 1 }, () => [
e.endText ? (r(), d("div", je, T(e.endText), 1)) : b("", !0)
]) : b("", !0)
], 512)
]));
}
}, De = {
key: 0,
class: "base-input__label"
}, He = {
key: 0,
class: "base-input__required",
"aria-hidden": "true"
}, Ke = { class: "base-input__wrapper" }, We = {
key: 0,
class: "base-input__prefix"
}, Ue = ["id", "type", "value", "placeholder", "disabled", "readonly", "required", "aria-required", "maxlength"], Xe = {
key: 1,
class: "base-input__suffix"
}, Ge = {
__name: "BaseInput",
props: {
id: {
type: String,
default: ""
},
modelValue: {
type: [String, Number],
default: ""
},
variant: {
type: String,
default: "default",
validator: (e) => ["default", "filled", "outlined"].includes(e)
},
state: {
type: String,
default: null,
validator: (e) => ["success", "error", "warning"].includes(e)
},
type: {
type: String,
default: "text"
},
label: {
type: String,
default: null
},
placeholder: {
type: String,
default: ""
},
disabled: {
type: Boolean,
default: !1
},
readonly: {
type: Boolean,
default: !1
},
required: {
type: Boolean,
default: !1
},
helperText: {
type: String,
default: null
},
errorMessage: {
type: String,
default: null
},
prefixIcon: {
type: String,
default: null
},
suffixIcon: {
type: String,
default: null
},
rules: {
type: Array,
default: () => []
},
validateOnBlur: {
type: Boolean,
default: !0
},
validateOnInput: {
type: Boolean,
default: !1
},
name: {
type: String,
default: ""
},
mask: {
type: [String, Object],
default: null
}
},
emits: ["update:modelValue", "focus", "blur", "input", "validation", "mounted"],
setup(e, { emit: f }) {
const t = me(), l = e, { autoId: o } = P("input", l), a = f, c = $(null), i = $(!1), u = $(""), y = S(() => ({
"vsui base-input": !0,
[`base-input--${l.variant}`]: !0,
[`base-input--${s.value}`]: s.value,
"base-input--disabled": l.disabled,
"base-input--focused": i.value,
"base-input--with-prefix": l.prefixIcon || t.prefix,
"base-input--with-suffix": l.suffixIcon || t.suffix
})), V = {
required: (n) => ({
valid: !!(n != null && n.toString().trim()),
message: "This field is required"
}),
email: (n) => ({
valid: !n || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(n),
message: "Please enter a valid email"
}),
min: (n, m) => ({
valid: !n || n.length >= m,
message: `Must be at least ${m} characters`
}),
max: (n, m) => ({
valid: !n || n.length <= m,
message: `Must be no more than ${m} characters`
}),
pattern: (n, m) => ({
valid: !n || new RegExp(m).test(n),
message: "Invalid format"
})
}, h = (n) => {
if (!l.rules.length) return !0;
for (const m of l.rules) {
if (typeof m == "string") {
const C = V[m];
if (C) {
const F = C(n);
if (!F.valid)
return u.value = F.message, !1;
}
continue;
}
if (typeof m == "object") {
const [C, F] = Object.entries(m)[0], D = V[C];
if (D) {
const O = D(n, F);
if (!O.valid)
return u.value = m.message || O.message, !1;
}
if (typeof m.validator == "function" && !m.validator(n))
return u.value = m.message || "Invalid value", !1;
}
}
return u.value = "", !0;
}, x = S({
get: () => l.mask === "currency" && l.modelValue ? I.currency.format(l.modelValue) : l.modelValue,
set: (n) => a("update:modelValue", n)
}), I = {
phone: {
patterns: ["(##) ####-####", "(##) #####-####"],
match: (n) => n.replace(/\D/g, "").length <= 10 ? 0 : 1
},
currency: {
pattern: "currency",
format: (n) => {
if (!n) return "";
const m = typeof n == "string" ? parseFloat(n.replace(/\D/g, "")) / 100 : n;
return new Intl.NumberFormat("pt-BR", {
style: "currency",
currency: "BRL",
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(m);
},
parse: (n) => {
const m = n.replace(/[^\d]/g, "");
return parseFloat(m) / 100;
}
},
date: "##/##/####",
cpf: "###.###.###-##",
cnpj: "##.###.###/####-##",
cep: "#####-###"
}, M = (n, m) => {
if (!n) return n;
if (m === "currency" || m.pattern === "currency") {
const C = I.currency.parse(n);
return I.currency.format(C);
}
if (typeof m == "string")
return L(n, m);
if (m.patterns) {
const C = m.match(n);
return L(n, m.patterns[C]);
}
return n;
}, L = (n, m) => {
if (!m) return n;
const F = n.replace(/\D/g, "").split("");
let D = "", O = 0;
for (let K = 0; K < m.length && F[K]; K++)
m[O] === "#" ? (D += F[K], O++) : (D += m[O], O++, K--);
return D;
}, H = (n) => {
let m = n.target.value;
if (l.mask) {
const C = typeof l.mask == "string" ? I[l.mask] || l.mask : l.mask.pattern;
m = M(m, C), c.value && (c.value.value = m);
}
if (l.mask === "currency") {
const C = I.currency.parse(m);
x.value = C, a("update:modelValue", C);
} else
x.value = m, a("update:modelValue", m);
if (a("input", { ...n, target: { ...n.target, value: m } }), l.validateOnInput) {
const C = h(x.value);
a("validation", { valid: C, error: u.value });
}
}, k = (n) => {
i.value = !0, a("focus", n);
}, w = (n) => {
if (i.value = !1, a("blur", n), l.validateOnBlur) {
const m = h(x.value);
a("validation", { valid: m, error: u.value });
}
}, g = () => {
var n;
(n = c.value) == null || n.focus();
}, s = S(() => u.value ? "error" : l.state), v = S(() => u.value ? u.value : l.errorMessage || l.helperText), E = () => {
const n = h(x.value);
return a("validation", { valid: n, error: u.value, name: l.name }), n;
}, R = S(() => l.required ? !0 : l.rules.some((n) => n === "required" ? !0 : typeof n == "object" ? n.required || Object.keys(n)[0] === "required" : !1)), z = S(() => {
if (!l.mask) return;
const n = typeof l.mask == "string" ? I[l.mask] || l.mask : l.mask.pattern;
if (typeof n == "string")
return n.length;
if (n.patterns)
return Math.max(...n.patterns.map((m) => m.length));
});
return A(() => {
a("mounted", {
validate: E,
focus: g
});
}), (n, m) => (r(), d("div", {
class: _(y.value)
}, [
e.label ? (r(), d("label", De, [
X(T(e.label) + " ", 1),
R.value ? (r(), d("span", He, "*")) : b("", !0)
])) : b("", !0),
p("div", Ke, [
n.$slots.prefix || e.prefixIcon ? (r(), d("div", We, [
B(n.$slots, "prefix", {}, () => [
p("i", {
class: _(e.prefixIcon)
}, null, 2)
])
])) : b("", !0),
p("input", {
id: q(o),
ref_key: "inputRef",
ref: c,
type: e.type,
value: x.value,
placeholder: e.placeholder,
disabled: e.disabled,
readonly: e.readonly,
required: R.value,
"aria-required": R.value,
maxlength: z.value,
class: "base-input__field",
onInput: H,
onFocus: k,
onBlur: w
}, null, 40, Ue),
n.$slots.suffix || e.suffixIcon ? (r(), d("div", Xe, [
B(n.$slots, "suffix", {}, () => [
p("i", {
class: _(e.suffixIcon)
}, null, 2)
])
])) : b("", !0)
]),
v.value ? (r(), d("div", {
key: 1,
class: _(["base-input__helper", { "base-input__helper--error": u.value }])
}, T(v.value), 3)) : b("", !0)
], 2));
}
}, Je = {
key: 0,
class: "base-popup__header"
}, Qe = { class: "base-popup__content" }, Ye = {
key: 1,
class: "base-popup__footer"
}, Ze = {
__name: "BasePopup",
props: {
modelValue: {
type: Boolean,
default: !1
},
variant: {
type: String,
default: "default",
validator: (e) => ["default", "info", "success", "warning", "error"].includes(e)
},
size: {
type: String,
default: "medium",
validator: (e) => ["small", "medium", "large"].includes(e)
},
position: {
type: String,
default: "center",
validator: (e) => ["center", "top", "bottom", "left", "right"].includes(e)
},
disableClickOutside: {
type: Boolean,
default: !1
},
closeOnEsc: {
type: Boolean,
default: !0
}
},
emits: ["update:modelValue", "close"],
setup(e, { emit: f }) {
const t = e, l = f, o = $(null), a = (i) => {
!t.disableClickOutside && o.value && !o.value.contains(i.target) && (i.target.closest(".base-popup") || (l("update:modelValue", !1), l("close")));
}, c = (i) => {
t.closeOnEsc && i.key === "Escape" && (l("update:modelValue", !1), l("close"));
};
return A(() => {
document.addEventListener("mousedown", a), document.addEventListener("keydown", c);
}), U(() => {
document.removeEventListener("mousedown", a), document.removeEventListener("keydown", c);
}), (i, u) => (r(), Z(ve, { to: "body" }, [
e.modelValue ? (r(), d("div", {
key: 0,
class: _(["vsui base-popup-overlay", [`base-popup-overlay--${e.position}`]])
}, [
p("div", {
ref_key: "popupRef",
ref: o,
class: _(["base-popup", [`base-popup--${e.variant}`, `base-popup--${e.size}`, `base-popup--${e.position}`]])
}, [
i.$slots.header ? (r(), d("div", Je, [
B(i.$slots, "header")
])) : b("", !0),
p("div", Qe, [
B(i.$slots, "default")
]),
i.$slots.footer ? (r(), d("div", Ye, [
B(i.$slots, "footer")
])) : b("", !0),
i.$slots.close ? (r(), d("button", {
key: 2,
class: "base-popup__close",
onClick: u[0] || (u[0] = (y) => i.$emit("update:modelValue", !1))
}, [
B(i.$slots, "close")
])) : b("", !0)
], 2)
], 2)) : b("", !0)
]));
}
}, et = {
__name: "BaseSkeleton",
props: {
variant: {
type: String,
default: "rectangle",
validator: (e) => ["rectangle", "circle", "text", "heading", "button"].includes(e)
},
width: {
type: String,
default: "100%"
},
height: {
type: String,
default: null
},
animated: {
type: Boolean,
default: !0
},
rounded: {
type: Boolean,
default: !1
}
},
setup(e) {
return (f, t) => (r(), d("div", {
class: _(["vsui base-skeleton", [
`base-skeleton--${e.variant}`,
{
"base-skeleton--animated": e.animated,
"base-skeleton--rounded": e.rounded
}
]]),
style: N({
width: e.width,
height: e.height || null
})
}, [
B(f.$slots, "default")
], 6));
}
}, tt = ["for"], at = {
key: 0,
class: "base-slider__required"
}, lt = { class: "base-slider__container" }, nt = { class: "base-slider__extremity-value base-slider__extremity-value--min" }, st = {
key: 0,
class: "base-slider__mark-label"
}, ot = ["onMousedown", "onTouchstart", "onKeydown", "aria-valuemin", "aria-valuemax", "aria-valuenow", "aria-valuetext", "aria-disabled"], it = {
key: 0,
class: "base-slider__thumb-value"
}, rt = { class: "base-slider__extremity-value base-slider__extremity-value--max" }, ut = {
key: 1,
class: "base-slider__helper"
}, dt = {
__name: "BaseSlider",
props: {
id: {
type: String,
default: ""
},
modelValue: {
type: [Number, Array],
default: 0
},
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
},
step: {
type: Number,
default: 1
},
label: {
type: String,
default: null
},
disabled: {
type: Boolean,
default: !1
},
required: {
type: Boolean,
default: !1
},
helperText: {
type: String,
default: null
},
errorMessage: {
type: String,
default: null
},
state: {
type: String,
default: null,
validator: (e) => ["success", "error", "warning"].includes(e)
},
showValue: {
type: Boolean,
default: !0
},
range: {
type: Boolean,
default: !1
},
variant: {
type: String,
default: "default",
validator: (e) => ["default", "filled"].includes(e)
},
marks: {
type: Array,
default: () => []
},
formatValue: {
type: Function,
default: null
}
},
emits: ["update:modelValue", "change", "mounted"],
setup(e, { emit: f }) {
const t = e, l = f, { autoId: o } = P("slider", t), a = $(t.modelValue), c = $(!1), i = $(null), u = $([]), y = S(() => t.range && Array.isArray(t.modelValue)), V = S(() => t.formatValue ? y.value ? a.value.map((k) => t.formatValue(k)) : t.formatValue(a.value) : a.value), h = S(() => {
if (y.value) {
const [k, w] = a.value, g = (k - t.min) / (t.max - t.min) * 100, s = (w - t.min) / (t.max - t.min) * 100;
return {
left: `${g}%`,
width: `${s - g}%`
};
} else
return {
width: `${(a.value - t.min) / (t.max - t.min) * 100}%`
};
}), x = S(() => y.value ? a.value.map((k) => `${(k - t.min) / (t.max - t.min) * 100}%`) : [`${(a.value - t.min) / (t.max - t.min) * 100}%`]), I = S(() => ({
"base-slider--disabled": t.disabled,
"base-slider--success": t.state === "success",
"base-slider--error": t.state === "error",
"base-slider--warning": t.state === "warning",
"base-slider--filled": t.variant === "filled"
}));
W(
() => t.modelValue,
(k) => {
a.value = k;
}
), W(a, (k) => {
l("update:modelValue", k);
});
const M = (k, w = 0) => {
if (t.disabled) return;
const g = i.value.getBoundingClientRect(), s = k.clientX - g.left, v = Math.min(Math.max(s / g.width, 0), 1), E = t.min + v * (t.max - t.min), R = Math.round(E / t.step) * t.step, z = Math.min(Math.max(R, t.min), t.max);
if (y.value) {
const n = [...a.value];
n[w] = z, w === 0 && n[0] > n[1] ? n[0] = n[1] : w === 1 && n[1] < n[0] && (n[1] = n[0]), a.value = n;
} else
a.value = z;
l("change", a.value);
}, L = (k, w = 0) => {
if (t.disabled) return;
c.value = !0, M(k, w);
const g = (v) => M(v, w), s = () => {
c.value = !1, document.removeEventListener("mousemove", g), document.removeEventListener("mouseup", s), document.removeEventListener("touchmove", g), document.removeEventListener("touchend", s);
};
document.addEventListener("mousemove", g), document.addEventListener("mouseup", s), document.addEventListener("touchmove", g), document.addEventListener("touchend", s);
}, H = (k, w = 0) => {
if (t.disabled) return;
const g = y.value ? a.value[w] : a.value;
let s = g;
switch (k.key) {
case "ArrowRight":
case "ArrowUp":
s = Math.min(g + t.step, t.max);
break;
case "ArrowLeft":
case "ArrowDown":
s = Math.max(g - t.step, t.min);
break;
case "Home":
s = t.min;
break;
case "End":
s = t.max;
break;
default:
return;
}
if (y.value) {
const v = [...a.value];
v[w] = s, w === 0 && v[0] > v[1] ? v[0] = v[1] : w === 1 && v[1] < v[0] && (v[1] = v[0]), a.value = v;
} else
a.value = s;
l("change", a.value), k.preventDefault();
};
return A(() => {
y.value && (!Array.isArray(a.value) || a.value.length !== 2) ? a.value = [t.min, t.max] : !y.value && Array.isArray(a.value) && (a.value = t.min), l("mounted", {
id: o.value,
getValue: () => a.value,
setValue: (k) => {
a.value = k;
}
});
}), (k, w) => (r(), d("div", {
class: _(["vsui base-slider", I.value])
}, [
e.label ? (r(), d("label", {
key: 0,
for: q(o),
class: "base-slider__label"
}, [
X(T(e.label) + " ", 1),
e.required ? (r(), d("span", at, "*")) : b("", !0)
], 8, tt)) : b("", !0),
p("div", lt, [
p("div", nt, T(e.formatValue ? e.formatValue(e.min) : e.min), 1),
p("div", {
ref_key: "sliderTrack",
ref: i,
class: "base-slider__track",
onMousedown: w[0] || (w[0] = (g) => M(g)),
onTouchstart: w[1] || (w[1] = Y((g) => M(g.touches[0]), ["prevent"]))
}, [
p("div", {
class: "base-slider__track-fill",
style: N(h.value)
}, null, 4),
(r(!0), d(j, null, J(e.marks, (g) => (r(), d("div", {
key: g.value,
class: _(["base-slider__mark", {
"base-slider__mark--active": y.value ? g.value >= a.value[0] && g.value <= a.value[1] : g.value <= a.value
}]),
style: N({ left: `calc(${(g.value - e.min) / (e.max - e.min) * 100}%)` })
}, [
w[2] || (w[2] = p("div", { class: "base-slider__mark-dot" }, null, -1)),
g.label ? (r(), d("div", st, T(g.label), 1)) : b("", !0)
], 6))), 128)),
(r(!0), d(j, null, J(x.value, (g, s) => (r(), d("div", {
key: s,
ref_for: !0,
ref_key: "thumbRefs",
ref: u,
class: "base-slider__thumb",
style: N({ left: g }),
onMousedown: Y((v) => L(v, s), ["stop"]),
onTouchstart: Y((v) => L(v.touches[0], s), ["stop", "prevent"]),
onKeydown: (v) => H(v, s),
tabindex: "0",
role: "slider",
"aria-valuemin": e.min,
"aria-valuemax": e.max,
"aria-valuenow": y.value ? a.value[s] : a.value,
"aria-valuetext": y.value ? V.value[s] : V.value,
"aria-disabled": e.disabled
}, [
e.showValue ? (r(), d("div", it, T(y.value ? V.value[s] : V.value), 1)) : b("", !0)
], 44, ot))), 128))
], 544),
p("div", rt, T(e.formatValue ? e.formatValue(e.max) : e.max), 1)
]),
e.helperText || e.errorMessage ? (r(), d("div", ut, T(e.errorMessage || e.helperText), 1)) : b("", !0)
], 2));
}
}, ct = {
key: 0,
class: "base-textarea__label"
}, ft = {
key: 0,
class: "base-textarea__required",
"aria-hidden": "true"
}, mt = { class: "base-textarea__wrapper" }, vt = ["id", "value", "rows", "placeholder", "disabled", "readonly", "required", "aria-required"], pt = {
__name: "BaseTextarea",
props: {
id: {
type: String,
default: ""
},
modelValue: {
type: String,
default: ""
},
variant: {
type: String,
default: "default",
validator: (e) => ["default", "filled", "outlined"].includes(e)
},
state: {
type: String,
default: null,
validator: (e) => ["success", "error", "warning"].includes(e)
},
label: {
type: String,
default: null
},
placeholder: {
type: String,
default: ""
},
rows: {
type: [String, Number],
default: 3
},
maxRows: {
type: [String, Number],
default: null
},
disabled: {
type: Boolean,
default: !1
},
block: {
type: Boolean,
default: !1
},
readonly: {
type: Boolean,
default: !1
},
required: {
type: Boolean,
default: !1
},
helperText: {
type: String,
default: null
},
errorMessage: {
type: String,
default: null
},
rules: {
type: Array,
default: () => []
},
validateOnBlur: {
type: Boolean,
default: !0
},
validateOnInput: {
type: Boolean,
default: !1
},
name: {
type: String,
default: ""
},
resize: {
type: String,
default: "vertical",
validator: (e) => ["none", "both", "horizontal", "vertical"].includes(e)
},
autoResize: {
type: Boolean,
default: !1
}
},
emits: ["update:modelValue", "focus", "blur", "input", "validation", "mounted"],
setup(e, { emit: f }) {
const t = e, { autoId: l } = P("textarea", t), o = f, a = $(null), c = $(!1), i = $(""), u = S(() => ({
"vsui base-textarea": !0,
[`base-textarea--${t.variant}`]: !0,
[`base-textarea--${k.value}`]: k.value,
"base-textarea--disabled": t.disabled,
"base-textarea--focused": c.value,
"base-textarea--block": t.block,
[`base-textarea--resize-${t.resize}`]: !0
})), y = {
required: (s) => ({
valid: !!(s != null && s.toString().trim()),
message: "This field is required"
}),
min: (s, v) => ({
valid: !s || s.toString().length >= v,
message: `Must be at least ${v} characters`
}),
max: (s, v) => ({
valid: !s || s.toString().length <= v,
message: `Must be no more than ${v} characters`
})
}, V = () => {
const s = h(t.modelValue);
return o("validation", { valid: s, error: i.value, name: t.name }), s;
}, h = (s) => {
if (!t.rules.length) return !0;
for (const v of t.rules) {
if (typeof v == "string") {
const E = y[v];
if (E) {
const R = E(s);
if (!R.valid)
return i.value = R.message, !1;
}
continue;
}
if (typeof v == "object") {
const [E, R] = Object.entries(v)[0], z = y[E];
if (z) {
const n = z(s, R);
if (!n.valid)
return i.value = v.message || n.message, !1;
}
if (typeof v.validator == "function" && !v.validator(s))
return i.value = v.message || "Invalid value", !1;
}
}
return i.value = "", !0;
}, x = (s) => {
if (o("update:modelValue", s.target.value), o("input", s), t.validateOnInput) {
const v = h(s.target.value);
o("validation", { valid: v, error: i.value });
}
t.autoResize && L();
}, I = (s) => {
c.value = !0, o("focus", s);
}, M = (s) => {
if (c.value = !1, o("blur", s), t.validateOnBlur) {
const v = h(s.target.value);
o("validation", { valid: v, error: i.value });
}
}, L = () => {
if (!a.value) return;
a.value.style.height = "auto";
let s = a.value.scrollHeight + 2;
if (t.maxRows) {
const E = parseInt(getComputedStyle(a.value).lineHeight) * t.maxRows;
s = Math.min(s, E);
}
a.value.style.height = `${s}px`;
}, H = () => {
var s;
(s = a.value) == null || s.focus();
}, k = S(() => i.value ? "error" : t.state), w = S(() => i.value ? i.value : t.errorMessage || t.helperText), g = S(() => t.required ? !0 : t.rules.some(
(s) => s === "required" || typeof s == "object" && s.required
));
return A(() => {
t.autoResize && L(), o("mounted", {
validate: V,
focus: H
});
}), (s, v) => (r(), d("div", {
class: _(u.value)
}, [
e.label ? (r(), d("label", ct, [
X(T(e.label) + " ", 1),
g.value ? (r(), d("span", ft, "*")) : b("", !0)
])) : b("", !0),
p("div", mt, [
p("textarea", {
id: q(l),
ref_key: "textareaRef",
ref: a,
value: e.modelValue,
rows: e.rows,
placeholder: e.placeholder,
disabled: e.disabled,
readonly: e.readonly,
required: g.value,
"aria-required": g.value,
class: "base-textarea__field",
onInput: x,
onFocus: I,
onBlur: M
}, null, 40, vt)
]),
w.value ? (r(), d("div", {
key: 1,
class: _(["base-textarea__helper", { "base-textarea__helper--error": i.value }])
}, T(w.value), 3)) : b("", !0)
], 2));
}
}, Q = (e, f) => {
const t = e.__vccOpts || e;
for (const [l, o] of f)
t[l] = o;
return t;
}, yt = {}, gt = {
xmlns: "http://www.w3.org/2000/svg",
width: "20",
height: "20",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
};
function bt(e, f) {
return r(), d("svg", gt, f[0] || (f[0] = [
p("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }, null, -1),
p("polyline", { points: "22 4 12 14.01 9 11.01" }, null, -1)
]));
}
const ht = /* @__PURE__ */ Q(yt, [["render", bt]]), kt = {}, wt = {
xmlns: "http://www.w3.org/2000/svg",
width: "20",
height: "20",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
};
function $t(e, f) {
return r(), d("svg", wt, f[0] || (f[0] = [
p("circle", {
cx: "12",
cy: "12",
r: "10"
}, null, -1),
p("line", {
x1: "15",
y1: "9",
x2: "9",
y2: "15"
}, null, -1),
p("line", {
x1: "9",
y1: "9",
x2: "15",
y2: "15"
}, null, -1)
]));
}
const xt = /* @__PURE__ */ Q(kt, [["render", $t]]), Bt = {}, St = {
xmlns: "http://www.w3.org/2000/svg",
width: "20",
height: "20",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
};
function Vt(e, f) {
return r(), d("svg", St, f[0] || (f[0] = [
p("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }, null, -1),
p("line", {
x1: "12",
y1: "9",
x2: "12",
y2: "13"
}, null, -1),
p("line", {
x1: "12",
y1: "17",
x2: "12.01",
y2: "17"
}, null, -1)
]));
}
const _t = /* @__PURE__ */ Q(Bt, [["render", Vt]]), It = {}, Ct = {
xmlns: "http://www.w3.org/2000/svg",
width: "20",
height: "20",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
};
function Tt(e, f) {
return r(), d("svg", Ct, f[0] || (f[0] = [
p("circle", {
cx: "12",
cy: "12",
r: "10"
}, null, -1),
p("line", {
x1: "12",
y1: "16",
x2: "12",
y2: "12"
}, null, -1),
p("line", {
x1: "12",
y1: "8",
x2: "12.01",
y2: "8"
}, null, -1)
]));
}
const te = /* @__PURE__ */ Q(It, [["render", Tt]]), Mt = ["data-toast-id"], Et = {
key: 0,
class: "base-toast__icon"
}, Rt = { class: "base-toast__content" }, qt = {
key: 0,
class: "base-toast__title"
}, Lt = { class: "base-toast__message" }, se = {
__name: "BaseToast",
props: {
id: {
type: [String, Number],
required: !0
},
variant: {
type: String,
default: "default",
validator: (e) => ["default", "info", "success", "warning", "error"].includes(e)
},
position: {
type: String,
default: "top-right",
validator: (e) => [
"top-right",
"top-left",
"top-center",
"bottom-right",
"bottom-left",
"bottom-center"
].includes(e)
},
duration: {
type: Number,
default: 3e3
},
closable: {
type: Boolean,
default: !0
},
message: {
type: String,
required: !0
},
title: {
type: String,
default: ""
},
simple: {
type: Boolean,
default: !1
}
},
emits: ["close"],
setup(e, { emit: f }) {
const t = e, l = f, o = $(!1), a = $(null), c = $("100%"), i = () => {
t.duration > 0 && (c.value = "100%", requestAnimationFrame(() => {
requestAnimationFrame(() => {
c.value = "0%";
});
}));
}, u = () => {
o.value = !1, setTimeout(() => {
l("close");
}, 100);
}, y = () => {
a.value && (a.value.style.animationPlayState = "paused");
}, V = () => {
a.value && (a.value.style.animationPlayState = "running");
}, h = {
success: ht,
error: xt,
warning: _t,
info: te,
default: te
}, x = S(() => h[t.variant] || h.default);
return A(() => {
var I;
setTimeout(() => {
o.value = !0;
}, 100), t.duration > 0 && (t.simple ? setTimeout(u, t.duration) : (I = a.value) == null || I.addEventListener("animationend", u, { once: !0 })), i();
}), U(() => {
a.value && a.value.removeEventListener("animationend", u);
}), (I, M) => (r(), d("div", {
"data-toast-id": e.id,
class: _(["vsui base-toast", [
`base-toast--${e.variant}`,
`base-toast--${e.position}`,
{ "base-toast--visible": o.value },
{ "base-toast--simple": e.simple }
]]),
onMouseenter: y,
onMouseleave: V
}, [
e.simple ? b("", !0) : (r(), d("div", Et, [
(r(), Z(pe(x.value), { class: "icon" }))
])),
p("div", Rt, [
!e.simple && e.title ? (r(), d("div", qt, T(e.title), 1)) : b("", !0),
p("div", Lt, T(e.message), 1)
]),
e.closable ? (r(), d("button", {
key: 1,
class: "base-toast__close",
onClick: u
}, M[0] || (M[0] = [
p("span", null, "×", -1)
]))) : b("", !0),
!e.simple && e.duration > 0 ? (r(), d("div", {
key: 2,
ref_key: "progressBarRef",
ref: a,
class: _(["progress-bar", `progress-bar--${e.variant}`]),
style: N({
animationDuration: `${e.duration}ms`
})
}, null, 6)) : b("", !0)
], 42, Mt));
}
}, G = $([]);
let Ot = 0, ae = null;
function At() {
const e = () => {
if (ae) return;
const l = document.createElement("div");
l.id = "toast-container", document.body.appendChild(l), ae = ye({
render: () => ge(oe)
}).mount(l);
}, f = ({
message: l,
title: o = "",
variant: a = "default",
position: c = "top-right",
duration: i = 3e3,
closable: u = !0,
simple: y = !1
}) => {
e();
const V = ++Ot;
return G.value.push({
id: V,
message: l,
title: o,
variant: a,
position: c,
duration: i,
closable: u,
simple: y
}), V;
};
return {
toasts: G,
addToast: f,
removeToast: (l) => {
const o = G.value.findIndex((a) => a.id === l);
o > -1 && G.value.splice(o, 1);
},
// Convenience methods
default: (l, o = {}) => f({ ...o, message: l, variant: "default" }),
success: (l, o = {}) => f({ ...o, message: l, variant: "success" }),
error: (l, o = {}) => f({ ...o, message: l, variant: "error" }),
info: (l, o = {}) => f({ ...o, message: l, variant: "info" }),
warning: (l, o = {}) => f({ ...o, message: l, variant: "warning" })
};
}
const oe = {
__name: "ToastsContainer",
setup(e) {
const { toasts: f, removeToast: t } = At(), l = S(() => {
const o = {
"top-right": [],
"top-left": [],
"top-center": [],
"bottom-right": [],
"bottom-left": [],
"bottom-center": []
};
return f.value.forEach((a) => {
o[a.position].push(a);
}), o;
});
return (o, a) => (r(!0), d(j, null, J(l.value, (c, i) => (r(), d(j, { key: i }, [
c.length ? (r(), d("div", {
key: 0,
class: _(["vsui toasts-container", `toasts-container--${i}`])
}, [
le(be, { name: "toast" }, {
default: ne(() => [
(r(!0), d(j, null, J(c, (u) => (r(), Z(q(se), he({
key: u.id,
ref_for: !0
}, u, {
onClose: (y) => q(t)(u.id)
}), null, 16, ["onClose"]))), 128))
]),
_: 2
}, 1024)
], 2)) : b("", !0)
], 64))), 128));
}
}, Ft = {
install(e) {
e.component("BaseAccordion", we), e.component("BaseAccordionItem", Be), e.component("BaseButton", Ce), e.component("BaseCheckbox", Le), e.component("BaseDropdown", Ae), e.component("BaseInfiniteScroll", Pe), e.component("BaseInput", Ge), e.component("BasePopup", Ze), e.component("BaseSkeleton", et), e.component("BaseSlider", dt), e.component("BaseTextarea", pt), e.component("BaseToast", se), e.component("ToastsContainer", oe);
}
};
export {
we as BaseAccordion,
Be as BaseAccordionItem,
Ce as BaseButton,
Le as BaseCheckbox,
Ae as BaseDropdown,
Pe as BaseInfiniteScroll,
Ge as BaseInput,
Ze as BasePopup,
et as BaseSkeleton,
dt as BaseSlider,
pt as BaseTextarea,
se as BaseToast,
oe as ToastsContainer,
Ft as default,
At as useToast
};