vue-smart-ui
Version:
A collection of Vue 3 smart and highly customizable UI components for modern web applications
1,750 lines • 103 kB
JavaScript
import { computed as C, ref as M, provide as Le, createElementBlock as o, openBlock as s, unref as X, normalizeClass as q, renderSlot as H, inject as Ee, onMounted as ae, onUnmounted as ue, watch as oe, createElementVNode as c, createCommentVNode as $, createTextVNode as se, toDisplayString as E, normalizeStyle as le, nextTick as ce, createVNode as J, Transition as _e, withCtx as ne, withDirectives as he, vShow as Se, useSlots as Ve, withKeys as je, createBlock as fe, Teleport as Pe, withModifiers as re, Fragment as Q, renderList as Y, resolveDynamicComponent as ze, createApp as Fe, h as De, createSlots as Ne, vModelDynamic as Ke, TransitionGroup as He, mergeProps as Ue } from "vue";
let we = 0;
function ee(e = "base", x) {
const t = () => (we++, `${e}-${we}`);
return {
autoId: C(() => x.id || t())
};
}
const We = ["id"], Ge = {
__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 x = e, { autoId: t } = ee("accordion", x), a = M([]);
return Le("accordion", {
activeItems: a,
toggleItem: (l) => {
if (x.multiple) {
const b = a.value.indexOf(l);
b === -1 ? a.value.push(l) : a.value.splice(b, 1);
} else
a.value = a.value.includes(l) ? [] : [l];
},
variant: x.variant
}), (l, b) => (s(), o("div", {
class: q(["vsui base-accordion", `base-accordion--${e.variant}`]),
id: X(t)
}, [
H(l.$slots, "default")
], 10, We));
}
}, Xe = ["disabled", "aria-expanded"], Qe = { class: "base-accordion-item__body" }, Je = {
__name: "BaseAccordionItem",
props: {
title: {
type: String,
required: !0
},
disabled: {
type: Boolean,
default: !1
}
},
setup(e) {
const x = e, t = Ee("accordion"), a = M(Symbol()), i = M("0px"), l = M(null), b = C(() => t.activeItems.value.includes(a.value)), d = C(() => t.variant), r = () => {
x.disabled || t.toggleItem(a.value);
}, g = () => {
l.value && (i.value = b.value ? `${l.value.scrollHeight}px` : "0px");
}, V = new ResizeObserver(g);
return ae(() => {
l.value && (V.observe(l.value), g());
}), ue(() => {
V.disconnect();
}), oe(b, g), (k, A) => (s(), o("div", {
class: q(["vsui base-accordion-item", [
`base-accordion-item--${d.value}`,
{
"base-accordion-item--active": b.value,
"base-accordion-item--disabled": e.disabled
}
]])
}, [
c("button", {
class: "base-accordion-item__header",
onClick: r,
disabled: e.disabled,
"aria-expanded": b.value
}, [
k.$slots.icon ? H(k.$slots, "icon", { key: 0 }) : $("", !0),
H(k.$slots, "title", {}, () => [
se(E(e.title), 1)
]),
H(k.$slots, "chevron", {}, () => [
A[0] || (A[0] = c("svg", {
class: "base-accordion-item__chevron",
viewBox: "0 0 24 24",
width: "1.2em",
height: "1.2em"
}, [
c("path", {
fill: "currentColor",
d: "M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"
})
], -1))
])
], 8, Xe),
c("div", {
class: "base-accordion-item__content",
ref_key: "contentRef",
ref: l,
style: le({ height: i.value })
}, [
c("div", Qe, [
H(k.$slots, "default")
])
], 4)
], 2));
}
}, Ye = ["id", "disabled"], Ze = {
key: 0,
class: "spinner"
}, de = /* @__PURE__ */ Object.assign({
inheritAttrs: !1
}, {
__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 x = e, { autoId: t } = ee("button", x);
return (a, i) => (s(), o("button", {
id: X(t),
class: q(["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,
"base-button--loading": e.loading
},
a.$attrs.class
]]),
disabled: e.disabled || e.loading,
onClick: i[0] || (i[0] = (l) => a.$emit("click", l))
}, [
c("div", {
class: q(["button-content", [{ hidden: e.loading }, a.$attrs.class]])
}, [
a.$slots.prefix ? H(a.$slots, "prefix", { key: 0 }) : $("", !0),
H(a.$slots, "default"),
a.$slots.suffix ? H(a.$slots, "suffix", { key: 1 }) : $("", !0)
], 2),
e.loading ? (s(), o("div", Ze)) : $("", !0)
], 10, Ye));
}
}), et = ["id", "checked", "disabled", "indeterminate"], tt = { class: "base-checkbox__checkmark" }, at = {
key: 0,
viewBox: "0 0 14 14",
fill: "none",
xmlns: "http://www.w3.org/2000/svg"
}, lt = {
key: 1,
viewBox: "0 0 14 14",
fill: "none",
xmlns: "http://www.w3.org/2000/svg"
}, st = {
key: 0,
class: "base-checkbox__label"
}, me = {
__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: x }) {
const t = e, { autoId: a } = ee("checkbox", t), i = x, l = C(() => Array.isArray(t.modelValue) ? t.modelValue.includes(t.value) : t.modelValue), b = (d) => {
if (Array.isArray(t.modelValue)) {
const r = [...t.modelValue];
if (d.target.checked)
r.push(t.value);
else {
const g = r.indexOf(t.value);
g > -1 && r.splice(g, 1);
}
i("update:modelValue", r);
} else
i("update:modelValue", d.target.checked);
};
return (d, r) => (s(), o("label", {
class: q([
"vsui base-checkbox",
`base-checkbox--${e.size}`,
{
"base-checkbox--disabled": e.disabled,
"base-checkbox--error": e.error
}
])
}, [
c("input", {
id: X(a),
type: "checkbox",
checked: l.value,
disabled: e.disabled,
indeterminate: e.indeterminate,
class: "base-checkbox__input",
onChange: b
}, null, 40, et),
c("span", tt, [
H(d.$slots, "checkmark", {}, () => [
l.value && !e.indeterminate ? (s(), o("svg", at, r[0] || (r[0] = [
c("path", {
d: "M11.6666 3.5L5.24992 9.91667L2.33325 7",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
}, null, -1)
]))) : $("", !0),
e.indeterminate ? (s(), o("svg", lt, r[1] || (r[1] = [
c("path", {
d: "M2.91675 7H11.0834",
stroke: "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
}, null, -1)
]))) : $("", !0)
])
]),
d.$slots.default || e.label ? (s(), o("span", st, [
H(d.$slots, "default", {}, () => [
se(E(e.label), 1)
])
])) : $("", !0)
], 2));
}
}, nt = ["id"], ot = {
__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: x }) {
const t = e, { autoId: a } = ee("dropdown", t), i = x, l = M(null), b = M(null), d = M(t.modelValue), r = () => {
if (!b.value || !l.value) return;
const k = b.value.getBoundingClientRect(), A = l.value.getBoundingClientRect(), O = {
width: window.innerWidth,
height: window.innerHeight
};
b.value.style.top = "100%", b.value.style.bottom = "auto", b.value.style.left = "auto", b.value.style.right = "0", A.right + k.width > O.width && (b.value.style.right = "0", b.value.style.left = "auto"), A.right - k.width < 0 && (b.value.style.left = "0", b.value.style.right = "auto"), A.bottom + k.height > O.height && (b.value.style.bottom = "100%", b.value.style.top = "auto", b.value.style.marginTop = "0", b.value.style.marginBottom = "0.5rem");
};
oe(
() => t.modelValue,
(k) => {
d.value = k, k ? (document.addEventListener("click", g), ce(() => {
r();
})) : document.removeEventListener("click", g);
}
);
const g = (k) => {
t.closeOnClickOutside && l.value && !l.value.contains(k.target) && i("update:modelValue", !1);
}, V = (k) => {
t.closeOnClick && !k.target.closest("[data-prevent-close]") && i("update:modelValue", !1);
};
return ae(() => {
t.modelValue && document.addEventListener("click", g), window.addEventListener("scroll", r, !0), window.addEventListener("resize", r);
}), ue(() => {
document.removeEventListener("click", g), window.removeEventListener("scroll", r, !0), window.removeEventListener("resize", r);
}), (k, A) => (s(), o("div", {
ref_key: "dropdownRef",
ref: l,
class: "vsui base-dropdown",
id: X(a)
}, [
c("div", {
class: "base-dropdown__trigger",
onClick: A[0] || (A[0] = (O) => i("update:modelValue", !e.modelValue))
}, [
H(k.$slots, "trigger")
]),
J(_e, { name: "dropdown" }, {
default: ne(() => [
he(c("div", {
ref_key: "menuRef",
ref: b,
class: q(["base-dropdown__menu", `base-dropdown__menu--${e.variant}`]),
style: le({ width: e.width }),
onClick: V
}, [
H(k.$slots, "default")
], 6), [
[Se, d.value]
])
]),
_: 3
})
], 8, nt));
}
}, rt = { class: "vsui infinite-scroll" }, it = { class: "infinite-scroll__loader" }, ut = { key: 0 }, dt = {
key: 0,
class: "infinite-scroll__end"
}, ct = {
__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: x }) {
const t = e, a = x, i = M(null), l = M(null), b = () => {
i.value && i.value.disconnect(), i.value = new IntersectionObserver(
(d) => {
d[0].isIntersecting && !t.loading && !t.disabled && a("load-more");
},
{
threshold: 0,
root: t.container ? document.querySelector(t.container) : null,
rootMargin: `0px 0px ${t.threshold}px 0px`
}
), l.value && i.value.observe(l.value);
};
return oe(
() => t.loading,
(d, r) => {
r === !0 && d === !1 && setTimeout(() => {
b();
}, 100);
}
), ae(() => {
b();
}), ue(() => {
i.value && i.value.disconnect();
}), (d, r) => (s(), o("div", rt, [
H(d.$slots, "default"),
c("div", {
ref_key: "bottomElement",
ref: l,
class: "infinite-scroll__trigger"
}, [
e.loading ? H(d.$slots, "loading", { key: 0 }, () => [
c("div", it, [
r[0] || (r[0] = c("div", { class: "spinner" }, null, -1)),
e.loadingText ? (s(), o("span", ut, E(e.loadingText), 1)) : $("", !0)
])
]) : e.disabled ? H(d.$slots, "disabled", { key: 1 }, () => [
e.endText ? (s(), o("div", dt, E(e.endText), 1)) : $("", !0)
]) : $("", !0)
], 512)
]));
}
}, ft = {
key: 0,
class: "base-input__label"
}, vt = {
key: 0,
class: "base-input__required",
"aria-hidden": "true"
}, mt = { class: "base-input__wrapper" }, bt = {
key: 0,
class: "base-input__prefix"
}, pt = ["id", "type", "value", "placeholder", "disabled", "readonly", "required", "aria-required", "maxlength", "min", "max"], gt = {
key: 1,
class: "base-input__suffix"
}, be = {
__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: ""
},
min: {
type: [Number, String],
default: null
},
max: {
type: [Number, String],
default: null
},
mask: {
type: [String, Object],
default: null
}
},
emits: ["update:modelValue", "focus", "blur", "input", "validation", "mounted"],
setup(e, { emit: x }) {
const t = Ve(), a = e, { autoId: i } = ee("input", a), l = x, b = M(null), d = M(!1), r = M(""), g = C(() => ({
"vsui base-input": !0,
[`base-input--${a.variant}`]: !0,
[`base-input--${h.value}`]: h.value,
"base-input--disabled": a.disabled,
"base-input--focused": d.value,
"base-input--with-prefix": a.prefixIcon || t.prefix,
"base-input--with-suffix": a.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, y) => ({
valid: !n || n.length >= y,
message: `Must be at least ${y} characters`
}),
max: (n, y) => ({
valid: !n || n.length <= y,
message: `Must be no more than ${y} characters`
}),
pattern: (n, y) => ({
valid: !n || new RegExp(y).test(n),
message: "Invalid format"
}),
minValue: (n, y) => ({
valid: !n || Number(n) >= y,
message: `Value must be at least ${y}`
}),
maxValue: (n, y) => ({
valid: !n || Number(n) <= y,
message: `Value must be no more than ${y}`
}),
hexColor: (n) => ({
valid: !n || /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(n),
message: "Invalid HEX color"
}),
rgbColor: (n) => ({
valid: !n || /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/.test(n),
message: "Invalid RGB color"
}),
rgbaColor: (n) => ({
valid: !n || /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|0?\.\d+|1(\.0)?)\s*\)$/.test(
n
),
message: "Invalid RGBA color"
}),
hslColor: (n) => ({
valid: !n || /^hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)$/.test(n),
message: "Invalid HSL color"
})
}, k = (n) => {
if (!a.rules.length) return !0;
for (const y of a.rules) {
if (typeof y == "string") {
const T = V[y];
if (T) {
const j = T(n);
if (!j.valid)
return r.value = j.message, !1;
}
continue;
}
if (typeof y == "object") {
const [T, j] = Object.entries(y)[0];
console.log(T, j);
const W = V[T];
if (W) {
const p = W(n, j);
if (!p.valid)
return r.value = y.message || p.message, !1;
}
if (typeof y.validator == "function" && !y.validator(n))
return r.value = y.message || "Invalid value", !1;
}
}
return r.value = "", !0;
}, A = C({
get: () => a.mask === "currency" && a.modelValue ? O.currency.format(a.modelValue) : a.modelValue,
set: (n) => l("update:modelValue", n)
}), O = {
phone: {
patterns: ["(##) ####-####", "(##) #####-####"],
match: (n) => n.replace(/\D/g, "").length <= 10 ? 0 : 1
},
currency: {
pattern: "currency",
format: (n) => {
if (!n) return "";
const y = 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(y);
},
parse: (n) => {
const y = n.replace(/[^\d]/g, "");
return parseFloat(y) / 100;
}
},
date: "##/##/####",
cpf: "###.###.###-##",
cnpj: "##.###.###/####-##",
cep: "#####-###"
}, D = (n, y) => {
if (!n) return n;
if (y === "currency" || y.pattern === "currency") {
const T = O.currency.parse(n);
return O.currency.format(T);
}
if (typeof y == "string")
return z(n, y);
if (y.patterns) {
const T = y.match(n);
return z(n, y.patterns[T]);
}
return n;
}, z = (n, y) => {
if (!y) return n;
const j = n.replace(/\D/g, "").split("");
let W = "", p = 0;
for (let w = 0; w < y.length && j[w]; w++)
y[p] === "#" ? (W += j[w], p++) : (W += y[p], p++, w--);
return W;
}, N = (n) => {
let y = n.target.value;
if (a.mask) {
const T = typeof a.mask == "string" ? O[a.mask] || a.mask : a.mask.pattern;
y = D(y, T), b.value && (b.value.value = y);
}
if (a.mask === "currency") {
const T = O.currency.parse(y);
A.value = T, l("update:modelValue", T);
} else
A.value = y, l("update:modelValue", y);
if (l("input", { ...n, target: { ...n.target, value: y } }), a.validateOnInput) {
const T = k(A.value);
l("validation", { valid: T, error: r.value });
}
}, L = (n) => {
d.value = !0, l("enter", n);
}, f = (n) => {
d.value = !0, l("focus", n);
}, m = (n) => {
if (d.value = !1, l("blur", n), a.validateOnBlur) {
const y = k(A.value);
l("validation", { valid: y, error: r.value });
}
}, u = () => {
var n;
(n = b.value) == null || n.focus();
}, h = C(() => r.value ? "error" : a.state), I = C(() => r.value ? r.value : a.errorMessage || a.helperText), R = () => {
const n = k(A.value);
return l("validation", { valid: n, error: r.value, name: a.name }), n;
}, P = C(() => a.required ? !0 : a.rules.some((n) => n === "required" ? !0 : typeof n == "object" ? n.required || Object.keys(n)[0] === "required" : !1)), S = C(() => {
if (!a.mask) return;
const n = typeof a.mask == "string" ? O[a.mask] || a.mask : a.mask.pattern;
if (typeof n == "string")
return n.length;
if (n.patterns)
return Math.max(...n.patterns.map((y) => y.length));
});
return ae(() => {
l("mounted", {
validate: R,
focus: u
});
}), (n, y) => (s(), o("div", {
class: q(g.value)
}, [
e.label ? (s(), o("label", ft, [
se(E(e.label) + " ", 1),
P.value ? (s(), o("span", vt, "*")) : $("", !0)
])) : $("", !0),
c("div", mt, [
n.$slots.prefix || e.prefixIcon ? (s(), o("div", bt, [
H(n.$slots, "prefix", {}, () => [
c("i", {
class: q(e.prefixIcon)
}, null, 2)
])
])) : $("", !0),
c("input", {
id: X(i),
ref_key: "inputRef",
ref: b,
type: e.type,
value: A.value,
placeholder: e.placeholder,
disabled: e.disabled,
readonly: e.readonly,
required: P.value,
"aria-required": P.value,
maxlength: S.value,
min: e.min,
max: e.max,
class: "base-input__field",
onInput: N,
onFocus: f,
onBlur: m,
onKeydown: je(L, ["enter"])
}, null, 40, pt),
n.$slots.suffix || e.suffixIcon ? (s(), o("div", gt, [
H(n.$slots, "suffix", {}, () => [
c("i", {
class: q(e.suffixIcon)
}, null, 2)
])
])) : $("", !0)
]),
I.value ? (s(), o("div", {
key: 1,
class: q(["base-input__helper", { "base-input__helper--error": r.value }])
}, E(I.value), 3)) : $("", !0)
], 2));
}
}, yt = {
key: 0,
class: "base-popup__header"
}, ht = { class: "base-popup__content" }, kt = {
key: 1,
class: "base-popup__footer"
}, wt = {
__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: x }) {
const t = e, a = x, i = M(null), l = (d) => {
!t.disableClickOutside && i.value && !i.value.contains(d.target) && (d.target.closest(".base-popup") || (a("update:modelValue", !1), a("close")));
}, b = (d) => {
t.closeOnEsc && d.key === "Escape" && (a("update:modelValue", !1), a("close"));
};
return ae(() => {
document.addEventListener("mousedown", l), document.addEventListener("keydown", b);
}), ue(() => {
document.removeEventListener("mousedown", l), document.removeEventListener("keydown", b);
}), (d, r) => (s(), fe(Pe, { to: "body" }, [
e.modelValue ? (s(), o("div", {
key: 0,
class: q(["vsui base-popup-overlay", [`base-popup-overlay--${e.position}`]])
}, [
c("div", {
ref_key: "popupRef",
ref: i,
class: q(["base-popup", [`base-popup--${e.variant}`, `base-popup--${e.size}`, `base-popup--${e.position}`]])
}, [
d.$slots.header ? (s(), o("div", yt, [
H(d.$slots, "header")
])) : $("", !0),
c("div", ht, [
H(d.$slots, "default")
]),
d.$slots.footer ? (s(), o("div", kt, [
H(d.$slots, "footer")
])) : $("", !0),
d.$slots.close ? (s(), o("button", {
key: 2,
class: "base-popup__close",
onClick: r[0] || (r[0] = (g) => d.$emit("update:modelValue", !1))
}, [
H(d.$slots, "close")
])) : $("", !0)
], 2)
], 2)) : $("", !0)
]));
}
}, ye = {
__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 (x, t) => (s(), o("div", {
class: q(["vsui base-skeleton", [
`base-skeleton--${e.variant}`,
{
"base-skeleton--animated": e.animated,
"base-skeleton--rounded": e.rounded
}
]]),
style: le({
width: e.width,
height: e.height || null
})
}, [
H(x.$slots, "default")
], 6));
}
}, $t = ["for"], xt = {
key: 0,
class: "base-slider__required"
}, _t = { class: "base-slider__container" }, St = { class: "base-slider__extremity-value base-slider__extremity-value--min" }, Vt = {
key: 0,
class: "base-slider__mark-label"
}, Bt = ["onMousedown", "onTouchstart", "onKeydown", "aria-valuemin", "aria-valuemax", "aria-valuenow", "aria-valuetext", "aria-disabled"], Ct = {
key: 0,
class: "base-slider__thumb-value"
}, It = { class: "base-slider__extremity-value base-slider__extremity-value--max" }, At = {
key: 1,
class: "base-slider__helper"
}, Tt = {
__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: x }) {
const t = e, a = x, { autoId: i } = ee("slider", t), l = M(t.modelValue), b = M(!1), d = M(null), r = M([]), g = C(() => t.range && Array.isArray(t.modelValue)), V = C(() => t.formatValue ? g.value ? l.value.map((L) => t.formatValue(L)) : t.formatValue(l.value) : l.value), k = C(() => {
if (g.value) {
const [L, f] = l.value, m = (L - t.min) / (t.max - t.min) * 100, u = (f - t.min) / (t.max - t.min) * 100;
return {
left: `${m}%`,
width: `${u - m}%`
};
} else
return {
width: `${(l.value - t.min) / (t.max - t.min) * 100}%`
};
}), A = C(() => g.value ? l.value.map((L) => `${(L - t.min) / (t.max - t.min) * 100}%`) : [`${(l.value - t.min) / (t.max - t.min) * 100}%`]), O = C(() => ({
"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"
}));
oe(
() => t.modelValue,
(L) => {
l.value = L;
}
), oe(l, (L) => {
a("update:modelValue", L);
});
const D = (L, f = 0) => {
if (t.disabled) return;
const m = d.value.getBoundingClientRect(), u = L.clientX - m.left, h = Math.min(Math.max(u / m.width, 0), 1), I = t.min + h * (t.max - t.min), R = Math.round(I / t.step) * t.step, P = Math.min(Math.max(R, t.min), t.max);
if (g.value) {
const S = [...l.value];
S[f] = P, f === 0 && S[0] > S[1] ? S[0] = S[1] : f === 1 && S[1] < S[0] && (S[1] = S[0]), l.value = S;
} else
l.value = P;
a("change", l.value);
}, z = (L, f = 0) => {
if (t.disabled) return;
b.value = !0, D(L, f);
const m = (h) => D(h, f), u = () => {
b.value = !1, document.removeEventListener("mousemove", m), document.removeEventListener("mouseup", u), document.removeEventListener("touchmove", m), document.removeEventListener("touchend", u);
};
document.addEventListener("mousemove", m), document.addEventListener("mouseup", u), document.addEventListener("touchmove", m), document.addEventListener("touchend", u);
}, N = (L, f = 0) => {
if (t.disabled) return;
const m = g.value ? l.value[f] : l.value;
let u = m;
switch (L.key) {
case "ArrowRight":
case "ArrowUp":
u = Math.min(m + t.step, t.max);
break;
case "ArrowLeft":
case "ArrowDown":
u = Math.max(m - t.step, t.min);
break;
case "Home":
u = t.min;
break;
case "End":
u = t.max;
break;
default:
return;
}
if (g.value) {
const h = [...l.value];
h[f] = u, f === 0 && h[0] > h[1] ? h[0] = h[1] : f === 1 && h[1] < h[0] && (h[1] = h[0]), l.value = h;
} else
l.value = u;
a("change", l.value), L.preventDefault();
};
return ae(() => {
g.value && (!Array.isArray(l.value) || l.value.length !== 2) ? l.value = [t.min, t.max] : !g.value && Array.isArray(l.value) && (l.value = t.min), a("mounted", {
id: i.value,
getValue: () => l.value,
setValue: (L) => {
l.value = L;
}
});
}), (L, f) => (s(), o("div", {
class: q(["vsui base-slider", O.value])
}, [
e.label ? (s(), o("label", {
key: 0,
for: X(i),
class: "base-slider__label"
}, [
se(E(e.label) + " ", 1),
e.required ? (s(), o("span", xt, "*")) : $("", !0)
], 8, $t)) : $("", !0),
c("div", _t, [
c("div", St, E(e.formatValue ? e.formatValue(e.min) : e.min), 1),
c("div", {
ref_key: "sliderTrack",
ref: d,
class: "base-slider__track",
onMousedown: f[0] || (f[0] = (m) => D(m)),
onTouchstart: f[1] || (f[1] = re((m) => D(m.touches[0]), ["prevent"]))
}, [
c("div", {
class: "base-slider__track-fill",
style: le(k.value)
}, null, 4),
(s(!0), o(Q, null, Y(e.marks, (m) => (s(), o("div", {
key: m.value,
class: q(["base-slider__mark", {
"base-slider__mark--active": g.value ? m.value >= l.value[0] && m.value <= l.value[1] : m.value <= l.value
}]),
style: le({ left: `calc(${(m.value - e.min) / (e.max - e.min) * 100}%)` })
}, [
f[2] || (f[2] = c("div", { class: "base-slider__mark-dot" }, null, -1)),
m.label ? (s(), o("div", Vt, E(m.label), 1)) : $("", !0)
], 6))), 128)),
(s(!0), o(Q, null, Y(A.value, (m, u) => (s(), o("div", {
key: u,
ref_for: !0,
ref_key: "thumbRefs",
ref: r,
class: "base-slider__thumb",
style: le({ left: m }),
onMousedown: re((h) => z(h, u), ["stop"]),
onTouchstart: re((h) => z(h.touches[0], u), ["stop", "prevent"]),
onKeydown: (h) => N(h, u),
tabindex: "0",
role: "slider",
"aria-valuemin": e.min,
"aria-valuemax": e.max,
"aria-valuenow": g.value ? l.value[u] : l.value,
"aria-valuetext": g.value ? V.value[u] : V.value,
"aria-disabled": e.disabled
}, [
e.showValue ? (s(), o("div", Ct, E(g.value ? V.value[u] : V.value), 1)) : $("", !0)
], 44, Bt))), 128))
], 544),
c("div", It, E(e.formatValue ? e.formatValue(e.max) : e.max), 1)
]),
e.helperText || e.errorMessage ? (s(), o("div", At, E(e.errorMessage || e.helperText), 1)) : $("", !0)
], 2));
}
}, Mt = {
key: 0,
class: "base-textarea__label"
}, Ot = {
key: 0,
class: "base-textarea__required",
"aria-hidden": "true"
}, Rt = { class: "base-textarea__wrapper" }, qt = ["id", "value", "rows", "placeholder", "disabled", "readonly", "required", "aria-required"], Lt = {
__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: x }) {
const t = e, { autoId: a } = ee("textarea", t), i = x, l = M(null), b = M(!1), d = M(""), r = C(() => ({
"vsui base-textarea": !0,
[`base-textarea--${t.variant}`]: !0,
[`base-textarea--${L.value}`]: L.value,
"base-textarea--disabled": t.disabled,
"base-textarea--focused": b.value,
"base-textarea--block": t.block,
[`base-textarea--resize-${t.resize}`]: !0
})), g = {
required: (u) => ({
valid: !!(u != null && u.toString().trim()),
message: "This field is required"
}),
min: (u, h) => ({
valid: !u || u.toString().length >= h,
message: `Must be at least ${h} characters`
}),
max: (u, h) => ({
valid: !u || u.toString().length <= h,
message: `Must be no more than ${h} characters`
})
}, V = () => {
const u = k(t.modelValue);
return i("validation", { valid: u, error: d.value, name: t.name }), u;
}, k = (u) => {
if (!t.rules.length) return !0;
for (const h of t.rules) {
if (typeof h == "string") {
const I = g[h];
if (I) {
const R = I(u);
if (!R.valid)
return d.value = R.message, !1;
}
continue;
}
if (typeof h == "object") {
const [I, R] = Object.entries(h)[0], P = g[I];
if (P) {
const S = P(u, R);
if (!S.valid)
return d.value = h.message || S.message, !1;
}
if (typeof h.validator == "function" && !h.validator(u))
return d.value = h.message || "Invalid value", !1;
}
}
return d.value = "", !0;
}, A = (u) => {
if (i("update:modelValue", u.target.value), i("input", u), t.validateOnInput) {
const h = k(u.target.value);
i("validation", { valid: h, error: d.value });
}
t.autoResize && z();
}, O = (u) => {
b.value = !0, i("focus", u);
}, D = (u) => {
if (b.value = !1, i("blur", u), t.validateOnBlur) {
const h = k(u.target.value);
i("validation", { valid: h, error: d.value });
}
}, z = () => {
if (!l.value) return;
l.value.style.height = "auto";
let u = l.value.scrollHeight + 2;
if (t.maxRows) {
const I = parseInt(getComputedStyle(l.value).lineHeight) * t.maxRows;
u = Math.min(u, I);
}
l.value.style.height = `${u}px`;
}, N = () => {
var u;
(u = l.value) == null || u.focus();
}, L = C(() => d.value ? "error" : t.state), f = C(() => d.value ? d.value : t.errorMessage || t.helperText), m = C(() => t.required ? !0 : t.rules.some(
(u) => u === "required" || typeof u == "object" && u.required
));
return ae(() => {
t.autoResize && z(), i("mounted", {
validate: V,
focus: N
});
}), (u, h) => (s(), o("div", {
class: q(r.value)
}, [
e.label ? (s(), o("label", Mt, [
se(E(e.label) + " ", 1),
m.value ? (s(), o("span", Ot, "*")) : $("", !0)
])) : $("", !0),
c("div", Rt, [
c("textarea", {
id: X(a),
ref_key: "textareaRef",
ref: l,
value: e.modelValue,
rows: e.rows,
placeholder: e.placeholder,
disabled: e.disabled,
readonly: e.readonly,
required: m.value,
"aria-required": m.value,
class: "base-textarea__field",
onInput: A,
onFocus: O,
onBlur: D
}, null, 40, qt)
]),
f.value ? (s(), o("div", {
key: 1,
class: q(["base-textarea__helper", { "base-textarea__helper--error": d.value }])
}, E(f.value), 3)) : $("", !0)
], 2));
}
}, pe = (e, x) => {
const t = e.__vccOpts || e;
for (const [a, i] of x)
t[a] = i;
return t;
}, Et = {}, jt = {
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 Pt(e, x) {
return s(), o("svg", jt, x[0] || (x[0] = [
c("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }, null, -1),
c("polyline", { points: "22 4 12 14.01 9 11.01" }, null, -1)
]));
}
const zt = /* @__PURE__ */ pe(Et, [["render", Pt]]), Ft = {}, Dt = {
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 Nt(e, x) {
return s(), o("svg", Dt, x[0] || (x[0] = [
c("circle", {
cx: "12",
cy: "12",
r: "10"
}, null, -1),
c("line", {
x1: "15",
y1: "9",
x2: "9",
y2: "15"
}, null, -1),
c("line", {
x1: "9",
y1: "9",
x2: "15",
y2: "15"
}, null, -1)
]));
}
const Kt = /* @__PURE__ */ pe(Ft, [["render", Nt]]), Ht = {}, Ut = {
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 Wt(e, x) {
return s(), o("svg", Ut, x[0] || (x[0] = [
c("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),
c("line", {
x1: "12",
y1: "9",
x2: "12",
y2: "13"
}, null, -1),
c("line", {
x1: "12",
y1: "17",
x2: "12.01",
y2: "17"
}, null, -1)
]));
}
const Gt = /* @__PURE__ */ pe(Ht, [["render", Wt]]), Xt = {}, Qt = {
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 Jt(e, x) {
return s(), o("svg", Qt, x[0] || (x[0] = [
c("circle", {
cx: "12",
cy: "12",
r: "10"
}, null, -1),
c("line", {
x1: "12",
y1: "16",
x2: "12",
y2: "12"
}, null, -1),
c("line", {
x1: "12",
y1: "8",
x2: "12.01",
y2: "8"
}, null, -1)
]));
}
const $e = /* @__PURE__ */ pe(Xt, [["render", Jt]]), Yt = ["data-toast-id"], Zt = {
key: 0,
class: "base-toast__icon"
}, ea = { class: "base-toast__content" }, ta = {
key: 0,
class: "base-toast__title"
}, aa = { class: "base-toast__message" }, Be = {
__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: x }) {
const t = e, a = x, i = M(!1), l = M(null), b = M("100%"), d = () => {
t.duration > 0 && (b.value = "100%", requestAnimationFrame(() => {
requestAnimationFrame(() => {
b.value = "0%";
});
}));
}, r = () => {
i.value = !1, setTimeout(() => {
a("close");
}, 100);
}, g = () => {
l.value && (l.value.style.animationPlayState = "paused");
}, V = () => {
l.value && (l.value.style.animationPlayState = "running");
}, k = {
success: zt,
error: Kt,
warning: Gt,
info: $e,
default: $e
}, A = C(() => k[t.variant] || k.default);
return ae(() => {
var O;
setTimeout(() => {
i.value = !0;
}, 100), t.duration > 0 && (t.simple ? setTimeout(r, t.duration) : (O = l.value) == null || O.addEventListener("animationend", r, { once: !0 })), d();
}), ue(() => {
l.value && l.value.removeEventListener("animationend", r);
}), (O, D) => (s(), o("div", {
"data-toast-id": e.id,
class: q(["vsui base-toast", [
`base-toast--${e.variant}`,
`base-toast--${e.position}`,
{ "base-toast--visible": i.value },
{ "base-toast--simple": e.simple }
]]),
onMouseenter: g,
onMouseleave: V
}, [
e.simple ? $("", !0) : (s(), o("div", Zt, [
(s(), fe(ze(A.value), { class: "icon" }))
])),
c("div", ea, [
!e.simple && e.title ? (s(), o("div", ta, E(e.title), 1)) : $("", !0),
c("div", aa, E(e.message), 1)
]),
e.closable ? (s(), o("button", {
key: 1,
class: "base-toast__close",
onClick: r
}, D[0] || (D[0] = [
c("span", null, "×", -1)
]))) : $("", !0),
!e.simple && e.duration > 0 ? (s(), o("div", {
key: 2,
ref_key: "progressBarRef",
ref: l,
class: q(["progress-bar", `progress-bar--${e.variant}`]),
style: le({
animationDuration: `${e.duration}ms`
})
}, null, 6)) : $("", !0)
], 42, Yt));
}
}, ve = M([]);
let la = 0, xe = null;
function sa() {
const e = () => {
if (xe) return;
const a = document.createElement("div");
a.id = "toast-container", document.body.appendChild(a), xe = Fe({
render: () => De(Ie)
}).mount(a);
}, x = ({
message: a,
title: i = "",
variant: l = "default",
position: b = "top-right",
duration: d = 3e3,
closable: r = !0,
simple: g = !1
}) => {
e();
const V = ++la;
return ve.value.push({
id: V,
message: a,
title: i,
variant: l,
position: b,
duration: d,
closable: r,
simple: g
}), V;
};
return {
toasts: ve,
addToast: x,
removeToast: (a) => {
const i = ve.value.findIndex((l) => l.id === a);
i > -1 && ve.value.splice(i, 1);
},
// Convenience methods
default: (a, i = {}) => x({ ...i, message: a, variant: "default" }),
success: (a, i = {}) => x({ ...i, message: a, variant: "success" }),
error: (a, i = {}) => x({ ...i, message: a, variant: "error" }),
info: (a, i = {}) => x({ ...i, message: a, variant: "info" }),
warning: (a, i = {}) => x({ ...i, message: a, variant: "warning" })
};
}
const na = { class: "vsui base-segmented-buttons-wrapper" }, oa = {
key: 0,
class: "base-segmented-buttons__label"
}, ra = {
key: 0,
class: "base-segmented-buttons__required"
}, ia = ["id"], ua = ["disabled", "onClick"], da = {
__name: "BaseSegmentedButtons",
props: {
id: {
type: String,
default: ""
},
modelValue: {
type: [String, Number, Array],
default: () => []
},
options: {
type: Array,
default: () => [],
required: !0
},
valueKey: {
type: String,
default: "value"
},
labelKey: {
type: String,
default: "label"
},
variant: {
type: String,
default: "primary",
validator: (e) => ["primary", "secondary", "gray"].includes(e)
},
size: {
type: String,
default: "medium",
validator: (e) => ["small", "medium", "large"].includes(e)
},
disabled: {
type: Boolean,
default: !1
},
block: {
type: Boolean,
default: !1
},
multiple: {
type: Boolean,
default: !1
},
label: {
type: String,
default: null
},
helperText: {
type: String,
default: null
},
errorMessage: {
type: String,
default: null
},
rules: {
type: Array,
default: () => []
},
validateOnChange: {
type: Boolean,
default: !0
}
},
emits: ["update:modelValue", "change", "validation", "mounted"],
setup(e, { emit: x }) {
const t = e, { autoId: a } = ee("segmented-buttons", t), i = x, l = M(""), b = M(!1), d = {
required: (f) => ({
valid: Array.isArray(f) ? f.length > 0 : !!f,
message: "This field is required"
}),
min: (f, m) => ({
valid: !Array.isArray(f) || f.length >= m,
message: `Select at least ${m} option${m > 1 ? "s" : ""}`
}),
max: (f, m) => ({
valid: !Array.isArray(f) || f.length <= m,
message: `Select no more than ${m} option${m > 1 ? "s" : ""}`
})
}, r = (f) => {
if (!t.rules.length) return !0;
for (const m of t.rules) {
if (typeof m == "string") {
if (m.includes(":")) {
const [u, h] = m.split(":"), I = d[u];
if (I) {
const R = I(f, parseInt(h, 10));
if (!R.valid)
return l.value = R.message, !1;
}
} else if (d[m]) {
const u = d[m](f);
if (!u.valid)
return l.value = u.message, !1;
}
continue;
}
if (typeof m == "object") {
if (m.message) {
let u, h;
for (const R in m)
if (R !== "message") {
u = R, h = m[R];
break;
}
const I = d[u];
if (I) {
const R = I(f, h);
if (!R.valid)
return l.value = m.message || R.message, !1;
}
} else if (typeof m.validator == "function" && !m.validator(f))
return l.value = m.message || "Invalid selection", !1;
}
}
return l.value = "", !0;
}, g = C({
get: () => t.modelValue,
set: (f) => {
if (i("update:modelValue", f), i("change", f), t.validateOnChange) {
b.value = !0;
const m = r(f);
i("validation", { valid: m, error: l.value });
}
}
}), V = C(() => ({
"vsui bas