@m3ui-vue/m3ui-vue 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MMenuItem-_n5OG5MT.js +514 -0
- package/dist/MMenuItem-_n5OG5MT.js.map +1 -0
- package/dist/common-VrOaLkjh.js +6751 -0
- package/dist/common-VrOaLkjh.js.map +1 -0
- package/dist/components/MAbsolute.vue.d.ts +27 -0
- package/dist/components/MAppLayout.vue.d.ts +27 -0
- package/dist/components/MAspectRatio.vue.d.ts +18 -0
- package/dist/components/MBadge.vue.d.ts +6 -0
- package/dist/components/MBox.vue.d.ts +27 -0
- package/dist/components/MCenter.vue.d.ts +18 -0
- package/dist/components/MContainer.vue.d.ts +1 -1
- package/dist/components/MDivider.vue.d.ts +1 -1
- package/dist/components/MEmoji.vue.d.ts +10 -0
- package/dist/components/MEmojiButton.vue.d.ts +21 -0
- package/dist/components/MEmojiSelector.vue.d.ts +21 -0
- package/dist/components/MFab.vue.d.ts +2 -0
- package/dist/components/MFixed.vue.d.ts +28 -0
- package/dist/components/MFlex.vue.d.ts +28 -0
- package/dist/components/MFullscreen.vue.d.ts +20 -0
- package/dist/components/MGrid.vue.d.ts +1 -1
- package/dist/components/MIconButton.vue.d.ts +1 -1
- package/dist/components/MList.vue.d.ts +30 -0
- package/dist/components/MListItem.vue.d.ts +60 -0
- package/dist/components/MListSubheader.vue.d.ts +18 -0
- package/dist/components/MMasonry.vue.d.ts +1 -1
- package/dist/components/MOverlay.vue.d.ts +26 -0
- package/dist/components/MRelative.vue.d.ts +13 -0
- package/dist/components/MResponsive.vue.d.ts +21 -0
- package/dist/components/MScrollable.vue.d.ts +20 -0
- package/dist/components/MSection.vue.d.ts +31 -0
- package/dist/components/MSpacer.vue.d.ts +3 -0
- package/dist/components/MStack.vue.d.ts +2 -2
- package/dist/components/MSticky.vue.d.ts +20 -0
- package/dist/components/MSubtitle.vue.d.ts +22 -0
- package/dist/components/MText.vue.d.ts +27 -0
- package/dist/components/MTitle.vue.d.ts +22 -0
- package/dist/data/emojis.d.ts +10 -0
- package/dist/index.d.ts +30 -0
- package/dist/m3ui-vue.css +1 -1
- package/dist/m3ui.js +3767 -3224
- package/dist/m3ui.js.map +1 -1
- package/dist/markdown.js +50 -7
- package/dist/markdown.js.map +1 -1
- package/dist/rich-text-editor.js +188 -116
- package/dist/rich-text-editor.js.map +1 -1
- package/dist/styles/theme.css +4 -0
- package/dist/styles.css +1 -1
- package/package.json +5 -1
- package/src/components/MAbsolute.vue +68 -0
- package/src/components/MAppLayout.vue +45 -0
- package/src/components/MAspectRatio.vue +20 -0
- package/src/components/MBadge.vue +27 -1
- package/src/components/MBox.vue +66 -0
- package/src/components/MCenter.vue +21 -0
- package/src/components/MEmoji.vue +19 -0
- package/src/components/MEmojiButton.vue +60 -0
- package/src/components/MEmojiSelector.vue +126 -0
- package/src/components/MFab.vue +6 -3
- package/src/components/MFixed.vue +64 -0
- package/src/components/MFlex.vue +63 -0
- package/src/components/MFullscreen.vue +23 -0
- package/src/components/MIconButton.vue +2 -2
- package/src/components/MList.vue +40 -0
- package/src/components/MListItem.vue +299 -0
- package/src/components/MListSubheader.vue +18 -0
- package/src/components/MMarkdown.vue +157 -4
- package/src/components/MOverlay.vue +46 -0
- package/src/components/MRelative.vue +5 -0
- package/src/components/MResponsive.vue +48 -0
- package/src/components/MRichTextEditor.vue +97 -58
- package/src/components/MScrollable.vue +31 -0
- package/src/components/MSection.vue +65 -0
- package/src/components/MSpacer.vue +3 -0
- package/src/components/MSticky.vue +27 -0
- package/src/components/MSubtitle.vue +29 -0
- package/src/components/MText.vue +107 -0
- package/src/components/MTitle.vue +29 -0
- package/src/components/MTour.vue +84 -43
- package/src/data/emojis.ts +214 -0
- package/src/index.ts +30 -0
- package/src/styles/theme.css +4 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import { t as e } from "./MIcon-CaEooCmZ.js";
|
|
2
|
+
import { t } from "./_plugin-vue_export-helper-B3ysoDQm.js";
|
|
3
|
+
import { Fragment as n, Teleport as r, Transition as i, computed as a, createBlock as o, createCommentVNode as s, createElementBlock as c, createElementVNode as l, createTextVNode as u, createVNode as d, defineComponent as f, normalizeClass as p, normalizeStyle as m, onBeforeUnmount as h, onMounted as g, onUnmounted as _, openBlock as v, ref as y, renderSlot as b, resolveDynamicComponent as x, toDisplayString as S, unref as C, useId as w, useSlots as T, watch as E, withCtx as D, withModifiers as O } from "vue";
|
|
4
|
+
//#region src/composables/useFieldBg.ts
|
|
5
|
+
var k = [
|
|
6
|
+
"bg-surface-container-highest",
|
|
7
|
+
"bg-surface-container-high",
|
|
8
|
+
"bg-surface-container-low",
|
|
9
|
+
"bg-surface-container-lowest",
|
|
10
|
+
"bg-surface-container",
|
|
11
|
+
"bg-surface-variant",
|
|
12
|
+
"bg-surface-bright",
|
|
13
|
+
"bg-surface-dim",
|
|
14
|
+
"bg-surface",
|
|
15
|
+
"bg-background",
|
|
16
|
+
"bg-inverse-surface",
|
|
17
|
+
"bg-primary-container",
|
|
18
|
+
"bg-secondary-container",
|
|
19
|
+
"bg-tertiary-container",
|
|
20
|
+
"bg-error-container",
|
|
21
|
+
"bg-primary",
|
|
22
|
+
"bg-secondary",
|
|
23
|
+
"bg-tertiary",
|
|
24
|
+
"bg-error"
|
|
25
|
+
];
|
|
26
|
+
function A(e) {
|
|
27
|
+
for (let t of k) if (e.classList.contains(t)) return `var(--color-${t.slice(3)})`;
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function j(e) {
|
|
31
|
+
if (!e || e === "transparent") return !0;
|
|
32
|
+
let t = e.match(/^rgba?\(([^)]+)\)$/);
|
|
33
|
+
if (t) {
|
|
34
|
+
let e = t[1].split(",").map((e) => e.trim());
|
|
35
|
+
if (e.length === 4 && parseFloat(e[3]) === 0) return !0;
|
|
36
|
+
}
|
|
37
|
+
return !1;
|
|
38
|
+
}
|
|
39
|
+
function M(e, t) {
|
|
40
|
+
let n = y("var(--color-surface)");
|
|
41
|
+
function r(r) {
|
|
42
|
+
n.value = r, e.value?.style.setProperty("--field-bg", t() ?? r);
|
|
43
|
+
}
|
|
44
|
+
function i() {
|
|
45
|
+
let t = e.value?.parentElement ?? null;
|
|
46
|
+
for (; t;) {
|
|
47
|
+
let e = A(t);
|
|
48
|
+
if (e) {
|
|
49
|
+
r(e);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (t === document.body) {
|
|
53
|
+
r("var(--color-surface)");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
let n = getComputedStyle(t).backgroundColor;
|
|
57
|
+
if (!j(n)) {
|
|
58
|
+
r(n);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
t = t.parentElement;
|
|
62
|
+
}
|
|
63
|
+
r("var(--color-surface)");
|
|
64
|
+
}
|
|
65
|
+
let o = null;
|
|
66
|
+
return g(() => {
|
|
67
|
+
i(), o = new MutationObserver(() => i()), o.observe(document.documentElement, {
|
|
68
|
+
attributes: !0,
|
|
69
|
+
attributeFilter: [
|
|
70
|
+
"class",
|
|
71
|
+
"style",
|
|
72
|
+
"data-theme"
|
|
73
|
+
]
|
|
74
|
+
});
|
|
75
|
+
}), h(() => o?.disconnect()), { resolvedFieldBg: a(() => t() ?? n.value) };
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/components/MSpinner.vue?vue&type=script&setup=true&lang.ts
|
|
79
|
+
var N = {
|
|
80
|
+
key: 0,
|
|
81
|
+
class: "block h-full w-full animate-spin rounded-full border-2 border-current border-t-transparent"
|
|
82
|
+
}, P = [
|
|
83
|
+
"width",
|
|
84
|
+
"height",
|
|
85
|
+
"viewBox"
|
|
86
|
+
], F = ["d", "stroke-dasharray"], I = 3, L = 9, R = /* @__PURE__ */ f({
|
|
87
|
+
__name: "MSpinner",
|
|
88
|
+
props: {
|
|
89
|
+
size: { default: 20 },
|
|
90
|
+
wavy: {
|
|
91
|
+
type: Boolean,
|
|
92
|
+
default: !1
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
setup(e) {
|
|
96
|
+
let t = e, n = a(() => (t.size / 2 - 1 - I / 2) / 1.25), r = a(() => t.size / 2), i = a(() => {
|
|
97
|
+
let e = r.value, t = n.value, i = t * .08, a = L * 24, o = [], s = 0, c = 0, l = 0;
|
|
98
|
+
for (let n = 0; n <= a; n++) {
|
|
99
|
+
let r = 2 * Math.PI * n / a - Math.PI / 2, u = t + i * Math.sin(L * r), d = e + u * Math.cos(r), f = e + u * Math.sin(r);
|
|
100
|
+
n > 0 && (s += Math.sqrt((d - c) ** 2 + (f - l) ** 2)), o.push(`${n === 0 ? "M" : "L"}${d.toFixed(2)},${f.toFixed(2)}`), c = d, l = f;
|
|
101
|
+
}
|
|
102
|
+
let u = s * .58, d = s - u, f = `${u.toFixed(1)} ${d.toFixed(1)}`;
|
|
103
|
+
return {
|
|
104
|
+
path: o.join("") + "Z",
|
|
105
|
+
dash: f,
|
|
106
|
+
len: s.toFixed(1)
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
return (t, n) => (v(), c("span", {
|
|
110
|
+
class: "inline-flex shrink-0 items-center justify-center",
|
|
111
|
+
style: m({
|
|
112
|
+
width: `${e.size}px`,
|
|
113
|
+
height: `${e.size}px`
|
|
114
|
+
}),
|
|
115
|
+
role: "status",
|
|
116
|
+
"aria-label": "Cargando"
|
|
117
|
+
}, [e.wavy ? (v(), c("svg", {
|
|
118
|
+
key: 1,
|
|
119
|
+
width: e.size,
|
|
120
|
+
height: e.size,
|
|
121
|
+
viewBox: `0 0 ${e.size} ${e.size}`,
|
|
122
|
+
fill: "none",
|
|
123
|
+
class: "animate-[m3-wavy-spin_2.8s_linear_infinite]",
|
|
124
|
+
style: m(`transform-origin: ${r.value}px ${r.value}px`)
|
|
125
|
+
}, [l("path", {
|
|
126
|
+
d: i.value.path,
|
|
127
|
+
stroke: "currentColor",
|
|
128
|
+
"stroke-width": I,
|
|
129
|
+
"stroke-linecap": "round",
|
|
130
|
+
"stroke-dasharray": i.value.dash,
|
|
131
|
+
class: "animate-[m3-wavy-travel_2s_linear_infinite]",
|
|
132
|
+
style: m({ "--m3-wave-len": i.value.len })
|
|
133
|
+
}, null, 12, F)], 12, P)) : (v(), c("span", N))], 4));
|
|
134
|
+
}
|
|
135
|
+
}), z = "relative inline-flex items-center justify-center gap-2 h-10 rounded-full text-label-large font-medium whitespace-nowrap overflow-hidden transition-[box-shadow,background-color,color] duration-150 select-none cursor-pointer disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:shadow-none before:content-[''] before:pointer-events-none before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:duration-150 enabled:hover:before:opacity-[0.08] enabled:active:before:opacity-[0.12]", B = /* @__PURE__ */ f({
|
|
136
|
+
__name: "MButton",
|
|
137
|
+
props: {
|
|
138
|
+
variant: { default: "filled" },
|
|
139
|
+
color: { default: "primary" },
|
|
140
|
+
type: { default: "button" },
|
|
141
|
+
disabled: {
|
|
142
|
+
type: Boolean,
|
|
143
|
+
default: !1
|
|
144
|
+
},
|
|
145
|
+
loading: {
|
|
146
|
+
type: Boolean,
|
|
147
|
+
default: !1
|
|
148
|
+
},
|
|
149
|
+
icon: {},
|
|
150
|
+
to: {}
|
|
151
|
+
},
|
|
152
|
+
setup(t) {
|
|
153
|
+
let n = ["primary", "error"], r = t, i = a(() => r.to ? "RouterLink" : "button"), c = a(() => !!r.color && !n.includes(r.color)), l = a(() => {
|
|
154
|
+
if (c.value) return {
|
|
155
|
+
"--color-primary": r.color,
|
|
156
|
+
"--color-on-primary": "#ffffff",
|
|
157
|
+
"--color-primary-container": r.color + "33",
|
|
158
|
+
"--color-on-primary-container": r.color
|
|
159
|
+
};
|
|
160
|
+
}), u = a(() => r.color === "error"), d = a(() => {
|
|
161
|
+
let e = u.value;
|
|
162
|
+
switch (r.variant) {
|
|
163
|
+
case "filled": return e ? "px-6 bg-error text-on-error enabled:hover:shadow-elevation-1 enabled:active:shadow-none" : "px-6 bg-primary text-on-primary enabled:hover:shadow-elevation-1 enabled:active:shadow-none";
|
|
164
|
+
case "tonal": return e ? "px-6 bg-error-container text-on-error-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none" : "px-6 bg-secondary-container text-on-secondary-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none";
|
|
165
|
+
case "elevated": return e ? "px-6 bg-surface-container-low text-error shadow-elevation-1 enabled:hover:shadow-elevation-2" : "px-6 bg-surface-container-low text-primary shadow-elevation-1 enabled:hover:shadow-elevation-2";
|
|
166
|
+
case "outlined": return e ? "px-6 border border-error text-error" : "px-6 border border-outline text-primary";
|
|
167
|
+
case "text": return e ? "px-3 text-error" : "px-3 text-primary";
|
|
168
|
+
default: return "";
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
function f(e) {
|
|
172
|
+
if (r.disabled || r.loading) return;
|
|
173
|
+
let t = e.currentTarget, n = t.getBoundingClientRect(), i = Math.max(n.width, n.height) * 2, a = document.createElement("span");
|
|
174
|
+
a.className = "m3-ripple", a.style.cssText = `width:${i}px;height:${i}px;top:${e.clientY - n.top - i / 2}px;left:${e.clientX - n.left - i / 2}px`, t.appendChild(a), a.addEventListener("animationend", () => a.remove(), { once: !0 });
|
|
175
|
+
}
|
|
176
|
+
return (n, r) => (v(), o(x(i.value), {
|
|
177
|
+
to: t.to || void 0,
|
|
178
|
+
type: t.to ? void 0 : t.type,
|
|
179
|
+
disabled: t.disabled || t.loading,
|
|
180
|
+
class: p([z, d.value]),
|
|
181
|
+
style: m(l.value),
|
|
182
|
+
onPointerdown: f
|
|
183
|
+
}, {
|
|
184
|
+
default: D(() => [t.loading ? (v(), o(R, {
|
|
185
|
+
key: 0,
|
|
186
|
+
size: 18
|
|
187
|
+
})) : t.icon ? (v(), o(e, {
|
|
188
|
+
key: 1,
|
|
189
|
+
name: t.icon,
|
|
190
|
+
size: 20
|
|
191
|
+
}, null, 8, ["name"])) : s("", !0), b(n.$slots, "default")]),
|
|
192
|
+
_: 3
|
|
193
|
+
}, 40, [
|
|
194
|
+
"to",
|
|
195
|
+
"type",
|
|
196
|
+
"disabled",
|
|
197
|
+
"class",
|
|
198
|
+
"style"
|
|
199
|
+
]));
|
|
200
|
+
}
|
|
201
|
+
}), V = "inline-flex shrink-0 items-center justify-center rounded-full transition-colors duration-150 cursor-pointer disabled:cursor-not-allowed disabled:opacity-[0.38]", H = /* @__PURE__ */ f({
|
|
202
|
+
__name: "MIconButton",
|
|
203
|
+
props: {
|
|
204
|
+
icon: {},
|
|
205
|
+
label: {},
|
|
206
|
+
variant: { default: "standard" },
|
|
207
|
+
disabled: {
|
|
208
|
+
type: Boolean,
|
|
209
|
+
default: !1
|
|
210
|
+
},
|
|
211
|
+
size: { default: 40 },
|
|
212
|
+
to: {}
|
|
213
|
+
},
|
|
214
|
+
setup(t) {
|
|
215
|
+
let n = t, r = a(() => n.to ? "RouterLink" : "button"), i = a(() => {
|
|
216
|
+
switch (n.variant) {
|
|
217
|
+
case "filled": return "bg-primary text-on-primary hover:shadow-elevation-1";
|
|
218
|
+
case "tonal": return "bg-secondary-container text-on-secondary-container hover:shadow-elevation-1";
|
|
219
|
+
case "outlined": return "border border-outline text-on-surface-variant hover:bg-on-surface/8";
|
|
220
|
+
default: return "text-on-surface-variant hover:bg-on-surface/8 active:bg-on-surface/12";
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
return (n, a) => (v(), o(x(r.value), {
|
|
224
|
+
to: t.to || void 0,
|
|
225
|
+
type: t.to ? void 0 : "button",
|
|
226
|
+
"aria-label": t.label || void 0,
|
|
227
|
+
disabled: t.disabled,
|
|
228
|
+
class: p([V, i.value]),
|
|
229
|
+
style: m({
|
|
230
|
+
width: `${t.size}px`,
|
|
231
|
+
height: `${t.size}px`
|
|
232
|
+
})
|
|
233
|
+
}, {
|
|
234
|
+
default: D(() => [d(e, {
|
|
235
|
+
name: t.icon,
|
|
236
|
+
size: Math.round(t.size * .55)
|
|
237
|
+
}, null, 8, ["name", "size"])]),
|
|
238
|
+
_: 1
|
|
239
|
+
}, 8, [
|
|
240
|
+
"to",
|
|
241
|
+
"type",
|
|
242
|
+
"aria-label",
|
|
243
|
+
"disabled",
|
|
244
|
+
"class",
|
|
245
|
+
"style"
|
|
246
|
+
]));
|
|
247
|
+
}
|
|
248
|
+
}), U = { class: "flex items-start justify-between gap-4 px-6 pt-6 pb-2" }, W = { class: "text-headline-small text-on-surface" }, G = { class: "overflow-y-auto px-6 py-2 text-body-medium text-on-surface-variant" }, K = {
|
|
249
|
+
key: 0,
|
|
250
|
+
class: "flex justify-end gap-2 px-6 py-4"
|
|
251
|
+
}, q = /*#__PURE__*/ t(/* @__PURE__ */ f({
|
|
252
|
+
__name: "MDialog",
|
|
253
|
+
props: {
|
|
254
|
+
modelValue: { type: Boolean },
|
|
255
|
+
title: {},
|
|
256
|
+
maxWidth: { default: "max-w-md" },
|
|
257
|
+
persistent: {
|
|
258
|
+
type: Boolean,
|
|
259
|
+
default: !1
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
emits: ["update:modelValue"],
|
|
263
|
+
setup(e, { emit: t }) {
|
|
264
|
+
let n = e, a = t;
|
|
265
|
+
function f() {
|
|
266
|
+
n.persistent || a("update:modelValue", !1);
|
|
267
|
+
}
|
|
268
|
+
function m(e) {
|
|
269
|
+
e.key === "Escape" && f();
|
|
270
|
+
}
|
|
271
|
+
return E(() => n.modelValue, (e) => {
|
|
272
|
+
e ? (document.addEventListener("keydown", m), document.body.style.overflow = "hidden") : (document.removeEventListener("keydown", m), document.body.style.overflow = "");
|
|
273
|
+
}), (t, n) => (v(), o(r, { to: "body" }, [d(i, { name: "m3-dialog" }, {
|
|
274
|
+
default: D(() => [e.modelValue ? (v(), c("div", {
|
|
275
|
+
key: 0,
|
|
276
|
+
class: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",
|
|
277
|
+
onClick: O(f, ["self"])
|
|
278
|
+
}, [l("div", { class: p(["dialog-box flex max-h-[90vh] w-full flex-col rounded-xl bg-surface-container-high shadow-elevation-3", e.maxWidth]) }, [
|
|
279
|
+
l("div", U, [l("h2", W, [b(t.$slots, "title", {}, () => [u(S(e.title), 1)], !0)]), e.persistent ? s("", !0) : (v(), o(H, {
|
|
280
|
+
key: 0,
|
|
281
|
+
icon: "close",
|
|
282
|
+
label: "Cerrar",
|
|
283
|
+
onClick: f
|
|
284
|
+
}))]),
|
|
285
|
+
l("div", G, [b(t.$slots, "default", {}, void 0, !0)]),
|
|
286
|
+
t.$slots.actions ? (v(), c("div", K, [b(t.$slots, "actions", {}, void 0, !0)])) : s("", !0)
|
|
287
|
+
], 2)])) : s("", !0)]),
|
|
288
|
+
_: 3
|
|
289
|
+
})]));
|
|
290
|
+
}
|
|
291
|
+
}), [["__scopeId", "data-v-e7dfca29"]]), J = { class: "flex flex-col gap-1" }, Y = {
|
|
292
|
+
key: 0,
|
|
293
|
+
class: "pointer-events-none absolute left-3.5 top-1/2 -translate-y-1/2 text-on-surface-variant"
|
|
294
|
+
}, X = [
|
|
295
|
+
"id",
|
|
296
|
+
"value",
|
|
297
|
+
"rows",
|
|
298
|
+
"disabled",
|
|
299
|
+
"required"
|
|
300
|
+
], Z = [
|
|
301
|
+
"id",
|
|
302
|
+
"type",
|
|
303
|
+
"value",
|
|
304
|
+
"disabled",
|
|
305
|
+
"required",
|
|
306
|
+
"autocomplete"
|
|
307
|
+
], Q = ["for"], $ = {
|
|
308
|
+
key: 0,
|
|
309
|
+
class: "text-error"
|
|
310
|
+
}, ee = {
|
|
311
|
+
key: 3,
|
|
312
|
+
class: "absolute top-1/2 right-2 -translate-y-1/2"
|
|
313
|
+
}, te = {
|
|
314
|
+
key: 0,
|
|
315
|
+
class: "px-4 text-body-small text-error"
|
|
316
|
+
}, ne = {
|
|
317
|
+
key: 1,
|
|
318
|
+
class: "px-4 text-body-small text-on-surface-variant"
|
|
319
|
+
}, re = /* @__PURE__ */ f({
|
|
320
|
+
__name: "MTextField",
|
|
321
|
+
props: {
|
|
322
|
+
modelValue: {},
|
|
323
|
+
label: {},
|
|
324
|
+
type: { default: "text" },
|
|
325
|
+
variant: { default: "filled" },
|
|
326
|
+
error: {},
|
|
327
|
+
hint: {},
|
|
328
|
+
disabled: { type: Boolean },
|
|
329
|
+
required: { type: Boolean },
|
|
330
|
+
multiline: { type: Boolean },
|
|
331
|
+
rows: { default: 3 },
|
|
332
|
+
autocomplete: {},
|
|
333
|
+
leadingIcon: {},
|
|
334
|
+
fieldBg: {}
|
|
335
|
+
},
|
|
336
|
+
emits: ["update:modelValue"],
|
|
337
|
+
setup(t, { emit: n }) {
|
|
338
|
+
let r = t, i = n, o = w(), f = T(), h = y(null), { resolvedFieldBg: g } = M(h, () => r.fieldBg), _ = a(() => {
|
|
339
|
+
let e = !!f.trailing, t = r.leadingIcon ? "pl-12" : "pl-4", n = e ? "pr-12" : "pr-4", i = [
|
|
340
|
+
"peer block w-full text-body-large text-on-surface outline-none placeholder:text-transparent",
|
|
341
|
+
"transition-[border-color,border-width] duration-150",
|
|
342
|
+
"disabled:cursor-not-allowed disabled:opacity-[0.38]",
|
|
343
|
+
r.multiline ? "resize-y min-h-[56px]" : "h-14",
|
|
344
|
+
t,
|
|
345
|
+
n
|
|
346
|
+
];
|
|
347
|
+
return r.variant === "outlined" ? [
|
|
348
|
+
...i,
|
|
349
|
+
"rounded-sm border bg-transparent py-4",
|
|
350
|
+
r.error ? "border-error focus:border-2 focus:border-error" : "border-outline hover:border-on-surface focus:border-2 focus:border-primary"
|
|
351
|
+
].join(" ") : [
|
|
352
|
+
...i,
|
|
353
|
+
"rounded-t-sm bg-surface-container-highest border-b pt-6 pb-2",
|
|
354
|
+
r.error ? "border-error focus:border-b-2 focus:border-error" : "border-on-surface-variant hover:border-on-surface focus:border-b-2 focus:border-primary"
|
|
355
|
+
].join(" ");
|
|
356
|
+
}), x = a(() => {
|
|
357
|
+
let e = [
|
|
358
|
+
"pointer-events-none absolute truncate transition-all duration-200",
|
|
359
|
+
r.leadingIcon ? r.variant === "outlined" ? "left-11" : "left-12" : r.variant === "outlined" ? "left-3" : "left-4",
|
|
360
|
+
"right-4",
|
|
361
|
+
"top-1/2 -translate-y-1/2 text-body-large"
|
|
362
|
+
];
|
|
363
|
+
return r.variant === "outlined" ? [
|
|
364
|
+
...e,
|
|
365
|
+
"peer-focus:-top-2.5 peer-focus:translate-y-0 peer-focus:text-label-small peer-focus:right-auto peer-focus:max-w-[calc(100%-1.5rem)] peer-focus:bg-[var(--field-bg)] peer-focus:px-1",
|
|
366
|
+
"peer-[&:not(:placeholder-shown)]:-top-2.5 peer-[&:not(:placeholder-shown)]:translate-y-0 peer-[&:not(:placeholder-shown)]:right-auto peer-[&:not(:placeholder-shown)]:max-w-[calc(100%-1.5rem)]",
|
|
367
|
+
"peer-[&:not(:placeholder-shown)]:text-label-small peer-[&:not(:placeholder-shown)]:bg-[var(--field-bg)] peer-[&:not(:placeholder-shown)]:px-1",
|
|
368
|
+
r.error ? "text-error peer-focus:text-error" : "text-on-surface-variant peer-focus:text-primary"
|
|
369
|
+
].join(" ") : [
|
|
370
|
+
...e,
|
|
371
|
+
"peer-focus:top-2 peer-focus:translate-y-0 peer-focus:text-label-small",
|
|
372
|
+
"peer-[&:not(:placeholder-shown)]:top-2 peer-[&:not(:placeholder-shown)]:translate-y-0 peer-[&:not(:placeholder-shown)]:text-label-small",
|
|
373
|
+
r.error ? "text-error peer-focus:text-error" : "text-on-surface-variant peer-focus:text-primary"
|
|
374
|
+
].join(" ");
|
|
375
|
+
});
|
|
376
|
+
function E(e) {
|
|
377
|
+
let t = e.target;
|
|
378
|
+
i("update:modelValue", t.value);
|
|
379
|
+
}
|
|
380
|
+
return (n, r) => (v(), c("div", J, [l("div", {
|
|
381
|
+
ref_key: "fieldBgEl",
|
|
382
|
+
ref: h,
|
|
383
|
+
class: p(["relative", t.variant === "outlined" ? "mt-2" : ""]),
|
|
384
|
+
style: m(t.variant === "outlined" ? { "--field-bg": C(g) } : void 0)
|
|
385
|
+
}, [
|
|
386
|
+
t.leadingIcon ? (v(), c("div", Y, [d(e, {
|
|
387
|
+
name: t.leadingIcon,
|
|
388
|
+
size: 20
|
|
389
|
+
}, null, 8, ["name"])])) : s("", !0),
|
|
390
|
+
t.multiline ? (v(), c("textarea", {
|
|
391
|
+
key: 1,
|
|
392
|
+
id: C(o),
|
|
393
|
+
value: String(t.modelValue),
|
|
394
|
+
rows: t.rows,
|
|
395
|
+
disabled: t.disabled,
|
|
396
|
+
required: t.required,
|
|
397
|
+
placeholder: " ",
|
|
398
|
+
class: p(_.value),
|
|
399
|
+
onInput: E
|
|
400
|
+
}, null, 42, X)) : (v(), c("input", {
|
|
401
|
+
key: 2,
|
|
402
|
+
id: C(o),
|
|
403
|
+
type: t.type,
|
|
404
|
+
value: t.modelValue,
|
|
405
|
+
disabled: t.disabled,
|
|
406
|
+
required: t.required,
|
|
407
|
+
autocomplete: t.autocomplete,
|
|
408
|
+
placeholder: " ",
|
|
409
|
+
class: p(_.value),
|
|
410
|
+
onInput: E
|
|
411
|
+
}, null, 42, Z)),
|
|
412
|
+
l("label", {
|
|
413
|
+
for: C(o),
|
|
414
|
+
class: p(x.value)
|
|
415
|
+
}, [u(S(t.label), 1), t.required ? (v(), c("span", $, "\xA0*")) : s("", !0)], 10, Q),
|
|
416
|
+
n.$slots.trailing ? (v(), c("div", ee, [b(n.$slots, "trailing")])) : s("", !0)
|
|
417
|
+
], 6), t.error ? (v(), c("p", te, S(t.error), 1)) : t.hint ? (v(), c("p", ne, S(t.hint), 1)) : s("", !0)]));
|
|
418
|
+
}
|
|
419
|
+
}), ie = /* @__PURE__ */ f({
|
|
420
|
+
__name: "MMenu",
|
|
421
|
+
props: { align: { default: "right" } },
|
|
422
|
+
setup(e, { expose: t }) {
|
|
423
|
+
let u = e, f = y(!1), p = y(null), h = y(null), x = y({});
|
|
424
|
+
function S() {
|
|
425
|
+
if (!p.value) return;
|
|
426
|
+
let e = p.value.getBoundingClientRect(), t = window.innerHeight - e.bottom - 8, n = t < 200 && e.top > t, r = { maxHeight: `${Math.min(n ? e.top - 12 : t, 400)}px` };
|
|
427
|
+
n ? r.bottom = `${window.innerHeight - e.top + 4}px` : r.top = `${e.bottom + 4}px`, u.align === "right" ? r.right = `${window.innerWidth - e.right}px` : r.left = `${e.left}px`, x.value = r;
|
|
428
|
+
}
|
|
429
|
+
function C() {
|
|
430
|
+
f.value || S(), f.value = !f.value;
|
|
431
|
+
}
|
|
432
|
+
function w() {
|
|
433
|
+
f.value = !1;
|
|
434
|
+
}
|
|
435
|
+
t({
|
|
436
|
+
close: w,
|
|
437
|
+
open: f
|
|
438
|
+
});
|
|
439
|
+
function T(e) {
|
|
440
|
+
let t = e.target;
|
|
441
|
+
!p.value?.contains(t) && !h.value?.contains(t) && w();
|
|
442
|
+
}
|
|
443
|
+
function E(e) {
|
|
444
|
+
if (!f.value || h.value?.contains(e.target) || !p.value) return;
|
|
445
|
+
let t = p.value.getBoundingClientRect();
|
|
446
|
+
if (t.bottom < 0 || t.top > window.innerHeight) {
|
|
447
|
+
w();
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
S();
|
|
451
|
+
}
|
|
452
|
+
function O(e) {
|
|
453
|
+
e.key === "Escape" && w();
|
|
454
|
+
}
|
|
455
|
+
g(() => {
|
|
456
|
+
document.addEventListener("mousedown", T), document.addEventListener("keydown", O), window.addEventListener("scroll", E, !0);
|
|
457
|
+
}), _(() => {
|
|
458
|
+
document.removeEventListener("mousedown", T), document.removeEventListener("keydown", O), window.removeEventListener("scroll", E, !0);
|
|
459
|
+
});
|
|
460
|
+
let k = a(() => u.align === "right" ? "top right" : "top left");
|
|
461
|
+
return (e, t) => (v(), c(n, null, [l("div", {
|
|
462
|
+
ref_key: "triggerEl",
|
|
463
|
+
ref: p,
|
|
464
|
+
class: "inline-block",
|
|
465
|
+
onClick: C
|
|
466
|
+
}, [b(e.$slots, "trigger", { open: f.value })], 512), (v(), o(r, { to: "body" }, [d(i, {
|
|
467
|
+
"enter-active-class": "transition-[opacity,transform] duration-100 ease-out",
|
|
468
|
+
"enter-from-class": "opacity-0 scale-95",
|
|
469
|
+
"enter-to-class": "opacity-100 scale-100",
|
|
470
|
+
"leave-active-class": "transition-[opacity,transform] duration-75 ease-in",
|
|
471
|
+
"leave-from-class": "opacity-100 scale-100",
|
|
472
|
+
"leave-to-class": "opacity-0 scale-95"
|
|
473
|
+
}, {
|
|
474
|
+
default: D(() => [f.value ? (v(), c("div", {
|
|
475
|
+
key: 0,
|
|
476
|
+
ref_key: "dropdownEl",
|
|
477
|
+
ref: h,
|
|
478
|
+
class: "fixed z-500 min-w-48 overflow-y-auto overflow-x-hidden rounded-xs bg-surface-container py-1 shadow-elevation-2",
|
|
479
|
+
style: m({
|
|
480
|
+
...x.value,
|
|
481
|
+
transformOrigin: k.value
|
|
482
|
+
}),
|
|
483
|
+
onClick: w
|
|
484
|
+
}, [b(e.$slots, "default")], 4)) : s("", !0)]),
|
|
485
|
+
_: 3
|
|
486
|
+
})]))], 64));
|
|
487
|
+
}
|
|
488
|
+
}), ae = /* @__PURE__ */ f({
|
|
489
|
+
__name: "MMenuItem",
|
|
490
|
+
props: {
|
|
491
|
+
icon: {},
|
|
492
|
+
to: {}
|
|
493
|
+
},
|
|
494
|
+
setup(t) {
|
|
495
|
+
let n = t, r = a(() => n.to ? "RouterLink" : "button");
|
|
496
|
+
return (n, i) => (v(), o(x(r.value), {
|
|
497
|
+
to: t.to || void 0,
|
|
498
|
+
type: t.to ? void 0 : "button",
|
|
499
|
+
class: "flex w-full cursor-pointer items-center gap-3 px-4 py-2.5 text-left text-body-large text-on-surface hover:bg-on-surface/8"
|
|
500
|
+
}, {
|
|
501
|
+
default: D(() => [t.icon ? (v(), o(e, {
|
|
502
|
+
key: 0,
|
|
503
|
+
name: t.icon,
|
|
504
|
+
size: 20,
|
|
505
|
+
class: "text-on-surface-variant"
|
|
506
|
+
}, null, 8, ["name"])) : s("", !0), b(n.$slots, "default")]),
|
|
507
|
+
_: 3
|
|
508
|
+
}, 8, ["to", "type"]));
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
//#endregion
|
|
512
|
+
export { H as a, M as c, q as i, ie as n, B as o, re as r, R as s, ae as t };
|
|
513
|
+
|
|
514
|
+
//# sourceMappingURL=MMenuItem-_n5OG5MT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MMenuItem-_n5OG5MT.js","names":["$slots","$slots"],"sources":["../src/composables/useFieldBg.ts","../src/components/MSpinner.vue","../src/components/MSpinner.vue","../src/components/MButton.vue","../src/components/MButton.vue","../src/components/MIconButton.vue","../src/components/MIconButton.vue","../src/components/MDialog.vue","../src/components/MDialog.vue","../src/components/MTextField.vue","../src/components/MTextField.vue","../src/components/MMenu.vue","../src/components/MMenu.vue","../src/components/MMenuItem.vue","../src/components/MMenuItem.vue"],"sourcesContent":["import { ref, computed, onMounted, onBeforeUnmount, type Ref } from 'vue'\n\nconst M3_BG_CLASSES = [\n 'bg-surface-container-highest',\n 'bg-surface-container-high',\n 'bg-surface-container-low',\n 'bg-surface-container-lowest',\n 'bg-surface-container',\n 'bg-surface-variant',\n 'bg-surface-bright',\n 'bg-surface-dim',\n 'bg-surface',\n 'bg-background',\n 'bg-inverse-surface',\n 'bg-primary-container',\n 'bg-secondary-container',\n 'bg-tertiary-container',\n 'bg-error-container',\n 'bg-primary',\n 'bg-secondary',\n 'bg-tertiary',\n 'bg-error',\n] as const\n\nfunction findM3BgVar(el: HTMLElement): string | null {\n for (const cls of M3_BG_CLASSES) {\n if (el.classList.contains(cls)) return `var(--color-${cls.slice(3)})`\n }\n return null\n}\n\nfunction isTransparent(color: string): boolean {\n if (!color || color === 'transparent') return true\n const m = color.match(/^rgba?\\(([^)]+)\\)$/)\n if (m) {\n const parts = m[1]!.split(',').map((s) => s.trim())\n if (parts.length === 4 && parseFloat(parts[3]!) === 0) return true\n }\n return false\n}\n\n/**\n * Auto-detects the background behind `containerEl` and exposes it as `--field-bg`.\n * Prefers a CSS variable reference (e.g. var(--color-surface-container-low)) over a\n * raw computed color so the outlined label cutout transitions in sync with the rest\n * of the theme switch instead of lagging behind.\n *\n * @param containerEl The element that receives `--field-bg` as an inline style.\n * @param fieldBgProp Getter for the explicit `fieldBg` prop (overrides auto-detect).\n */\nexport function useFieldBg(\n containerEl: Ref<HTMLElement | null>,\n fieldBgProp: () => string | undefined,\n) {\n const detectedBg = ref<string>('var(--color-surface)')\n\n function applyFieldBg(value: string) {\n detectedBg.value = value\n containerEl.value?.style.setProperty('--field-bg', fieldBgProp() ?? value)\n }\n\n function resolveBg() {\n let el: HTMLElement | null = containerEl.value?.parentElement ?? null\n while (el) {\n const cssVar = findM3BgVar(el)\n if (cssVar) { applyFieldBg(cssVar); return }\n if (el === document.body) { applyFieldBg('var(--color-surface)'); return }\n const bg = getComputedStyle(el).backgroundColor\n if (!isTransparent(bg)) { applyFieldBg(bg); return }\n el = el.parentElement\n }\n applyFieldBg('var(--color-surface)')\n }\n\n let observer: MutationObserver | null = null\n\n onMounted(() => {\n resolveBg()\n observer = new MutationObserver(() => resolveBg())\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'style', 'data-theme'],\n })\n })\n\n onBeforeUnmount(() => observer?.disconnect())\n\n const resolvedFieldBg = computed(() => fieldBgProp() ?? detectedBg.value)\n\n return { resolvedFieldBg }\n}\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\nconst props = withDefaults(\n defineProps<{\n size?: number;\n wavy?: boolean;\n }>(),\n { size: 20, wavy: false },\n);\n\nconst STROKE = 3;\nconst BUMPS = 9;\n\n// amp fraction of r = 0.25 → max radius = r * 1.25\n// Constrain so that max_r + STROKE/2 ≤ size/2 - 1 (1px margin from edge)\nconst r = computed(() => (props.size / 2 - 1 - STROKE / 2) / 1.25);\nconst cx = computed(() => props.size / 2);\n\n// Build the full bumpy-circle path and its total length.\nconst wavyData = computed(() => {\n const CX = cx.value;\n const R = r.value;\n const amp = R * 0.08;\n const segs = BUMPS * 24; // smooth curve\n\n const pts: string[] = [];\n let len = 0;\n let px = 0,\n py = 0;\n\n for (let i = 0; i <= segs; i++) {\n const theta = (2 * Math.PI * i) / segs - Math.PI / 2;\n const rr = R + amp * Math.sin(BUMPS * theta);\n const x = CX + rr * Math.cos(theta);\n const y = CX + rr * Math.sin(theta);\n if (i > 0) len += Math.sqrt((x - px) ** 2 + (y - py) ** 2);\n pts.push(`${i === 0 ? \"M\" : \"L\"}${x.toFixed(2)},${y.toFixed(2)}`);\n px = x;\n py = y;\n }\n\n // Visible arc ~58% of the circumference, gap fills the rest.\n const visible = len * 0.58;\n const gap = len - visible;\n const dash = `${visible.toFixed(1)} ${gap.toFixed(1)}`;\n\n // The wave \"travels\" by shifting dashoffset over exactly one full length,\n // so the crests slide around the path independently of the rotation.\n return { path: pts.join(\"\") + \"Z\", dash, len: len.toFixed(1) };\n});\n</script>\n\n<template>\n <span\n class=\"inline-flex shrink-0 items-center justify-center\"\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\n role=\"status\"\n aria-label=\"Cargando\"\n >\n <!-- Standard circular spinner -->\n <span\n v-if=\"!wavy\"\n class=\"block h-full w-full animate-spin rounded-full border-2 border-current border-t-transparent\"\n />\n\n <!-- Wavy spinner (M3 Expressive): the whole shape rotates AND the wave\n travels along the stroke via dashoffset, giving the snake-like flow. -->\n <svg\n v-else\n :width=\"size\"\n :height=\"size\"\n :viewBox=\"`0 0 ${size} ${size}`\"\n fill=\"none\"\n class=\"animate-[m3-wavy-spin_2.8s_linear_infinite]\"\n :style=\"`transform-origin: ${cx}px ${cx}px`\"\n >\n <path\n :d=\"wavyData.path\"\n stroke=\"currentColor\"\n :stroke-width=\"STROKE\"\n stroke-linecap=\"round\"\n :stroke-dasharray=\"wavyData.dash\"\n class=\"animate-[m3-wavy-travel_2s_linear_infinite]\"\n :style=\"{ '--m3-wave-len': wavyData.len }\"\n />\n </svg>\n </span>\n</template>\n\n<style>\n/* The SVG element rotates the whole bumpy circle. */\n@keyframes m3-wavy-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n/* The stroke's dashoffset slides by one full path length, so the crests\n appear to crawl along the circle — the \"snake\" motion of M3 Expressive.\n Negative direction makes the wave travel forward relative to the spin. */\n@keyframes m3-wavy-travel {\n from {\n stroke-dashoffset: 0;\n }\n to {\n stroke-dashoffset: calc(var(--m3-wave-len) * -1px);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .animate-\\[m3-wavy-spin_2\\.8s_linear_infinite\\] {\n animation: m3-wavy-spin 2.8s linear infinite;\n }\n .animate-\\[m3-wavy-travel_2s_linear_infinite\\] {\n animation: none !important;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\nconst props = withDefaults(\n defineProps<{\n size?: number;\n wavy?: boolean;\n }>(),\n { size: 20, wavy: false },\n);\n\nconst STROKE = 3;\nconst BUMPS = 9;\n\n// amp fraction of r = 0.25 → max radius = r * 1.25\n// Constrain so that max_r + STROKE/2 ≤ size/2 - 1 (1px margin from edge)\nconst r = computed(() => (props.size / 2 - 1 - STROKE / 2) / 1.25);\nconst cx = computed(() => props.size / 2);\n\n// Build the full bumpy-circle path and its total length.\nconst wavyData = computed(() => {\n const CX = cx.value;\n const R = r.value;\n const amp = R * 0.08;\n const segs = BUMPS * 24; // smooth curve\n\n const pts: string[] = [];\n let len = 0;\n let px = 0,\n py = 0;\n\n for (let i = 0; i <= segs; i++) {\n const theta = (2 * Math.PI * i) / segs - Math.PI / 2;\n const rr = R + amp * Math.sin(BUMPS * theta);\n const x = CX + rr * Math.cos(theta);\n const y = CX + rr * Math.sin(theta);\n if (i > 0) len += Math.sqrt((x - px) ** 2 + (y - py) ** 2);\n pts.push(`${i === 0 ? \"M\" : \"L\"}${x.toFixed(2)},${y.toFixed(2)}`);\n px = x;\n py = y;\n }\n\n // Visible arc ~58% of the circumference, gap fills the rest.\n const visible = len * 0.58;\n const gap = len - visible;\n const dash = `${visible.toFixed(1)} ${gap.toFixed(1)}`;\n\n // The wave \"travels\" by shifting dashoffset over exactly one full length,\n // so the crests slide around the path independently of the rotation.\n return { path: pts.join(\"\") + \"Z\", dash, len: len.toFixed(1) };\n});\n</script>\n\n<template>\n <span\n class=\"inline-flex shrink-0 items-center justify-center\"\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\n role=\"status\"\n aria-label=\"Cargando\"\n >\n <!-- Standard circular spinner -->\n <span\n v-if=\"!wavy\"\n class=\"block h-full w-full animate-spin rounded-full border-2 border-current border-t-transparent\"\n />\n\n <!-- Wavy spinner (M3 Expressive): the whole shape rotates AND the wave\n travels along the stroke via dashoffset, giving the snake-like flow. -->\n <svg\n v-else\n :width=\"size\"\n :height=\"size\"\n :viewBox=\"`0 0 ${size} ${size}`\"\n fill=\"none\"\n class=\"animate-[m3-wavy-spin_2.8s_linear_infinite]\"\n :style=\"`transform-origin: ${cx}px ${cx}px`\"\n >\n <path\n :d=\"wavyData.path\"\n stroke=\"currentColor\"\n :stroke-width=\"STROKE\"\n stroke-linecap=\"round\"\n :stroke-dasharray=\"wavyData.dash\"\n class=\"animate-[m3-wavy-travel_2s_linear_infinite]\"\n :style=\"{ '--m3-wave-len': wavyData.len }\"\n />\n </svg>\n </span>\n</template>\n\n<style>\n/* The SVG element rotates the whole bumpy circle. */\n@keyframes m3-wavy-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n/* The stroke's dashoffset slides by one full path length, so the crests\n appear to crawl along the circle — the \"snake\" motion of M3 Expressive.\n Negative direction makes the wave travel forward relative to the spin. */\n@keyframes m3-wavy-travel {\n from {\n stroke-dashoffset: 0;\n }\n to {\n stroke-dashoffset: calc(var(--m3-wave-len) * -1px);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .animate-\\[m3-wavy-spin_2\\.8s_linear_infinite\\] {\n animation: m3-wavy-spin 2.8s linear infinite;\n }\n .animate-\\[m3-wavy-travel_2s_linear_infinite\\] {\n animation: none !important;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport MSpinner from './MSpinner.vue'\nimport MIcon from './MIcon.vue'\n\nconst NAMED_COLORS = ['primary', 'error'] as const\ntype NamedColor = (typeof NAMED_COLORS)[number]\n\nconst props = withDefaults(\n defineProps<{\n variant?: 'filled' | 'tonal' | 'outlined' | 'text' | 'elevated'\n /**\n * Named semantic color ('primary' | 'error') OR any CSS color string\n * ('red', '#e91e63', 'oklch(0.6 0.2 0)', …).\n * When a CSS color is passed, --color-primary is overridden for this button.\n */\n color?: string\n type?: 'button' | 'submit' | 'reset'\n disabled?: boolean\n loading?: boolean\n icon?: string\n to?: string | Record<string, any>\n }>(),\n {\n variant: 'filled',\n color: 'primary',\n type: 'button',\n disabled: false,\n loading: false,\n },\n)\n\nconst tag = computed(() => props.to ? 'RouterLink' : 'button')\n\nconst isCustomColor = computed(\n () => !!props.color && !(NAMED_COLORS as readonly string[]).includes(props.color),\n)\n\nconst customStyle = computed(() => {\n if (!isCustomColor.value) return undefined\n return {\n '--color-primary': props.color,\n '--color-on-primary': '#ffffff',\n '--color-primary-container': props.color + '33',\n '--color-on-primary-container': props.color,\n }\n})\n\nconst isError = computed(() => props.color === 'error')\n\n// State-layer overlay: before: pseudo-element uses currentColor (the button's text color)\n// so it's always the correct M3 state-layer color for every variant automatically.\nconst base =\n 'relative inline-flex items-center justify-center gap-2 h-10 rounded-full text-label-large font-medium ' +\n 'whitespace-nowrap overflow-hidden transition-[box-shadow,background-color,color] duration-150 select-none cursor-pointer ' +\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:shadow-none ' +\n \"before:content-[''] before:pointer-events-none before:absolute before:inset-0 \" +\n 'before:bg-current before:opacity-0 before:transition-opacity before:duration-150 ' +\n 'enabled:hover:before:opacity-[0.08] enabled:active:before:opacity-[0.12]'\n\nconst variantClasses = computed(() => {\n const err = isError.value\n switch (props.variant) {\n case 'filled':\n return err\n ? 'px-6 bg-error text-on-error enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n : 'px-6 bg-primary text-on-primary enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n case 'tonal':\n return err\n ? 'px-6 bg-error-container text-on-error-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n : 'px-6 bg-secondary-container text-on-secondary-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n case 'elevated':\n return err\n ? 'px-6 bg-surface-container-low text-error shadow-elevation-1 enabled:hover:shadow-elevation-2'\n : 'px-6 bg-surface-container-low text-primary shadow-elevation-1 enabled:hover:shadow-elevation-2'\n case 'outlined':\n return err\n ? 'px-6 border border-error text-error'\n : 'px-6 border border-outline text-primary'\n case 'text':\n return err\n ? 'px-3 text-error'\n : 'px-3 text-primary'\n default:\n return ''\n }\n})\n\nfunction createRipple(event: PointerEvent) {\n if (props.disabled || props.loading) return\n const button = event.currentTarget as HTMLElement\n const rect = button.getBoundingClientRect()\n const d = Math.max(rect.width, rect.height) * 2\n const el = document.createElement('span')\n el.className = 'm3-ripple'\n el.style.cssText = `width:${d}px;height:${d}px;top:${event.clientY - rect.top - d / 2}px;left:${event.clientX - rect.left - d / 2}px`\n button.appendChild(el)\n el.addEventListener('animationend', () => el.remove(), { once: true })\n}\n</script>\n\n<template>\n <component\n :is=\"tag\"\n :to=\"to || undefined\"\n :type=\"to ? undefined : type\"\n :disabled=\"disabled || loading\"\n :class=\"[base, variantClasses]\"\n :style=\"customStyle\"\n @pointerdown=\"createRipple\"\n >\n <MSpinner v-if=\"loading\" :size=\"18\" />\n <MIcon v-else-if=\"icon\" :name=\"icon\" :size=\"20\" />\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport MSpinner from './MSpinner.vue'\nimport MIcon from './MIcon.vue'\n\nconst NAMED_COLORS = ['primary', 'error'] as const\ntype NamedColor = (typeof NAMED_COLORS)[number]\n\nconst props = withDefaults(\n defineProps<{\n variant?: 'filled' | 'tonal' | 'outlined' | 'text' | 'elevated'\n /**\n * Named semantic color ('primary' | 'error') OR any CSS color string\n * ('red', '#e91e63', 'oklch(0.6 0.2 0)', …).\n * When a CSS color is passed, --color-primary is overridden for this button.\n */\n color?: string\n type?: 'button' | 'submit' | 'reset'\n disabled?: boolean\n loading?: boolean\n icon?: string\n to?: string | Record<string, any>\n }>(),\n {\n variant: 'filled',\n color: 'primary',\n type: 'button',\n disabled: false,\n loading: false,\n },\n)\n\nconst tag = computed(() => props.to ? 'RouterLink' : 'button')\n\nconst isCustomColor = computed(\n () => !!props.color && !(NAMED_COLORS as readonly string[]).includes(props.color),\n)\n\nconst customStyle = computed(() => {\n if (!isCustomColor.value) return undefined\n return {\n '--color-primary': props.color,\n '--color-on-primary': '#ffffff',\n '--color-primary-container': props.color + '33',\n '--color-on-primary-container': props.color,\n }\n})\n\nconst isError = computed(() => props.color === 'error')\n\n// State-layer overlay: before: pseudo-element uses currentColor (the button's text color)\n// so it's always the correct M3 state-layer color for every variant automatically.\nconst base =\n 'relative inline-flex items-center justify-center gap-2 h-10 rounded-full text-label-large font-medium ' +\n 'whitespace-nowrap overflow-hidden transition-[box-shadow,background-color,color] duration-150 select-none cursor-pointer ' +\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:shadow-none ' +\n \"before:content-[''] before:pointer-events-none before:absolute before:inset-0 \" +\n 'before:bg-current before:opacity-0 before:transition-opacity before:duration-150 ' +\n 'enabled:hover:before:opacity-[0.08] enabled:active:before:opacity-[0.12]'\n\nconst variantClasses = computed(() => {\n const err = isError.value\n switch (props.variant) {\n case 'filled':\n return err\n ? 'px-6 bg-error text-on-error enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n : 'px-6 bg-primary text-on-primary enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n case 'tonal':\n return err\n ? 'px-6 bg-error-container text-on-error-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n : 'px-6 bg-secondary-container text-on-secondary-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n case 'elevated':\n return err\n ? 'px-6 bg-surface-container-low text-error shadow-elevation-1 enabled:hover:shadow-elevation-2'\n : 'px-6 bg-surface-container-low text-primary shadow-elevation-1 enabled:hover:shadow-elevation-2'\n case 'outlined':\n return err\n ? 'px-6 border border-error text-error'\n : 'px-6 border border-outline text-primary'\n case 'text':\n return err\n ? 'px-3 text-error'\n : 'px-3 text-primary'\n default:\n return ''\n }\n})\n\nfunction createRipple(event: PointerEvent) {\n if (props.disabled || props.loading) return\n const button = event.currentTarget as HTMLElement\n const rect = button.getBoundingClientRect()\n const d = Math.max(rect.width, rect.height) * 2\n const el = document.createElement('span')\n el.className = 'm3-ripple'\n el.style.cssText = `width:${d}px;height:${d}px;top:${event.clientY - rect.top - d / 2}px;left:${event.clientX - rect.left - d / 2}px`\n button.appendChild(el)\n el.addEventListener('animationend', () => el.remove(), { once: true })\n}\n</script>\n\n<template>\n <component\n :is=\"tag\"\n :to=\"to || undefined\"\n :type=\"to ? undefined : type\"\n :disabled=\"disabled || loading\"\n :class=\"[base, variantClasses]\"\n :style=\"customStyle\"\n @pointerdown=\"createRipple\"\n >\n <MSpinner v-if=\"loading\" :size=\"18\" />\n <MIcon v-else-if=\"icon\" :name=\"icon\" :size=\"20\" />\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport MIcon from './MIcon.vue'\n\nconst props = withDefaults(\n defineProps<{\n icon: string\n label?: string\n variant?: 'standard' | 'filled' | 'tonal' | 'outlined'\n disabled?: boolean\n size?: number\n to?: string | Record<string, any>\n }>(),\n {\n variant: 'standard',\n disabled: false,\n size: 40,\n },\n)\n\nconst tag = computed(() => props.to ? 'RouterLink' : 'button')\n\nconst base =\n 'inline-flex shrink-0 items-center justify-center rounded-full transition-colors duration-150 cursor-pointer ' +\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]'\n\nconst variantClasses = computed(() => {\n switch (props.variant) {\n case 'filled':\n return 'bg-primary text-on-primary hover:shadow-elevation-1'\n case 'tonal':\n return 'bg-secondary-container text-on-secondary-container hover:shadow-elevation-1'\n case 'outlined':\n return 'border border-outline text-on-surface-variant hover:bg-on-surface/8'\n default:\n return 'text-on-surface-variant hover:bg-on-surface/8 active:bg-on-surface/12'\n }\n})\n</script>\n\n<template>\n <component\n :is=\"tag\"\n :to=\"to || undefined\"\n :type=\"to ? undefined : 'button'\"\n :aria-label=\"label || undefined\"\n :disabled=\"disabled\"\n :class=\"[base, variantClasses]\"\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\n >\n <MIcon :name=\"icon\" :size=\"Math.round(size * 0.55)\" />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport MIcon from './MIcon.vue'\n\nconst props = withDefaults(\n defineProps<{\n icon: string\n label?: string\n variant?: 'standard' | 'filled' | 'tonal' | 'outlined'\n disabled?: boolean\n size?: number\n to?: string | Record<string, any>\n }>(),\n {\n variant: 'standard',\n disabled: false,\n size: 40,\n },\n)\n\nconst tag = computed(() => props.to ? 'RouterLink' : 'button')\n\nconst base =\n 'inline-flex shrink-0 items-center justify-center rounded-full transition-colors duration-150 cursor-pointer ' +\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]'\n\nconst variantClasses = computed(() => {\n switch (props.variant) {\n case 'filled':\n return 'bg-primary text-on-primary hover:shadow-elevation-1'\n case 'tonal':\n return 'bg-secondary-container text-on-secondary-container hover:shadow-elevation-1'\n case 'outlined':\n return 'border border-outline text-on-surface-variant hover:bg-on-surface/8'\n default:\n return 'text-on-surface-variant hover:bg-on-surface/8 active:bg-on-surface/12'\n }\n})\n</script>\n\n<template>\n <component\n :is=\"tag\"\n :to=\"to || undefined\"\n :type=\"to ? undefined : 'button'\"\n :aria-label=\"label || undefined\"\n :disabled=\"disabled\"\n :class=\"[base, variantClasses]\"\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\n >\n <MIcon :name=\"icon\" :size=\"Math.round(size * 0.55)\" />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { watch } from 'vue'\nimport MIconButton from './MIconButton.vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue: boolean\n title?: string\n maxWidth?: string\n persistent?: boolean\n }>(),\n {\n maxWidth: 'max-w-md',\n persistent: false,\n },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [boolean] }>()\n\nfunction close() {\n if (props.persistent) return\n emit('update:modelValue', false)\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape') close()\n}\n\nwatch(\n () => props.modelValue,\n (open) => {\n if (open) {\n document.addEventListener('keydown', onKeydown)\n document.body.style.overflow = 'hidden'\n } else {\n document.removeEventListener('keydown', onKeydown)\n document.body.style.overflow = ''\n }\n },\n)\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition name=\"m3-dialog\">\n <div\n v-if=\"modelValue\"\n class=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\"\n @click.self=\"close\"\n >\n <div\n class=\"dialog-box flex max-h-[90vh] w-full flex-col rounded-xl bg-surface-container-high shadow-elevation-3\"\n :class=\"maxWidth\"\n >\n <div class=\"flex items-start justify-between gap-4 px-6 pt-6 pb-2\">\n <h2 class=\"text-headline-small text-on-surface\">\n <slot name=\"title\">{{ title }}</slot>\n </h2>\n <MIconButton v-if=\"!persistent\" icon=\"close\" label=\"Cerrar\" @click=\"close\" />\n </div>\n <div class=\"overflow-y-auto px-6 py-2 text-body-medium text-on-surface-variant\">\n <slot />\n </div>\n <div v-if=\"$slots.actions\" class=\"flex justify-end gap-2 px-6 py-4\">\n <slot name=\"actions\" />\n </div>\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n\n<style scoped>\n.m3-dialog-enter-active,\n.m3-dialog-leave-active {\n transition: opacity 0.15s ease;\n}\n.m3-dialog-enter-from,\n.m3-dialog-leave-to {\n opacity: 0;\n}\n.m3-dialog-enter-active .dialog-box,\n.m3-dialog-leave-active .dialog-box {\n transition: transform 0.15s ease;\n}\n.m3-dialog-enter-from .dialog-box,\n.m3-dialog-leave-to .dialog-box {\n transform: scale(0.95);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { watch } from 'vue'\nimport MIconButton from './MIconButton.vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue: boolean\n title?: string\n maxWidth?: string\n persistent?: boolean\n }>(),\n {\n maxWidth: 'max-w-md',\n persistent: false,\n },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [boolean] }>()\n\nfunction close() {\n if (props.persistent) return\n emit('update:modelValue', false)\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape') close()\n}\n\nwatch(\n () => props.modelValue,\n (open) => {\n if (open) {\n document.addEventListener('keydown', onKeydown)\n document.body.style.overflow = 'hidden'\n } else {\n document.removeEventListener('keydown', onKeydown)\n document.body.style.overflow = ''\n }\n },\n)\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition name=\"m3-dialog\">\n <div\n v-if=\"modelValue\"\n class=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\"\n @click.self=\"close\"\n >\n <div\n class=\"dialog-box flex max-h-[90vh] w-full flex-col rounded-xl bg-surface-container-high shadow-elevation-3\"\n :class=\"maxWidth\"\n >\n <div class=\"flex items-start justify-between gap-4 px-6 pt-6 pb-2\">\n <h2 class=\"text-headline-small text-on-surface\">\n <slot name=\"title\">{{ title }}</slot>\n </h2>\n <MIconButton v-if=\"!persistent\" icon=\"close\" label=\"Cerrar\" @click=\"close\" />\n </div>\n <div class=\"overflow-y-auto px-6 py-2 text-body-medium text-on-surface-variant\">\n <slot />\n </div>\n <div v-if=\"$slots.actions\" class=\"flex justify-end gap-2 px-6 py-4\">\n <slot name=\"actions\" />\n </div>\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n\n<style scoped>\n.m3-dialog-enter-active,\n.m3-dialog-leave-active {\n transition: opacity 0.15s ease;\n}\n.m3-dialog-enter-from,\n.m3-dialog-leave-to {\n opacity: 0;\n}\n.m3-dialog-enter-active .dialog-box,\n.m3-dialog-leave-active .dialog-box {\n transition: transform 0.15s ease;\n}\n.m3-dialog-enter-from .dialog-box,\n.m3-dialog-leave-to .dialog-box {\n transform: scale(0.95);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, useId, useSlots } from \"vue\";\nimport MIcon from \"./MIcon.vue\";\nimport { useFieldBg } from \"../composables/useFieldBg\";\n\nconst props = withDefaults(\n defineProps<{\n modelValue: string | number;\n label: string;\n type?: string;\n variant?: \"filled\" | \"outlined\";\n error?: string;\n hint?: string;\n disabled?: boolean;\n required?: boolean;\n multiline?: boolean;\n rows?: number;\n autocomplete?: string;\n leadingIcon?: string;\n /**\n * Background color behind the label in outlined variant.\n * Defaults to the page surface color. Pass e.g. 'var(--color-surface-container-low)'\n * when the input is inside a card.\n */\n fieldBg?: string;\n }>(),\n {\n type: \"text\",\n variant: \"filled\",\n rows: 3,\n },\n);\n\nconst emit = defineEmits<{ \"update:modelValue\": [string] }>();\n\nconst id = useId();\nconst slots = useSlots();\n\nconst fieldBgEl = ref<HTMLElement | null>(null);\nconst { resolvedFieldBg } = useFieldBg(fieldBgEl, () => props.fieldBg);\n\nconst inputClasses = computed(() => {\n const hasTrailing = !!slots.trailing;\n const pl = props.leadingIcon ? \"pl-12\" : \"pl-4\";\n const pr = hasTrailing ? \"pr-12\" : \"pr-4\";\n const size = props.multiline ? \"resize-y min-h-[56px]\" : \"h-14\";\n const base = [\n \"peer block w-full text-body-large text-on-surface outline-none placeholder:text-transparent\",\n \"transition-[border-color,border-width] duration-150\",\n \"disabled:cursor-not-allowed disabled:opacity-[0.38]\",\n size,\n pl,\n pr,\n ];\n\n if (props.variant === \"outlined\") {\n return [\n ...base,\n \"rounded-sm border bg-transparent py-4\",\n props.error\n ? \"border-error focus:border-2 focus:border-error\"\n : \"border-outline hover:border-on-surface focus:border-2 focus:border-primary\",\n ].join(\" \");\n }\n\n return [\n ...base,\n \"rounded-t-sm bg-surface-container-highest border-b pt-6 pb-2\",\n props.error\n ? \"border-error focus:border-b-2 focus:border-error\"\n : \"border-on-surface-variant hover:border-on-surface focus:border-b-2 focus:border-primary\",\n ].join(\" \");\n});\n\nconst labelClasses = computed(() => {\n const left = props.leadingIcon\n ? props.variant === \"outlined\"\n ? \"left-11\"\n : \"left-12\"\n : props.variant === \"outlined\"\n ? \"left-3\"\n : \"left-4\";\n\n const base = [\n \"pointer-events-none absolute truncate transition-all duration-200\",\n left,\n \"right-4\",\n \"top-1/2 -translate-y-1/2 text-body-large\",\n ];\n\n if (props.variant === \"outlined\") {\n // When floated: drop right-4 (right-auto) and cap max-width so the label\n // shrinks to its own text width. The bg then only covers the glyphs + px-1,\n // cutting the border just where the text sits instead of a long strip.\n return [\n ...base,\n \"peer-focus:-top-2.5 peer-focus:translate-y-0 peer-focus:text-label-small peer-focus:right-auto peer-focus:max-w-[calc(100%-1.5rem)] peer-focus:bg-[var(--field-bg)] peer-focus:px-1\",\n \"peer-[&:not(:placeholder-shown)]:-top-2.5 peer-[&:not(:placeholder-shown)]:translate-y-0 peer-[&:not(:placeholder-shown)]:right-auto peer-[&:not(:placeholder-shown)]:max-w-[calc(100%-1.5rem)]\",\n \"peer-[&:not(:placeholder-shown)]:text-label-small peer-[&:not(:placeholder-shown)]:bg-[var(--field-bg)] peer-[&:not(:placeholder-shown)]:px-1\",\n props.error\n ? \"text-error peer-focus:text-error\"\n : \"text-on-surface-variant peer-focus:text-primary\",\n ].join(\" \");\n }\n\n // Filled: label floats to top-2 (slightly higher than before)\n return [\n ...base,\n \"peer-focus:top-2 peer-focus:translate-y-0 peer-focus:text-label-small\",\n \"peer-[&:not(:placeholder-shown)]:top-2 peer-[&:not(:placeholder-shown)]:translate-y-0 peer-[&:not(:placeholder-shown)]:text-label-small\",\n props.error\n ? \"text-error peer-focus:text-error\"\n : \"text-on-surface-variant peer-focus:text-primary\",\n ].join(\" \");\n});\n\nfunction onInput(event: Event) {\n const target = event.target as HTMLInputElement | HTMLTextAreaElement;\n emit(\"update:modelValue\", target.value);\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-1\">\n <!--\n --field-bg: background behind the floating label in outlined mode, so it\n \"cuts through\" the border. Auto-detected from the nearest opaque ancestor\n (see resolveBg); overridable via the fieldBg prop; falls back to surface.\n -->\n <div\n ref=\"fieldBgEl\"\n class=\"relative\"\n :class=\"variant === 'outlined' ? 'mt-2' : ''\"\n :style=\"variant === 'outlined' ? { '--field-bg': resolvedFieldBg } : undefined\"\n >\n <!-- Leading icon: centered in the 48px left zone (left-3.5 → center at 24px) -->\n <div\n v-if=\"leadingIcon\"\n class=\"pointer-events-none absolute left-3.5 top-1/2 -translate-y-1/2 text-on-surface-variant\"\n >\n <MIcon :name=\"leadingIcon\" :size=\"20\" />\n </div>\n\n <textarea\n v-if=\"multiline\"\n :id=\"id\"\n :value=\"String(modelValue)\"\n :rows=\"rows\"\n :disabled=\"disabled\"\n :required=\"required\"\n placeholder=\" \"\n :class=\"inputClasses\"\n @input=\"onInput\"\n />\n <input\n v-else\n :id=\"id\"\n :type=\"type\"\n :value=\"modelValue\"\n :disabled=\"disabled\"\n :required=\"required\"\n :autocomplete=\"autocomplete\"\n placeholder=\" \"\n :class=\"inputClasses\"\n @input=\"onInput\"\n />\n\n <label :for=\"id\" :class=\"labelClasses\">\n {{ label }}<span v-if=\"required\" class=\"text-error\"> *</span>\n </label>\n\n <div v-if=\"$slots.trailing\" class=\"absolute top-1/2 right-2 -translate-y-1/2\">\n <slot name=\"trailing\" />\n </div>\n </div>\n\n <p v-if=\"error\" class=\"px-4 text-body-small text-error\">{{ error }}</p>\n <p v-else-if=\"hint\" class=\"px-4 text-body-small text-on-surface-variant\">{{ hint }}</p>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useId, useSlots } from \"vue\";\nimport MIcon from \"./MIcon.vue\";\nimport { useFieldBg } from \"../composables/useFieldBg\";\n\nconst props = withDefaults(\n defineProps<{\n modelValue: string | number;\n label: string;\n type?: string;\n variant?: \"filled\" | \"outlined\";\n error?: string;\n hint?: string;\n disabled?: boolean;\n required?: boolean;\n multiline?: boolean;\n rows?: number;\n autocomplete?: string;\n leadingIcon?: string;\n /**\n * Background color behind the label in outlined variant.\n * Defaults to the page surface color. Pass e.g. 'var(--color-surface-container-low)'\n * when the input is inside a card.\n */\n fieldBg?: string;\n }>(),\n {\n type: \"text\",\n variant: \"filled\",\n rows: 3,\n },\n);\n\nconst emit = defineEmits<{ \"update:modelValue\": [string] }>();\n\nconst id = useId();\nconst slots = useSlots();\n\nconst fieldBgEl = ref<HTMLElement | null>(null);\nconst { resolvedFieldBg } = useFieldBg(fieldBgEl, () => props.fieldBg);\n\nconst inputClasses = computed(() => {\n const hasTrailing = !!slots.trailing;\n const pl = props.leadingIcon ? \"pl-12\" : \"pl-4\";\n const pr = hasTrailing ? \"pr-12\" : \"pr-4\";\n const size = props.multiline ? \"resize-y min-h-[56px]\" : \"h-14\";\n const base = [\n \"peer block w-full text-body-large text-on-surface outline-none placeholder:text-transparent\",\n \"transition-[border-color,border-width] duration-150\",\n \"disabled:cursor-not-allowed disabled:opacity-[0.38]\",\n size,\n pl,\n pr,\n ];\n\n if (props.variant === \"outlined\") {\n return [\n ...base,\n \"rounded-sm border bg-transparent py-4\",\n props.error\n ? \"border-error focus:border-2 focus:border-error\"\n : \"border-outline hover:border-on-surface focus:border-2 focus:border-primary\",\n ].join(\" \");\n }\n\n return [\n ...base,\n \"rounded-t-sm bg-surface-container-highest border-b pt-6 pb-2\",\n props.error\n ? \"border-error focus:border-b-2 focus:border-error\"\n : \"border-on-surface-variant hover:border-on-surface focus:border-b-2 focus:border-primary\",\n ].join(\" \");\n});\n\nconst labelClasses = computed(() => {\n const left = props.leadingIcon\n ? props.variant === \"outlined\"\n ? \"left-11\"\n : \"left-12\"\n : props.variant === \"outlined\"\n ? \"left-3\"\n : \"left-4\";\n\n const base = [\n \"pointer-events-none absolute truncate transition-all duration-200\",\n left,\n \"right-4\",\n \"top-1/2 -translate-y-1/2 text-body-large\",\n ];\n\n if (props.variant === \"outlined\") {\n // When floated: drop right-4 (right-auto) and cap max-width so the label\n // shrinks to its own text width. The bg then only covers the glyphs + px-1,\n // cutting the border just where the text sits instead of a long strip.\n return [\n ...base,\n \"peer-focus:-top-2.5 peer-focus:translate-y-0 peer-focus:text-label-small peer-focus:right-auto peer-focus:max-w-[calc(100%-1.5rem)] peer-focus:bg-[var(--field-bg)] peer-focus:px-1\",\n \"peer-[&:not(:placeholder-shown)]:-top-2.5 peer-[&:not(:placeholder-shown)]:translate-y-0 peer-[&:not(:placeholder-shown)]:right-auto peer-[&:not(:placeholder-shown)]:max-w-[calc(100%-1.5rem)]\",\n \"peer-[&:not(:placeholder-shown)]:text-label-small peer-[&:not(:placeholder-shown)]:bg-[var(--field-bg)] peer-[&:not(:placeholder-shown)]:px-1\",\n props.error\n ? \"text-error peer-focus:text-error\"\n : \"text-on-surface-variant peer-focus:text-primary\",\n ].join(\" \");\n }\n\n // Filled: label floats to top-2 (slightly higher than before)\n return [\n ...base,\n \"peer-focus:top-2 peer-focus:translate-y-0 peer-focus:text-label-small\",\n \"peer-[&:not(:placeholder-shown)]:top-2 peer-[&:not(:placeholder-shown)]:translate-y-0 peer-[&:not(:placeholder-shown)]:text-label-small\",\n props.error\n ? \"text-error peer-focus:text-error\"\n : \"text-on-surface-variant peer-focus:text-primary\",\n ].join(\" \");\n});\n\nfunction onInput(event: Event) {\n const target = event.target as HTMLInputElement | HTMLTextAreaElement;\n emit(\"update:modelValue\", target.value);\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-1\">\n <!--\n --field-bg: background behind the floating label in outlined mode, so it\n \"cuts through\" the border. Auto-detected from the nearest opaque ancestor\n (see resolveBg); overridable via the fieldBg prop; falls back to surface.\n -->\n <div\n ref=\"fieldBgEl\"\n class=\"relative\"\n :class=\"variant === 'outlined' ? 'mt-2' : ''\"\n :style=\"variant === 'outlined' ? { '--field-bg': resolvedFieldBg } : undefined\"\n >\n <!-- Leading icon: centered in the 48px left zone (left-3.5 → center at 24px) -->\n <div\n v-if=\"leadingIcon\"\n class=\"pointer-events-none absolute left-3.5 top-1/2 -translate-y-1/2 text-on-surface-variant\"\n >\n <MIcon :name=\"leadingIcon\" :size=\"20\" />\n </div>\n\n <textarea\n v-if=\"multiline\"\n :id=\"id\"\n :value=\"String(modelValue)\"\n :rows=\"rows\"\n :disabled=\"disabled\"\n :required=\"required\"\n placeholder=\" \"\n :class=\"inputClasses\"\n @input=\"onInput\"\n />\n <input\n v-else\n :id=\"id\"\n :type=\"type\"\n :value=\"modelValue\"\n :disabled=\"disabled\"\n :required=\"required\"\n :autocomplete=\"autocomplete\"\n placeholder=\" \"\n :class=\"inputClasses\"\n @input=\"onInput\"\n />\n\n <label :for=\"id\" :class=\"labelClasses\">\n {{ label }}<span v-if=\"required\" class=\"text-error\"> *</span>\n </label>\n\n <div v-if=\"$slots.trailing\" class=\"absolute top-1/2 right-2 -translate-y-1/2\">\n <slot name=\"trailing\" />\n </div>\n </div>\n\n <p v-if=\"error\" class=\"px-4 text-body-small text-error\">{{ error }}</p>\n <p v-else-if=\"hint\" class=\"px-4 text-body-small text-on-surface-variant\">{{ hint }}</p>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nconst props = withDefaults(\n defineProps<{\n /** Which edge of the trigger the dropdown aligns to. */\n align?: 'left' | 'right'\n }>(),\n { align: 'right' },\n)\n\nconst open = ref(false)\nconst triggerEl = ref<HTMLElement | null>(null)\nconst dropdownEl = ref<HTMLElement | null>(null)\nconst dropStyle = ref<Record<string, string>>({})\n\nfunction computePos() {\n if (!triggerEl.value) return\n const rect = triggerEl.value.getBoundingClientRect()\n const spaceBelow = window.innerHeight - rect.bottom - 8\n const openAbove = spaceBelow < 200 && rect.top > spaceBelow\n\n const style: Record<string, string> = {\n maxHeight: `${Math.min(openAbove ? rect.top - 12 : spaceBelow, 400)}px`,\n }\n\n if (openAbove) {\n style.bottom = `${window.innerHeight - rect.top + 4}px`\n } else {\n style.top = `${rect.bottom + 4}px`\n }\n\n if (props.align === 'right') {\n style.right = `${window.innerWidth - rect.right}px`\n } else {\n style.left = `${rect.left}px`\n }\n\n dropStyle.value = style\n}\n\nfunction toggle() {\n if (!open.value) computePos()\n open.value = !open.value\n}\n\nfunction close() {\n open.value = false\n}\n\ndefineExpose({ close, open })\n\nfunction onOutsideClick(e: MouseEvent) {\n const t = e.target as Node\n if (!triggerEl.value?.contains(t) && !dropdownEl.value?.contains(t)) close()\n}\n\nfunction onScroll(e: Event) {\n if (!open.value) return\n if (dropdownEl.value?.contains(e.target as Node)) return\n if (!triggerEl.value) return\n const rect = triggerEl.value.getBoundingClientRect()\n if (rect.bottom < 0 || rect.top > window.innerHeight) { close(); return }\n computePos()\n}\n\nfunction onKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape') close()\n}\n\nonMounted(() => {\n document.addEventListener('mousedown', onOutsideClick)\n document.addEventListener('keydown', onKeydown)\n window.addEventListener('scroll', onScroll, true)\n})\n\nonUnmounted(() => {\n document.removeEventListener('mousedown', onOutsideClick)\n document.removeEventListener('keydown', onKeydown)\n window.removeEventListener('scroll', onScroll, true)\n})\n\nconst origin = computed(() =>\n props.align === 'right' ? 'top right' : 'top left',\n)\n</script>\n\n<template>\n <div ref=\"triggerEl\" class=\"inline-block\" @click=\"toggle\">\n <slot name=\"trigger\" :open=\"open\" />\n </div>\n\n <Teleport to=\"body\">\n <Transition\n enter-active-class=\"transition-[opacity,transform] duration-100 ease-out\"\n enter-from-class=\"opacity-0 scale-95\"\n enter-to-class=\"opacity-100 scale-100\"\n leave-active-class=\"transition-[opacity,transform] duration-75 ease-in\"\n leave-from-class=\"opacity-100 scale-100\"\n leave-to-class=\"opacity-0 scale-95\"\n >\n <div\n v-if=\"open\"\n ref=\"dropdownEl\"\n class=\"fixed z-500 min-w-48 overflow-y-auto overflow-x-hidden rounded-xs bg-surface-container py-1 shadow-elevation-2\"\n :style=\"{ ...dropStyle, transformOrigin: origin }\"\n @click=\"close\"\n >\n <slot />\n </div>\n </Transition>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nconst props = withDefaults(\n defineProps<{\n /** Which edge of the trigger the dropdown aligns to. */\n align?: 'left' | 'right'\n }>(),\n { align: 'right' },\n)\n\nconst open = ref(false)\nconst triggerEl = ref<HTMLElement | null>(null)\nconst dropdownEl = ref<HTMLElement | null>(null)\nconst dropStyle = ref<Record<string, string>>({})\n\nfunction computePos() {\n if (!triggerEl.value) return\n const rect = triggerEl.value.getBoundingClientRect()\n const spaceBelow = window.innerHeight - rect.bottom - 8\n const openAbove = spaceBelow < 200 && rect.top > spaceBelow\n\n const style: Record<string, string> = {\n maxHeight: `${Math.min(openAbove ? rect.top - 12 : spaceBelow, 400)}px`,\n }\n\n if (openAbove) {\n style.bottom = `${window.innerHeight - rect.top + 4}px`\n } else {\n style.top = `${rect.bottom + 4}px`\n }\n\n if (props.align === 'right') {\n style.right = `${window.innerWidth - rect.right}px`\n } else {\n style.left = `${rect.left}px`\n }\n\n dropStyle.value = style\n}\n\nfunction toggle() {\n if (!open.value) computePos()\n open.value = !open.value\n}\n\nfunction close() {\n open.value = false\n}\n\ndefineExpose({ close, open })\n\nfunction onOutsideClick(e: MouseEvent) {\n const t = e.target as Node\n if (!triggerEl.value?.contains(t) && !dropdownEl.value?.contains(t)) close()\n}\n\nfunction onScroll(e: Event) {\n if (!open.value) return\n if (dropdownEl.value?.contains(e.target as Node)) return\n if (!triggerEl.value) return\n const rect = triggerEl.value.getBoundingClientRect()\n if (rect.bottom < 0 || rect.top > window.innerHeight) { close(); return }\n computePos()\n}\n\nfunction onKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape') close()\n}\n\nonMounted(() => {\n document.addEventListener('mousedown', onOutsideClick)\n document.addEventListener('keydown', onKeydown)\n window.addEventListener('scroll', onScroll, true)\n})\n\nonUnmounted(() => {\n document.removeEventListener('mousedown', onOutsideClick)\n document.removeEventListener('keydown', onKeydown)\n window.removeEventListener('scroll', onScroll, true)\n})\n\nconst origin = computed(() =>\n props.align === 'right' ? 'top right' : 'top left',\n)\n</script>\n\n<template>\n <div ref=\"triggerEl\" class=\"inline-block\" @click=\"toggle\">\n <slot name=\"trigger\" :open=\"open\" />\n </div>\n\n <Teleport to=\"body\">\n <Transition\n enter-active-class=\"transition-[opacity,transform] duration-100 ease-out\"\n enter-from-class=\"opacity-0 scale-95\"\n enter-to-class=\"opacity-100 scale-100\"\n leave-active-class=\"transition-[opacity,transform] duration-75 ease-in\"\n leave-from-class=\"opacity-100 scale-100\"\n leave-to-class=\"opacity-0 scale-95\"\n >\n <div\n v-if=\"open\"\n ref=\"dropdownEl\"\n class=\"fixed z-500 min-w-48 overflow-y-auto overflow-x-hidden rounded-xs bg-surface-container py-1 shadow-elevation-2\"\n :style=\"{ ...dropStyle, transformOrigin: origin }\"\n @click=\"close\"\n >\n <slot />\n </div>\n </Transition>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport MIcon from './MIcon.vue'\n\nconst props = withDefaults(defineProps<{ icon?: string; to?: string | Record<string, any> }>(), {})\n\nconst tag = computed(() => props.to ? 'RouterLink' : 'button')\n</script>\n\n<template>\n <component\n :is=\"tag\"\n :to=\"to || undefined\"\n :type=\"to ? undefined : 'button'\"\n class=\"flex w-full cursor-pointer items-center gap-3 px-4 py-2.5 text-left text-body-large text-on-surface hover:bg-on-surface/8\"\n >\n <MIcon v-if=\"icon\" :name=\"icon\" :size=\"20\" class=\"text-on-surface-variant\" />\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport MIcon from './MIcon.vue'\n\nconst props = withDefaults(defineProps<{ icon?: string; to?: string | Record<string, any> }>(), {})\n\nconst tag = computed(() => props.to ? 'RouterLink' : 'button')\n</script>\n\n<template>\n <component\n :is=\"tag\"\n :to=\"to || undefined\"\n :type=\"to ? undefined : 'button'\"\n class=\"flex w-full cursor-pointer items-center gap-3 px-4 py-2.5 text-left text-body-large text-on-surface hover:bg-on-surface/8\"\n >\n <MIcon v-if=\"icon\" :name=\"icon\" :size=\"20\" class=\"text-on-surface-variant\" />\n <slot />\n </component>\n</template>\n"],"mappings":"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"}
|