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