vuetensils
Version:
A 'naked' component library for building accessible, lightweight, on-brand applications.
1,777 lines • 83.3 kB
JavaScript
import { openBlock as o, createBlock as P, Transition as L, withCtx as I, resolveDynamicComponent as j, normalizeClass as d, renderSlot as h, createElementBlock as c, createTextVNode as D, createCommentVNode as p, withModifiers as B, Fragment as k, renderList as O, createElementVNode as f, mergeProps as g, toHandlers as V, resolveDirective as _e, withDirectives as N, normalizeProps as y, guardReactiveProps as S, withKeys as J, toDisplayString as w, vShow as ue, createVNode as F, normalizeStyle as R, toHandlerKey as we, vModelSelect as ke, vModelText as Se, vModelDynamic as De, reactive as $, TransitionGroup as Ee, watch as Ve, nextTick as X, computed as Oe } from "vue";
const E = (e, s) => {
const t = e.__vccOpts || e;
for (const [l, n] of s)
t[l] = n;
return t;
}, Ie = {
name: "VAlert",
model: {
prop: "modelValue",
event: "update:modelValue"
},
props: {
tag: {
type: String,
default: "div"
},
modelValue: {
type: [Boolean, Number],
default: !0
},
dismissible: Boolean,
dismissLabel: {
type: [String, Boolean],
default: "Dismiss this alert"
},
transition: {
type: String,
default: void 0
},
classes: {
type: Object,
default: () => ({})
}
},
data: () => ({
dismissed: !1,
timerId: null
}),
watch: {
modelValue: {
handler(e) {
e && (this.dismissed = !1), typeof e == "number" && (this.clearTimer(), this.countdown());
},
immediate: !0
}
},
beforeUnmount() {
this.clearTimer();
},
beforeDestroy() {
this.clearTimer();
},
methods: {
dismiss() {
this.$emit("dismiss"), this.dismissed = !0, typeof this.modelValue == "number" ? (this.$emit("update:modelValue", 0), this.$emit("update", 0), this.clearTimer()) : (this.$emit("update:modelValue", !1), this.$emit("update", !1));
},
countdown() {
const { modelValue: e } = this;
typeof e != "number" || e <= 0 || (this.timerId = setTimeout(() => {
this.$emit("update:modelValue", e - 1), this.$emit("update", e - 1);
}, 1e3));
},
clearTimer() {
const { timerId: e } = this;
e && (clearInterval(e), this.timerId = null);
}
}
}, Me = ["aria-label"];
function Ce(e, s, t, l, n, i) {
return o(), P(L, { name: t.transition }, {
default: I(() => [
!e.dismissed && t.modelValue ? (o(), P(j(t.tag), {
key: 0,
role: "alert",
class: d(["vts-alert", t.classes.root])
}, {
default: I(() => [
h(e.$slots, "default"),
t.dismissible ? (o(), c("button", {
key: 0,
"aria-label": t.dismissLabel || null,
class: d(["vts-alert__dismiss", t.classes.dismiss]),
type: "button",
onClick: s[0] || (s[0] = (...a) => i.dismiss && i.dismiss(...a))
}, [
h(e.$slots, "dismiss", {}, () => [
D("×")
])
], 10, Me)) : p("", !0)
]),
_: 3
}, 8, ["class"])) : p("", !0)
]),
_: 3
}, 8, ["name"]);
}
const Te = /* @__PURE__ */ E(Ie, [["render", Ce]]), Pe = {
name: "VAsync",
props: {
await: {
type: [Promise, Function],
default: () => Promise.resolve()
},
default: {
type: void 0,
default: void 0
}
},
emits: ["pending", "resolve", "reject", "finally"],
data() {
return {
pending: !1,
results: this.default,
error: null,
done: !1
};
},
watch: {
await: {
handler: "awaitOn",
immediate: !0
},
pending: {
handler(e) {
this.$emit("pending", e);
},
immediate: !0
}
},
methods: {
awaitOn(e) {
if (e && (e = typeof e == "function" ? e() : e, !!e.then))
return this.pending = !0, this.results = this.default, this.error = null, e.then((s) => {
this.results = typeof s > "u" ? this.default : s, this.$emit("resolve", s);
}).catch((s) => {
s instanceof Error && (s = {
name: s.name,
message: s.message
}), this.error = s, this.$emit("reject", s);
}).finally(() => {
this.pending = !1, this.done = !0, this.$emit("finally");
});
}
},
render() {
const { pending: e, error: s, results: t, done: l } = this;
let n = this.$slots;
const i = n.pending, a = n.rejected, r = n.resolved, u = n.default;
if (e && i)
return i();
if (l && s && a)
return a(s);
if (l && !s && r)
return r(t);
if (u)
return u({
pending: e,
resolved: t,
rejected: s,
results: t,
error: s
});
}
};
const Le = {
name: "VBtn",
inheritAttrs: !1,
props: {
action: { type: String, default: "" },
data: { type: Object, default: () => ({}) }
},
emits: ["submit"],
computed: {
tag() {
const e = this.$attrs || {};
return e.to ? "RouterLink" : e.href ? "a" : "button";
},
type() {
if (this.tag === "button")
return this.$attrs.type || "button";
},
listeners() {
return this.$attrs;
}
}
}, Fe = ["action"], Ae = ["value", "name"];
function Be(e, s, t, l, n, i) {
return t.action && t.data ? (o(), c("form", {
key: 0,
action: t.action,
method: "POST",
class: "vts-btn__form",
onSubmit: s[0] || (s[0] = B((a) => e.$emit("submit", a), ["prevent"]))
}, [
(o(!0), c(k, null, O(t.data, (a, r) => (o(), c("input", {
key: r,
value: a,
name: String(r),
type: "hidden",
hidden: "",
autocomplete: "off",
"aria-hidden": "true",
tabindex: "-1"
}, null, 8, Ae))), 128)),
f("button", g({ type: "submit" }, e.$attrs, { class: "vts-btn" }, V(i.listeners, !0)), [
h(e.$slots, "default")
], 16)
], 40, Fe)) : (o(), P(j(i.tag), g({
key: 1,
class: "vts-btn",
type: i.type
}, e.$attrs, V(i.listeners)), {
default: I(() => [
h(e.$slots, "default")
]),
_: 3
}, 16, ["type"]));
}
const xe = /* @__PURE__ */ E(Le, [["render", Be]]), v = Object.freeze({
TAB: 9,
ENTER: 13,
ESC: 27,
SPACE: 32,
PAGEUP: 33,
PAGEDOWN: 34,
END: 35,
HOME: 36,
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40
}), Q = (e) => e.focus(), Ne = {
mounted: Q,
inserted: Q
};
function Z(e, s) {
e._vtsClickout = {
stop: (t) => t.stopPropagation()
}, document.body.addEventListener("click", s.value), e.addEventListener("click", e._vtsClickout.stop);
}
function ee(e, s) {
document.body.removeEventListener("click", s.value), e.removeEventListener("click", e._vtsClickout.stop);
}
const fe = {
mounted: Z,
unmounted: ee,
bind: Z,
unbind: ee
};
function he(e) {
const s = document.activeElement, t = document.createElement("textarea");
t.value = e, t.setAttribute("readonly", ""), t.style.position = "absolute", t.style.left = "-9999px", t.style.fontSize = "12pt", document.body.append(t), t.select(), document.execCommand("copy"), t.remove(), s && s.focus();
}
function te(e, s) {
e._vtsCopy = () => he(s.value), e.addEventListener("click", e._vtsCopy);
}
function se(e, s) {
e.removeEventListener("click", e._vtsCopy), e._vtsCopy = () => he(s.value), e.addEventListener("click", e._vtsCopy);
}
function ne(e) {
e.removeEventListener("click", e._vtsCopy);
}
const je = {
mounted: te,
updated: se,
unmounted: ne,
bind: te,
update: se,
unbind: ne
};
function ie(e, s) {
e._vtsFocusout = () => {
requestAnimationFrame(() => {
e.contains(document.activeElement) || s.value();
});
}, e.addEventListener("focusout", e._vtsFocusout);
}
function ae(e) {
e._vtsFocusout && e.removeEventListener("focusout", e._vtsFocusout);
}
const ze = {
mounted: ie,
unmounted: ae,
bind: ie,
unbind: ae
};
function q(e) {
e._vtsIntersect && (e._vtsIntersect.unobserve(e), delete e._vtsIntersect);
}
function le(e, { value: s, modifiers: t }) {
const l = {
...s
}, { enter: n, exit: i, once: a } = t;
l.root && (l.root = typeof l.root == "string" ? document.querySelector(l.root) : l.root);
const r = { ...s };
s instanceof Function && (n && (r.onEnter = s), i && (r.onExit = s), !n && !i && (r.onChange = s));
const u = new IntersectionObserver(([m]) => {
const b = Array.isArray(l.threshold), _ = {};
for (const M in m)
_[M] = m[M];
_.isIntersecting = b ? l.threshold.includes(m.intersectionRatio) : m.intersectionRatio === l.threshold, _.isIntersecting ? r.onEnter && r.onEnter(_, e) : r.onExit && r.onExit(_, e), r.onChange && r.onChange(_, e), a && q(e);
}, l);
u.observe(e), e._vtsIntersect = u;
}
const Ue = {
mounted: le,
unmounted: q,
inserted: le,
unbind: q
}, ve = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
autofocus: Ne,
clickout: fe,
copy: je,
focusout: ze,
intersect: Ue
}, Symbol.toStringTag, { value: "Module" })), G = [
'a[href]:not([tabindex^="-"])',
'area[href]:not([tabindex^="-"])',
'input:not([disabled]):not([type="hidden"]):not([aria-hidden]):not([tabindex^="-"])',
'select:not([disabled]):not([aria-hidden]):not([tabindex^="-"])',
'textarea:not([disabled]):not([aria-hidden]):not([tabindex^="-"])',
'button:not([disabled]):not([aria-hidden]):not([tabindex^="-"]):not([tabindex^="-"])',
'iframe:not([tabindex^="-"])',
'object:not([tabindex^="-"])',
'embed:not([tabindex^="-"])',
'[contenteditable]:not([tabindex^="-"])',
'[tabindex]:not([tabindex^="-"])'
];
function T(e = 10, s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") {
let t = "";
for (let l = 0; l < e; l++)
t += s.charAt(Math.floor(Math.random() * s.length));
return t;
}
function K(e, s) {
return Object.prototype.toString.call(e).slice(8, -1).toLowerCase() === s.toLowerCase();
}
function He(e, s) {
const t = Array.from(e.querySelectorAll(G));
if (!t.length) {
s.preventDefault();
return;
}
if (!e.contains(document.activeElement))
s.preventDefault(), t[0].focus();
else {
const l = t.indexOf(document.activeElement);
s.shiftKey && l === 0 && (t[t.length - 1].focus(), s.preventDefault()), !s.shiftKey && l === t.length - 1 && (t[0].focus(), s.preventDefault());
}
}
function re(e, s) {
return e.getFullYear() === s.getFullYear() && e.getMonth() === s.getMonth() && e.getDate() === s.getDate();
}
const Ye = [
v.UP,
v.DOWN,
v.LEFT,
v.RIGHT,
v.PAGEUP,
v.PAGEDOWN,
v.HOME,
v.END
], Ke = {
selectDate: "Select Date",
showCalendar: "show calendar",
previousMonth: "previous month",
nextMonth: "next month",
previousYear: "previous year",
nextYear: "next year"
}, We = {
name: "VDate",
directives: {
clickout: fe
},
model: {
prop: "date",
event: "update"
},
props: {
modelValue: {
type: [Date, String],
default: () => new Date()
},
date: {
type: [Date, String],
default: () => new Date()
},
min: {
type: [Date, String],
default: ""
},
max: {
type: [Date, String],
default: ""
},
id: {
type: String,
default: () => `vts-${T(4)}`
},
daysOfWeek: {
type: Object,
default: () => Object.freeze({
Su: "Sunday",
Mo: "Monday",
Tu: "Tuesday",
We: "Wednesday",
Th: "Thursday",
Fr: "Friday",
Sa: "Saturday"
})
},
monthLabels: {
type: Array,
default: () => [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
]
},
buttonLabels: {
type: Object,
default: () => Object.freeze(Ke)
},
classes: {
type: Object,
default: () => ({})
}
},
emits: ["update", "update:modelValue"],
data() {
return {
show: !1,
previousActiveEl: null,
focusedDate: new Date(this.modelValue || this.date),
selectedDate: new Date(this.modelValue || this.date)
};
},
computed: {
monthYear() {
const { monthLabels: e, focusedDate: s } = this;
return `${e[s.getMonth()]} ${s.getFullYear()}`;
},
disableNav() {
const { focusedDate: e, min: s, max: t } = this, l = {}, n = new Date(s), i = new Date(t);
return s && (l.prevYear = e.getFullYear() <= n.getFullYear(), l.prevMonth = e.getMonth() <= n.getMonth()), t && (l.nextYear = e.getFullYear() >= i.getFullYear(), l.nextMonth = e.getMonth() >= i.getMonth()), l;
},
daysByWeeks() {
const { focusedDate: e, selectedDate: s, min: t, max: l } = this, n = new Date(
e.getFullYear(),
e.getMonth(),
1
), i = n.getDay();
n.setDate(n.getDate() - i);
const a = new Date(
e.getFullYear(),
e.getMonth() + 1,
0
).getDate(), r = new Date(n), u = i + a < 36 ? 5 : 6, m = [];
for (let b = 0; b < u; b++) {
m.push([]);
for (let _ = 0; _ < 7; _++) {
const M = new Date(r);
let A = !1;
t && (A = M < new Date(t)), l && !A && (A = M > new Date(l)), m[b].push({
date: M,
isFocused: re(M, e),
isSelected: re(M, s),
disabled: A
}), r.setDate(r.getDate() + 1);
}
}
return m;
},
toggle() {
const { show: e } = this;
return {
bind: {
"aria-label": this.buttonLabels.selectDate,
"aria-expanded": "" + e
},
on: {
click: () => {
this.show = !e;
}
}
};
}
},
watch: {
show(e) {
const { previousActiveEl: s, date: t } = this;
e ? (this.previousActiveEl = document.activeElement, this.focusedDate = new Date(t), this.$nextTick(() => {
this.$el.querySelector('button[aria-selected="true"]').focus();
})) : s && s.focus();
},
selectedDate(e) {
this.$emit("update", e), this.$emit("update:modelValue", e), this.show = !1;
}
},
methods: {
incrementMonthBy(e) {
const { focusedDate: s } = this, t = new Date(s);
t.setMonth(t.getMonth() + e + 1), t.setDate(0);
const l = new Date(s);
l.setDate(Math.min(l.getDate(), t.getDate())), l.setMonth(l.getMonth() + e), this.focusedDate = l;
},
incrementYearBy(e) {
const s = new Date(this.focusedDate);
s.setFullYear(s.getFullYear() + e), this.focusedDate = s;
},
onClick({ target: e }) {
e.classList.contains("vts-date__day") && (this.selectedDate = new Date(e.value));
},
onKeydown(e) {
if (!e.target.classList.contains("vts-date__day") || !Ye.includes(e.keyCode))
return;
e.stopPropagation(), e.preventDefault();
const { focusedDate: s, min: t, max: l } = this, n = new Date(s);
switch (e.keyCode) {
case v.ENTER:
case v.SPACE:
this.selectedDate = n;
return;
case v.RIGHT:
n.setDate(n.getDate() + 1);
break;
case v.LEFT:
n.setDate(n.getDate() - 1);
break;
case v.DOWN:
n.setDate(n.getDate() + 7);
break;
case v.UP:
n.setDate(n.getDate() - 7);
break;
case v.PAGEUP:
e.shiftKey ? n.setFullYear(s.getFullYear() - 1) : n.setMonth(s.getMonth() - 1);
break;
case v.PAGEDOWN:
e.shiftKey ? n.setFullYear(s.getFullYear() + 1) : n.setMonth(s.getMonth() + 1);
break;
case v.HOME:
n.setDate(n.getDate() - n.getDay());
break;
case v.END:
n.setDate(n.getDate() + (6 - n.getDay()));
break;
}
const i = t && new Date(t), a = l && new Date(l);
i && n < i || a && n > a || (this.focusedDate = n, this.$nextTick(() => {
this.$el.querySelector('button[aria-selected="true"]').focus();
}));
},
onTab(e) {
const s = this.$refs.calendar;
He(s, e);
},
onClickout(e) {
const { show: s } = this;
e.preventDefault(), s && (this.show = !1);
}
}
}, qe = ["id"], Re = ["aria-label", "aria-expanded"], $e = ["aria-label"], Ge = ["aria-labelledby"], Je = { class: "vts-date__navigation" }, Xe = ["aria-label", "disabled"], Qe = ["aria-label", "disabled"], Ze = ["id"], et = ["aria-label", "disabled"], tt = ["aria-label", "disabled"], st = ["aria-labelledby"], nt = ["abbr"], it = ["tabindex", "aria-selected", "value", "disabled"];
function at(e, s, t, l, n, i) {
const a = _e("clickout");
return N((o(), c("div", {
id: t.id,
class: d(["vtd-date", t.classes.root])
}, [
h(e.$slots, "default", y(S(i.toggle)), () => [
f("button", {
"aria-label": t.buttonLabels.selectDate,
"aria-expanded": n.show ? "true" : "false",
type: "button",
class: d(["vtd-date__toggle", t.classes.toggle]),
onClick: s[0] || (s[0] = (r) => n.show = !n.show)
}, [
f("span", {
role: "img",
"aria-label": t.buttonLabels.showCalendar
}, " 📅 ", 8, $e)
], 10, Re)
]),
N(f("div", {
ref: "calendar",
class: d(["", ["vtd-date__wrapper", t.classes.wrapper]]),
role: "dialog",
"aria-modal": "true",
"aria-labelledby": `${t.id}-dialog-label`,
onClick: s[5] || (s[5] = (...r) => i.onClick && i.onClick(...r)),
onKeydown: [
s[6] || (s[6] = (...r) => i.onKeydown && i.onKeydown(...r)),
s[7] || (s[7] = J((...r) => i.onTab && i.onTab(...r), ["tab"])),
s[8] || (s[8] = J((r) => n.show = !1, ["esc"]))
]
}, [
f("div", Je, [
f("button", {
class: d(["vtd-date__prev-year", t.classes.prevYear]),
"aria-label": t.buttonLabels.previousYear,
type: "button",
disabled: i.disableNav.prevYear,
onClick: s[1] || (s[1] = (r) => i.incrementYearBy(-1))
}, [
h(e.$slots, "prevYearLabel", {}, () => [
D("↞")
])
], 10, Xe),
f("button", {
class: d(["vtd-date__prev-month", t.classes.prevMonth]),
"aria-label": t.buttonLabels.previousMonth,
type: "button",
disabled: i.disableNav.prevMonth,
onClick: s[2] || (s[2] = (r) => i.incrementMonthBy(-1))
}, [
h(e.$slots, "prevMonthLabel", {}, () => [
D("←")
])
], 10, Qe),
f("h4", {
id: `${t.id}-dialog-label`,
class: d(["vtd-date__title", t.classes.title]),
"aria-live": "polite"
}, w(i.monthYear), 11, Ze),
f("button", {
class: d(["vtd-date__next-month", t.classes.nextMonth]),
"aria-label": t.buttonLabels.nextMonth,
type: "button",
disabled: i.disableNav.nextMonth,
onClick: s[3] || (s[3] = (r) => i.incrementMonthBy(1))
}, [
h(e.$slots, "nextMonthLabel", {}, () => [
D("→")
])
], 10, et),
f("button", {
class: d(["vtd-date__next-year", t.classes.nextYear]),
"aria-label": t.buttonLabels.nextYear,
type: "button",
disabled: i.disableNav.nextYear,
onClick: s[4] || (s[4] = (r) => i.incrementYearBy(1))
}, [
h(e.$slots, "nextYearLabel", {}, () => [
D("↠")
])
], 10, tt)
]),
f("table", {
class: d(["vtd-date__calendar", t.classes.calendar]),
role: "grid",
"aria-labelledby": `${t.id}-dialog-label`
}, [
f("thead", {
class: d(["vtd-date__thead", t.classes.thead])
}, [
f("tr", {
class: d(["vtd-date__week", t.classes.week])
}, [
(o(!0), c(k, null, O(t.daysOfWeek, (r, u) => (o(), c("th", {
key: u,
abbr: r,
scope: "col",
class: d(["vtd-date__th", t.classes.th])
}, w(u), 11, nt))), 128))
], 2)
], 2),
f("tbody", {
class: d(["vtd-date__tbody", t.classes.tbody])
}, [
(o(), c(k, null, O(6, (r) => f("tr", {
key: r,
class: d(["vtd-date__tr", t.classes.tr])
}, [
(o(!0), c(k, null, O(i.daysByWeeks[r - 1], (u) => (o(), c("td", {
key: u.date.toString(),
class: d([
"vts-date__td",
{ "vts-date__td--focused": u.isFocused },
{ "vts-date__td--selected": u.isSelected },
t.classes.td,
{ [t.classes.tdFocused]: t.classes.tdFocused && u.isFocused },
{ [t.classes.tdSelected]: t.classes.tdSelected && u.isSelected }
])
}, [
f("button", {
class: d([
"vts-date__day",
{ "vts-date__day--focused": u.isFocused },
{ "vts-date__day--selected": u.isSelected },
t.classes.day,
{ [t.classes.dayFocused]: t.classes.dayFocused && u.isFocused },
{
[t.classes.daySelected]: t.classes.daySelected && u.isSelected
}
]),
tabindex: u.isFocused ? "0" : "-1",
"aria-selected": u.isFocused,
value: u.date,
disabled: u.disabled,
type: "button"
}, w(u.date.getDate()), 11, it)
], 2))), 128))
], 2)), 64))
], 2)
], 10, st)
], 42, Ge), [
[ue, n.show]
])
], 10, qe)), [
[a, i.onClickout]
]);
}
const lt = /* @__PURE__ */ E(We, [["render", at]]);
const rt = {
name: "VDialog",
inheritAttrs: !1,
model: {
prop: "showing",
event: "update:modelValue"
},
props: {
modelValue: Boolean,
showing: Boolean,
tag: {
type: String,
default: "div"
},
dismissible: {
type: Boolean,
default: !0
},
width: {
type: String,
default: ""
},
inlineSize: {
type: String,
default: ""
},
maxWidth: {
type: String,
default: ""
},
maxInlineSize: {
type: String,
default: ""
},
noScroll: Boolean,
transition: {
type: String,
default: ""
},
bgTransition: {
type: String,
default: ""
},
contentTransition: {
type: String,
default: ""
},
classes: {
type: Object,
default: () => ({})
}
},
emits: ["update", "update:modelValue", "open", "close"],
data() {
return {
localShow: this.modelValue || this.showing,
activeElement: null
};
},
computed: {
slots() {
return this.$slots;
}
},
watch: {
showing(e) {
this.localShow = e;
},
modelValue(e) {
this.localShow = e;
},
localShow: {
handler(e, s) {
if (!(typeof window > "u")) {
if (e && e != s)
this.activeElement = document.activeElement, this.onOpen();
else {
this.onClose();
const { activeElement: t } = this;
t && t.focus && this.$nextTick(() => {
t.focus();
});
}
this.$emit("update", e), this.$emit("update:modelValue", e);
}
}
}
},
destroyed() {
this.onClose();
},
methods: {
onOpen() {
const { onClick: e, onKeydown: s, noScroll: t } = this;
window.addEventListener("click", e), window.addEventListener("keydown", s), t && document.body.style.setProperty("overflow", "hidden"), this.$nextTick(() => {
var l;
return (l = this.$refs.content) == null ? void 0 : l.focus();
}), this.$emit("open");
},
onClose() {
const { onClick: e, onKeydown: s, noScroll: t } = this;
window.removeEventListener("click", e), window.removeEventListener("keydown", s), t && document.body.style.removeProperty("overflow"), this.$emit("close");
},
onClick(e) {
e.target.classList.contains("vts-dialog") && this.dismissible && (this.localShow = !1);
},
onKeydown(e) {
if (e.keyCode === v.ESC && this.dismissible && (this.localShow = !1), e.keyCode === v.TAB) {
const s = this.$refs.content;
if (!s)
return;
const t = Array.from(
s.querySelectorAll(G.join(","))
);
if (!t.length) {
e.preventDefault();
return;
}
if (!s.contains(document.activeElement))
e.preventDefault(), t[0].focus();
else {
const l = t.indexOf(
document.activeElement
);
e.shiftKey && l === 0 && (t[t.length - 1].focus(), e.preventDefault()), !e.shiftKey && l === t.length - 1 && (t[0].focus(), e.preventDefault());
}
}
}
}
}, ot = { key: 0 };
function dt(e, s, t, l, n, i) {
return n.localShow || i.slots.toggle ? (o(), c("span", ot, [
i.slots.toggle ? h(e.$slots, "toggle", y(g({ key: 0 }, {
on: {
click: () => n.localShow = !n.localShow
},
bind: {
type: "button",
role: "button",
"aria-haspopup": !0,
"aria-expanded": "" + n.localShow
}
}))) : p("", !0),
F(L, {
name: t.bgTransition || t.transition,
appear: !0
}, {
default: I(() => [
n.localShow ? (o(), c("div", {
key: 0,
class: d(["vts-dialog", t.classes.root, t.classes.bg, e.$attrs.class])
}, [
F(L, { name: t.contentTransition }, {
default: I(() => [
(o(), P(j(t.tag), {
ref: "content",
class: d(["vts-dialog__content", t.classes.content]),
style: R({
width: t.width,
"inline-size": t.inlineSize,
"max-width": t.maxWidth,
"max-inline-size": t.maxInlineSize
}),
tabindex: "-1",
role: "dialog",
"aria-modal": "true"
}, {
default: I(() => [
h(e.$slots, "default", y(S({ close: () => n.localShow = !n.localShow })))
]),
_: 3
}, 8, ["class", "style"]))
]),
_: 3
}, 8, ["name"])
], 2)) : p("", !0)
]),
_: 3
}, 8, ["name"])
])) : p("", !0);
}
const ct = /* @__PURE__ */ E(rt, [["render", dt]]);
const ut = "vts-drawer", ft = {
name: "VDrawer",
model: {
prop: "showing",
event: "update:modelValue"
},
props: {
modelValue: Boolean,
showing: Boolean,
tag: {
type: String,
default: "aside"
},
right: Boolean,
width: {
type: String,
default: ""
},
inlineSize: {
type: String,
default: ""
},
maxWidth: {
type: String,
default: ""
},
maxInlineSize: {
type: String,
default: ""
},
noScroll: Boolean,
transition: {
type: String,
default: ""
},
bgTransition: {
type: String,
default: ""
},
classes: {
type: Object,
default: () => ({})
}
},
emits: ["update", "update:modelValue", "open", "close"],
data() {
return {
localShow: this.modelValue || this.showing,
activeElement: null
};
},
computed: {
slots() {
return this.$slots;
}
},
watch: {
showing(e) {
this.localShow = e;
},
modelValue(e) {
this.localShow = e;
},
localShow: {
handler(e, s) {
if (!(typeof window > "u")) {
if (e && e != s)
this.activeElement = document.activeElement, this.onOpen();
else {
this.onClose();
const { activeElement: t } = this;
t && t.focus && this.$nextTick(() => {
t.focus();
});
}
this.$emit("update", e), this.$emit("update:modelValue", e);
}
}
}
},
destroyed() {
this.onClose();
},
methods: {
onOpen() {
const { onClick: e, onKeydown: s, noScroll: t } = this;
window.addEventListener("click", e), window.addEventListener("keydown", s), t && document.body.style.setProperty("overflow", "hidden"), this.$nextTick(() => this.$refs.content.focus()), this.$emit("open");
},
onClose() {
const { onClick: e, onKeydown: s, noScroll: t } = this;
window.removeEventListener("click", e), window.removeEventListener("keydown", s), t && document.body.style.removeProperty("overflow"), this.$emit("close");
},
onClick(e) {
e.target.classList.contains(ut) && (this.localShow = !1);
},
onKeydown(e) {
if (e.keyCode === v.ESC && (this.localShow = !1), e.keyCode === v.TAB) {
const s = this.$refs.content;
if (!s)
return;
const t = Array.from(
s.querySelectorAll(G.join(","))
);
if (!t.length) {
e.preventDefault();
return;
}
if (!s.contains(document.activeElement))
e.preventDefault(), t[0].focus();
else {
const l = t.indexOf(
document.activeElement
);
e.shiftKey && l === 0 && (t[t.length - 1].focus(), e.preventDefault()), !e.shiftKey && l === t.length - 1 && (t[0].focus(), e.preventDefault());
}
}
}
}
}, ht = { key: 0 };
function vt(e, s, t, l, n, i) {
return n.localShow || i.slots.toggle ? (o(), c("span", ht, [
i.slots.toggle ? h(e.$slots, "toggle", y(g({ key: 0 }, {
on: {
click: () => n.localShow = !n.localShow
},
bind: {
type: "button",
role: "button",
"aria-haspopup": !0,
"aria-expanded": "" + n.localShow
}
}))) : p("", !0),
F(L, {
name: t.bgTransition || t.transition,
appear: ""
}, {
default: I(() => [
n.localShow ? (o(), c("div", {
key: 0,
class: d(["vts-drawer", t.classes.root, t.classes.bg, e.$attrs.class])
}, [
F(L, {
name: t.transition,
appear: ""
}, {
default: I(() => [
n.localShow ? (o(), P(j(t.tag), {
key: 0,
ref: "content",
class: d([
"vts-drawer__content",
{ "vts-drawer__content--right": !!t.right },
t.classes.content
]),
style: R({
width: t.width,
"inline-size": t.inlineSize,
"max-width": t.maxWidth,
"max-inline-size": t.maxInlineSize
}),
tabindex: "-1"
}, {
default: I(() => [
h(e.$slots, "default", y(S({ close: () => n.localShow = !n.localShow })))
]),
_: 3
}, 8, ["class", "style"])) : p("", !0)
]),
_: 3
}, 8, ["name"])
], 2)) : p("", !0)
]),
_: 3
}, 8, ["name"])
])) : p("", !0);
}
const mt = /* @__PURE__ */ E(ft, [["render", vt]]);
const yt = {
name: "VDrawer",
props: {
text: {
type: String,
default: ""
},
position: {
type: String,
default: "bottom",
validator(e) {
return ["top", "bottom"].includes(e);
}
},
transition: {
type: String,
default: ""
},
classes: {
type: Object,
default: () => ({})
}
},
data: () => ({
isHovered: !1,
isFocused: !1
}),
mounted() {
document.addEventListener("click", this.onClickout);
},
beforeDestroy() {
document.removeEventListener("click", this.onClickout);
},
beforeUnmount() {
document.removeEventListener("click", this.onClickout);
},
methods: {
onClickout(e) {
this.$el.contains(e.target) || (this.isFocused = !1);
},
onFocusout(e) {
this.$el.contains(e.relatedTarget) || (this.isFocused = !1);
}
}
}, bt = ["aria-expanded"];
function gt(e, s, t, l, n, i) {
return o(), c("div", {
class: d(["vts-dropdown", t.classes.root]),
onMouseenter: s[1] || (s[1] = (a) => e.isHovered = !0),
onMouseleave: s[2] || (s[2] = (a) => e.isHovered = !1),
onFocus: s[3] || (s[3] = (a) => e.isFocused = !0),
onBlur: s[4] || (s[4] = (a) => e.isFocused = !1),
onFocusout: s[5] || (s[5] = (...a) => i.onFocusout && i.onFocusout(...a))
}, [
f("button", {
"aria-expanded": !!e.isHovered || !!e.isFocused,
"aria-haspopup": "true",
class: d(["vts-dropdown__trigger", t.classes.trigger]),
type: "button",
onClick: s[0] || (s[0] = (a) => e.isFocused = !e.isFocused)
}, [
h(e.$slots, "trigger", {}, () => [
D(w(t.text), 1)
])
], 10, bt),
F(L, { name: t.transition }, {
default: I(() => [
e.isHovered || e.isFocused ? (o(), c("div", {
key: 0,
class: d(["vts-dropdown__content", [`vts-dropdown__content--${t.position}`, t.classes.content]])
}, [
h(e.$slots, "default")
], 2)) : p("", !0)
]),
_: 3
}, 8, ["name"])
], 34);
}
const pt = /* @__PURE__ */ E(yt, [["render", gt]]);
const _t = {
name: "VFile",
model: {
prop: "files",
event: "update"
},
props: {
label: {
type: String,
required: !0
},
id: {
type: String,
default: () => "vts-" + T(4)
},
modelValue: {
type: Array,
default: () => []
},
files: {
type: Array,
default: () => []
},
classes: {
type: Object,
default: () => ({})
}
},
data: () => ({
localFiles: [],
droppable: !1
}),
computed: {
listeners() {
return this.$attrs;
}
},
watch: {
files(e) {
this.localFiles = e;
},
modelValue(e) {
this.localFiles = e;
},
localFiles() {
this.droppable = !1;
}
},
methods: {
onChange(e) {
const s = Array.from(e.target.files);
this.localFiles = s, this.$emit("update", s), this.$emit("update:modelValue", s);
},
onDrop(e) {
const s = Array.from(e.dataTransfer.files);
!(this.$attrs.multiple != null) && s.length > 1 && (s.length = 1), this.localFiles = s, this.$emit("update", s), this.$emit("update:modelValue", s);
}
}
}, wt = ["for"], kt = ["id"], St = {
key: 0,
"aria-hidden": "true"
}, Dt = {
key: 1,
"aria-hidden": "true"
};
function Et(e, s, t, l, n, i) {
return o(), c("label", {
for: t.id,
class: d([
"vts-file",
{
"vts-file--droppable": e.droppable,
"vts-file--selected": !!e.localFiles.length
},
t.classes.label
])
}, [
f("input", g({
id: t.id,
ref: "input"
}, e.$attrs, {
type: "file",
class: ["vts-visually-hidden", t.classes.input],
onChange: s[0] || (s[0] = (...a) => i.onChange && i.onChange(...a))
}, V(i.listeners, !0)), null, 16, kt),
f("span", {
class: d(["vts-file__text", t.classes.text])
}, [
h(e.$slots, "label", {}, () => [
D(w(t.label), 1)
])
], 2),
f("div", {
class: d(["vts-file__dropzone", t.classes.dropzone]),
onDragenter: s[5] || (s[5] = B((a) => e.droppable = !0, ["prevent"]))
}, [
h(e.$slots, "default", y(S({ files: e.localFiles, droppable: e.droppable })), () => [
e.localFiles.length ? (o(), c("span", St, [
e.localFiles.length > 1 ? (o(), c(k, { key: 0 }, [
D(w(e.localFiles.length) + " files selected ", 1)
], 64)) : (o(), c(k, { key: 1 }, [
D(w(e.localFiles[0].name), 1)
], 64))
])) : (o(), c("span", Dt, " Choose files or drop here "))
]),
e.droppable ? (o(), c("span", {
key: 0,
class: d(["vts-file__overlay", t.classes.overlay]),
onDrop: s[1] || (s[1] = B((...a) => i.onDrop && i.onDrop(...a), ["prevent"])),
onDragenter: s[2] || (s[2] = B((a) => e.droppable = !0, ["stop"])),
onDragleave: s[3] || (s[3] = B((a) => e.droppable = !1, ["stop"])),
onDragover: s[4] || (s[4] = B(() => {
}, ["prevent"]))
}, [
h(e.$slots, "overlay")
], 34)) : p("", !0)
], 34)
], 10, wt);
}
const Vt = /* @__PURE__ */ E(_t, [["render", Et]]), oe = /* @__PURE__ */ new Set(["INPUT", "SELECT", "TEXTAREA"]), Ot = {
name: "VForm",
props: {
lazy: {
type: Boolean,
default: !1
},
errors: {
type: Object,
default: () => ({})
},
preventNavigation: {
type: Boolean,
default: !1
},
honeypot: {
type: [Boolean, String],
default: !1
}
},
data: () => ({
dirty: !1,
modified: !1,
localInputs: {}
}),
computed: {
listeners() {
return this.$attrs;
},
event() {
return this.lazy ? "change" : "input";
},
valid() {
return !Object.values(this.localInputs).find((e) => !e.valid);
},
error() {
return !this.valid && this.dirty;
},
inputs() {
const e = {}, { localInputs: s, errors: t } = this;
for (const l in s) {
const n = {
...s[l],
error: s[l].dirty && !s[l].valid,
errors: []
}, i = new Map(Object.entries(t || {}));
i.forEach((a, r) => {
if (!n.invalid[r])
return;
const u = i.get(r), m = r.replace("length", "Length"), b = typeof u == "string" ? u : u(n._inputEl[m]);
n.errors.push(b);
}), e[l] = n;
}
return e;
}
},
mounted() {
this.validate();
const e = new MutationObserver(this.validate);
e.observe(this.$el, {
childList: !0,
subtree: !0
}), this.observer = e, this.preventNavigation && window.addEventListener("beforeunload", this.preventNav), this.listeners.invalid && (this.$el.noValidate = !0);
},
beforeRouteLeave(e, s, t) {
this.modified || t(), window.confirm("Leave without saving?") && t();
},
beforeDestroy() {
this.observer.disconnect(), window.removeEventListener("beforeunload", this.preventNav);
},
beforeUnmount() {
this.observer.disconnect();
},
methods: {
checkModified({ target: e }) {
oe.has(e.tagName) && (this.modified = !0);
},
validate() {
const e = this.$el.querySelectorAll("input, textarea, select"), s = {};
e.forEach((t) => {
const { name: l, id: n, validity: i } = t, a = l || n;
if (a)
switch (s[a] = {
_inputEl: t,
valid: i.valid,
dirty: !1,
invalid: {
type: i.typeMismatch,
required: i.valueMissing,
minlength: i.tooShort,
maxlength: i.tooLong,
min: i.rangeOverflow,
max: i.rangeUnderflow,
pattern: i.patternMismatch
}
}, t.type) {
case "checkbox":
s[a].value = t.checked;
break;
case "radio":
t.checked && (s[a].value = t.value);
break;
default:
s[a].value = t.value;
}
}), this.localInputs = s;
},
onEvent() {
this.validate();
},
onBlur({ target: e }) {
oe.has(e.tagName) && (this.dirty = !0, this.localInputs[e.name].dirty = !0);
},
clear() {
this.$el.querySelectorAll("input, textarea, select").forEach((s) => {
["radio", "checkbox"].includes(s.type) ? s.checked = !1 : s.value = "";
});
},
reset() {
this.modified = !1, this.dirty = !1, this.validate();
},
onSubmit(e) {
if (!e.target.checkValidity()) {
this.$emit("invalid", e);
return;
}
this.reset(), this.$emit("valid", e);
},
preventNav(e) {
this.modified && (e.preventDefault(), e.returnValue = "");
}
}
}, It = ["method"], Mt = ["name"];
function Ct(e, s, t, l, n, i) {
return o(), c("form", g({
method: e.$attrs.method || "POST",
class: [
"vts-form",
{
"vts-form--invalid": !i.valid,
"vts-form--dirty": e.dirty,
"vts-form--error": i.error
}
]
}, {
[we(i.event)]: s[0] || (s[0] = (...a) => i.onEvent && i.onEvent(...a))
}, {
onKeydown: s[1] || (s[1] = (...a) => i.checkModified && i.checkModified(...a)),
onChange: s[2] || (s[2] = (...a) => i.checkModified && i.checkModified(...a)),
onSubmit: s[3] || (s[3] = (...a) => i.onSubmit && i.onSubmit(...a)),
onBlurCapture: s[4] || (s[4] = (...a) => i.onBlur && i.onBlur(...a))
}, V(i.listeners, !0)), [
t.honeypot ? (o(), c("input", {
key: 0,
name: typeof t.honeypot == "string" ? t.honeypot : "vts-honeypot",
class: "visually-hidden",
tabindex: "-1",
autocomplete: "off",
"aria-hidden": "true"
}, null, 8, Mt)) : p("", !0),
h(e.$slots, "default", y(S({ valid: i.valid, dirty: e.dirty, modified: e.modified, error: i.error, inputs: i.inputs, clear: i.clear, validate: i.validate })))
], 16, It);
}
const Tt = /* @__PURE__ */ E(Ot, [["render", Ct]]);
const W = "vts-img", Pt = {
name: "VImg",
inheritAttrs: !1,
props: {
src: {
type: String,
required: !0
},
alt: {
type: String,
required: !0
},
srcset: {
type: String,
default: ""
},
placeholder: {
type: String,
default: ""
},
background: {
type: String,
default: ""
},
transitionDuration: {
type: [Number, String],
default: 300
},
classes: {
type: Object,
default: () => ({})
}
},
data: () => ({
dataUrl: ""
}),
computed: {
listeners() {
return this.$attrs;
}
},
watch: {
src: {
handler: "init"
},
srcset: {
handler: "init"
}
},
mounted() {
this.init();
},
beforeUnmount() {
this.observer.disconnect();
},
beforeDestroy() {
this.observer.disconnect();
},
methods: {
init() {
this.dataUrl = this.getDataUrl(), this.observer = new IntersectionObserver(this.handler), this.observer.observe(this.$el);
},
handler([e]) {
const { $el: s } = this;
e.isIntersecting && (s.classList.add(`${W}--loading`), this.loadImg(), this.observer.disconnect());
},
getDataUrl() {
if (typeof window > "u")
return;
const { width: e, height: s } = this.$attrs;
if (!e || !s)
return "";
const t = 100, l = document.createElement("canvas");
return l.width = t, l.height = +s / +e * t, l.toDataURL();
},
loadImg() {
const { src: e, srcset: s } = this, { img: t } = this.$refs;
t.addEventListener("load", this.onLoad), s && (t.srcset = s), t.src = e;
},
onLoad() {
const { $el: e } = this, { img: s, placeholder: t } = this.$refs;
e.classList.remove(`${W}--loading`), e.classList.add(`${W}--loaded`), t && s.addEventListener("transitionend", function l() {
t.remove(), s.removeEventListener("transitionend", l);
}), s.removeEventListener("load", this.onLoad);
}
}
}, Lt = /* @__PURE__ */ f("noscript", null, `
<img
:src="dataUrl"
:class="['vts-img__img', classes.img]"
:alt="alt"
:style="{
transitionDuration: \`\${transitionDuration}ms\`,
}"
:decoding="$attrs.decoding || 'async'"
:role="$attrs.role || alt ? null : 'presentation'"
v-bind="$attrs"
/>
`, -1), Ft = ["src", "decoding"], At = ["src", "alt", "decoding", "role"];
function Bt(e, s, t, l, n, i) {
return o(), c("picture", {
class: d(["vts-img", t.classes.root])
}, [
Lt,
e.dataUrl ? (o(), c("div", {
key: 0,
ref: "placeholder",
class: d(["vts-img__placeholder", t.classes.placeholder]),
style: R({ background: t.background })
}, [
f("img", g({
src: t.placeholder || e.dataUrl,
alt: ""
}, e.$attrs, {
decoding: e.$attrs.decoding || "async"
}), null, 16, Ft)
], 6)) : p("", !0),
f("img", g({
ref: "img",
src: e.dataUrl,
class: ["vts-img__img", t.classes.img],
alt: t.alt,
style: {
transitionDuration: `${t.transitionDuration}ms`
},
decoding: e.$attrs.decoding || "async",
role: e.$attrs.role || t.alt ? null : "presentation"
}, e.$attrs, V(i.listeners, !0)), null, 16, At)
], 2);
}
const xt = /* @__PURE__ */ E(Pt, [["render", Bt]]), de = {
type: [String, Number, Boolean, Array],
default: void 0
};
function ce(e, s) {
e !== s && (this.localValue = e);
}
const Nt = {
name: "VInput",
inheritAttrs: !1,
model: {
event: "update:modelValue"
},
props: {
label: {
type: String,
required: !0
},
name: {
type: String,
required: !0
},
value: de,
modelValue: de,
type: {
type: String,
default: "text"
},
options: {
type: [Array, Object],
default: () => []
},
errors: {
type: Object,
default: () => ({})
},
classes: {
type: Object,
default: () => ({})
}
},
data() {
return {
localValue: this.modelValue || this.value,
valid: !0,
anyInvalid: !1,
dirty: !1,
invalid: {}
};
},
computed: {
bind() {
const { id: e, name: s, valid: t, dirty: l, error: n, errorMessages: i, classes: a, $attrs: r } = this, { class: u, ...m } = r, b = [];
return n && b.push(`${e}__description`), i.length && b.push(`${e}__errors`), {
"aria-invalid": !t,
"aria-describedby": l && b.length ? b.join(" ") : null,
...m,
id: `${e}__input`,
name: s,
class: ["vts-input__input", a.input]
};
},
listeners() {
return this.$attrs;
},
slots() {
return this.$slots;
},
computedOptions() {
const { $attrs: e, localValue: s, type: t } = this;
let l = this.options;
return K(l, "object") && (l = Object.entries(l).map(([n, i]) => ({
value: n,
label: i
}))), l.map((n) => {
if (n = K(n, "object") ? n : { value: n }, Object.assign(n, e, {
label: n.label || n.value,
value: n.value
}), t === "checkbox") {
const i = s || [];
n.checked = i.includes(n.value) || n.checked;
} else
s !== void 0 && typeof s == "string" && (n.checked = n.value === s || n.checked);
return n;
});
},
isMultiple() {
const { multiple: e } = this.$attrs;
return e != null && e != "false";
},
error() {
return !this.valid && this.dirty;
},
errorMessages() {
const { invalid: e, errors: s, $attrs: t } = this, l = [];
return Object.keys(s || {}).forEach((n) => {
if (!e[n])
return;
const i = s[n], a = K(i, "function") ? i(t[n]) : i;
l.push(a);
}), l;
}
},
watch: {
modelValue: ce,
value: ce,
localValue(e) {
this.$emit("update:modelValue", e), this.validate();
},
"$attrs.required": "validateAfterNextTick",
"$attrs.type": "validateAfterNextTick",
"$attrs.min": "validateAfterNextTick",
"$attrs.max": "validateAfterNextTick",
"$attrs.minlength": "validateAfterNextTick",
"$attrs.maxlength": "validateAfterNextTick",
"$attrs.pattern": "validateAfterNextTick"
},
created() {
this.id = this.$attrs.id || "vts-" + T(4);
},
mounted() {
this.validate();
},
methods: {
onSelect(e) {
const s = e.target;
if (this.isMultiple) {
const t = [];
for (const l of s.selectedOptions)
t.push(l.value);
this.localValue = [...t || []];
} else
this.localValue = s.value;
},
onFieldsetInput(e) {
const s = e.target, t = s.value;
if (s.type === "radio") {
this.localValue = t;
return;
}
const n = [...this.localValue || []], i = n.indexOf(t);
i === -1 ? n.push(t) : n.splice(i, 1), this.localValue = n;
},
validate() {
let e = this.$refs.input;
if (Array.isArray(e)) {
if (!e.length)
return;
e = e[0];
}
const { validity: s } = e;
this.anyInvalid = !s.valid, this.valid = s.valid, this.invalid = {
type: s.typeMismatch,
required: s.valueMissing,
minlength: s.tooShort,
maxlength: s.tooLong,
min: s.rangeUnderflow,
max: s.rangeOverflow,
pattern: s.patternMismatch
};
},
async validateAfterNextTick() {
await this.$nextTick(), this.validate();
}
}
}, jt = ["id", "type"], zt = ["for"], Ut = ["checked"], Ht = ["for"], Yt = ["for"], Kt = ["type"], Wt = ["id"], qt = ["id"];
function Rt(e, s, t, l, n, i) {
return o(), c("div", {
class: d([
"vts-input",
`vts-input--${t.type}`,
{
"vts-input--required": e.$attrs.hasOwnProperty("required"),
"vts-input--invalid": !n.valid,
"vts-input--dirty": n.dirty,
"vts-input--error": i.error
},
e.$attrs.class,
t.classes.root
])
}, [
["radio", "checkbox"].includes(t.type) && i.computedOptions.length ? (o(), c("fieldset", {
key: 0,
class: d(["vts-input__fieldset", t.classes.fieldset])
}, [
t.label ? (o(), c("legend", {
key: 0,
class: d(["vts-input__legend", t.classes.legend])
}, [
h(e.$slots, "label", y(S({
valid: n.valid,
dirty: n.dirty,
error: i.error,
invalid: n.invalid,
anyInvalid: n.anyInvalid,
errors: i.errorMessages
})), () => [
D(w(t.label), 1)
])
], 2)) : p("", !0),
f("div", {
class