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