@m3ui-vue/m3ui-vue 0.4.2 → 0.4.3
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-BsZO5XuL.js → MMenuItem-COdgD4m7.js} +68 -48
- package/dist/MMenuItem-COdgD4m7.js.map +1 -0
- package/dist/components/MAutocomplete.vue.d.ts +4 -0
- package/dist/components/MMaskField.vue.d.ts +4 -0
- package/dist/components/MMultiAutocomplete.vue.d.ts +4 -0
- package/dist/components/MNumberField.vue.d.ts +4 -0
- package/dist/components/MSpotlightSearch.vue.d.ts +1 -1
- package/dist/components/MTagInput.vue.d.ts +4 -0
- package/dist/components/MTextField.vue.d.ts +4 -0
- package/dist/composables/useDebounce.d.ts +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/m3ui-vue.css +1 -1
- package/dist/m3ui.js +3362 -3324
- package/dist/m3ui.js.map +1 -1
- package/dist/rich-text-editor.js +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/__tests__/useDebounce.test.ts +75 -0
- package/src/components/MAutocomplete.vue +30 -7
- package/src/components/MMaskField.vue +9 -2
- package/src/components/MMultiAutocomplete.vue +30 -7
- package/src/components/MNumberField.vue +22 -7
- package/src/components/MTagInput.vue +11 -3
- package/src/components/MTextField.vue +8 -2
- package/src/composables/useDebounce.ts +24 -0
- package/src/index.ts +1 -0
- package/dist/MMenuItem-BsZO5XuL.js.map +0 -1
|
@@ -80,7 +80,7 @@ function I() {
|
|
|
80
80
|
}
|
|
81
81
|
//#endregion
|
|
82
82
|
//#region src/components/MSpinner.vue?vue&type=script&setup=true&lang.ts
|
|
83
|
-
var
|
|
83
|
+
var L = ["aria-label"], ee = {
|
|
84
84
|
key: 0,
|
|
85
85
|
class: "block h-full w-full animate-spin rounded-full border-2 border-current border-t-transparent"
|
|
86
86
|
}, R = [
|
|
@@ -135,7 +135,7 @@ var ee = ["aria-label"], L = {
|
|
|
135
135
|
"stroke-dasharray": o.value.dash,
|
|
136
136
|
class: "animate-[m3-wavy-travel_2s_linear_infinite]",
|
|
137
137
|
style: h({ "--m3-wave-len": o.value.len })
|
|
138
|
-
}, null, 12, z)], 12, R)) : (y(), c("span",
|
|
138
|
+
}, null, 12, z)], 12, R)) : (y(), c("span", ee))], 12, L));
|
|
139
139
|
}
|
|
140
140
|
}), U = [
|
|
141
141
|
"bg-surface-container-highest",
|
|
@@ -210,8 +210,25 @@ function K(e, t) {
|
|
|
210
210
|
}), g(() => o?.disconnect()), { resolvedFieldBg: a(() => t() ?? n.value) };
|
|
211
211
|
}
|
|
212
212
|
//#endregion
|
|
213
|
+
//#region src/composables/useDebounce.ts
|
|
214
|
+
function q(e, t) {
|
|
215
|
+
let n = null;
|
|
216
|
+
function r(...r) {
|
|
217
|
+
n && clearTimeout(n), n = setTimeout(() => {
|
|
218
|
+
n = null, e(...r);
|
|
219
|
+
}, t);
|
|
220
|
+
}
|
|
221
|
+
function i() {
|
|
222
|
+
n &&= (clearTimeout(n), null);
|
|
223
|
+
}
|
|
224
|
+
return g(i), {
|
|
225
|
+
debounced: r,
|
|
226
|
+
cancel: i
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
//#endregion
|
|
213
230
|
//#region src/components/MIconButton.vue?vue&type=script&setup=true&lang.ts
|
|
214
|
-
var
|
|
231
|
+
var J = "inline-flex shrink-0 items-center justify-center transition-colors duration-150 cursor-pointer disabled:cursor-not-allowed disabled:opacity-[0.38]", Y = /* @__PURE__ */ f({
|
|
215
232
|
__name: "MIconButton",
|
|
216
233
|
props: {
|
|
217
234
|
icon: {},
|
|
@@ -270,7 +287,7 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
270
287
|
"aria-label": t.label || void 0,
|
|
271
288
|
disabled: t.disabled,
|
|
272
289
|
class: m([
|
|
273
|
-
|
|
290
|
+
J,
|
|
274
291
|
c.value,
|
|
275
292
|
u.value,
|
|
276
293
|
"relative overflow-hidden"
|
|
@@ -295,7 +312,7 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
295
312
|
"style"
|
|
296
313
|
]));
|
|
297
314
|
}
|
|
298
|
-
}),
|
|
315
|
+
}), X = "relative inline-flex items-center justify-center gap-2 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]", Z = /* @__PURE__ */ f({
|
|
299
316
|
__name: "MButton",
|
|
300
317
|
props: {
|
|
301
318
|
variant: { default: "filled" },
|
|
@@ -389,7 +406,7 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
389
406
|
type: t.to ? void 0 : t.type,
|
|
390
407
|
disabled: t.disabled || t.loading,
|
|
391
408
|
class: m([
|
|
392
|
-
|
|
409
|
+
X,
|
|
393
410
|
d.value,
|
|
394
411
|
g.value,
|
|
395
412
|
b.value,
|
|
@@ -415,16 +432,16 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
415
432
|
"style"
|
|
416
433
|
]));
|
|
417
434
|
}
|
|
418
|
-
}),
|
|
435
|
+
}), Q = { class: "flex items-start justify-between gap-4 px-6 pt-6 pb-2" }, te = { class: "text-headline-small text-on-surface" }, ne = { class: "overflow-y-auto px-6 py-2 text-body-medium text-on-surface-variant" }, re = {
|
|
419
436
|
key: 0,
|
|
420
437
|
class: "flex justify-end gap-2 px-6 py-4"
|
|
421
|
-
},
|
|
438
|
+
}, ie = {
|
|
422
439
|
key: 0,
|
|
423
440
|
class: "dialog-fs fixed inset-0 z-50 flex flex-col bg-surface"
|
|
424
|
-
},
|
|
441
|
+
}, ae = { class: "flex h-14 shrink-0 items-center gap-2 px-2" }, oe = { class: "flex-1 text-title-large font-medium text-on-surface" }, se = {
|
|
425
442
|
key: 1,
|
|
426
443
|
class: "flex items-center gap-2"
|
|
427
|
-
},
|
|
444
|
+
}, ce = { class: "flex-1 overflow-y-auto px-6 py-4 text-body-medium text-on-surface-variant" }, le = /*#__PURE__*/ t(/* @__PURE__ */ f({
|
|
428
445
|
__name: "MDialog",
|
|
429
446
|
props: {
|
|
430
447
|
modelValue: { type: Boolean },
|
|
@@ -455,16 +472,16 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
455
472
|
key: 1,
|
|
456
473
|
name: "m3-dialog-fs"
|
|
457
474
|
}, {
|
|
458
|
-
default: M(() => [e.modelValue ? (y(), c("div",
|
|
459
|
-
e.persistent ? s("", !0) : (y(), o(
|
|
475
|
+
default: M(() => [e.modelValue ? (y(), c("div", ie, [l("div", ae, [
|
|
476
|
+
e.persistent ? s("", !0) : (y(), o(Y, {
|
|
460
477
|
key: 0,
|
|
461
478
|
icon: "close",
|
|
462
479
|
label: e.closeLabel ?? D(a).close,
|
|
463
480
|
onClick: f
|
|
464
481
|
}, null, 8, ["label"])),
|
|
465
|
-
l("h2",
|
|
466
|
-
t.$slots.actions ? (y(), c("div",
|
|
467
|
-
]), l("div",
|
|
482
|
+
l("h2", oe, [C(t.$slots, "title", {}, () => [u(T(e.title), 1)], !0)]),
|
|
483
|
+
t.$slots.actions ? (y(), c("div", se, [C(t.$slots, "actions", {}, void 0, !0)])) : s("", !0)
|
|
484
|
+
]), l("div", ce, [C(t.$slots, "default", {}, void 0, !0)])])) : s("", !0)]),
|
|
468
485
|
_: 3
|
|
469
486
|
})) : (y(), o(i, {
|
|
470
487
|
key: 0,
|
|
@@ -475,44 +492,44 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
475
492
|
class: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",
|
|
476
493
|
onClick: N(f, ["self"])
|
|
477
494
|
}, [l("div", { class: m(["dialog-box flex max-h-[90vh] w-full flex-col rounded-xl bg-surface-container-high shadow-elevation-3", e.maxWidth]) }, [
|
|
478
|
-
l("div",
|
|
495
|
+
l("div", Q, [l("h2", te, [C(t.$slots, "title", {}, () => [u(T(e.title), 1)], !0)]), e.persistent ? s("", !0) : (y(), o(Y, {
|
|
479
496
|
key: 0,
|
|
480
497
|
icon: "close",
|
|
481
498
|
label: e.closeLabel ?? D(a).close,
|
|
482
499
|
onClick: f
|
|
483
500
|
}, null, 8, ["label"]))]),
|
|
484
|
-
l("div",
|
|
485
|
-
t.$slots.actions ? (y(), c("div",
|
|
501
|
+
l("div", ne, [C(t.$slots, "default", {}, void 0, !0)]),
|
|
502
|
+
t.$slots.actions ? (y(), c("div", re, [C(t.$slots, "actions", {}, void 0, !0)])) : s("", !0)
|
|
486
503
|
], 2)])) : s("", !0)]),
|
|
487
504
|
_: 3
|
|
488
505
|
}))]));
|
|
489
506
|
}
|
|
490
|
-
}), [["__scopeId", "data-v-2e3c3567"]]),
|
|
507
|
+
}), [["__scopeId", "data-v-2e3c3567"]]), ue = { class: "flex flex-col gap-1" }, de = [
|
|
491
508
|
"id",
|
|
492
509
|
"value",
|
|
493
510
|
"rows",
|
|
494
511
|
"disabled",
|
|
495
512
|
"required"
|
|
496
|
-
],
|
|
513
|
+
], fe = [
|
|
497
514
|
"id",
|
|
498
515
|
"type",
|
|
499
516
|
"value",
|
|
500
517
|
"disabled",
|
|
501
518
|
"required",
|
|
502
519
|
"autocomplete"
|
|
503
|
-
],
|
|
520
|
+
], pe = ["for"], me = {
|
|
504
521
|
key: 0,
|
|
505
522
|
class: "text-error"
|
|
506
|
-
},
|
|
523
|
+
}, he = {
|
|
507
524
|
key: 3,
|
|
508
525
|
class: "absolute right-2 top-1/2 -translate-y-1/2"
|
|
509
|
-
},
|
|
526
|
+
}, ge = {
|
|
510
527
|
key: 0,
|
|
511
528
|
class: "px-4 text-body-small text-error"
|
|
512
|
-
},
|
|
529
|
+
}, $ = {
|
|
513
530
|
key: 1,
|
|
514
531
|
class: "px-4 text-body-small text-on-surface-variant"
|
|
515
|
-
},
|
|
532
|
+
}, _e = /* @__PURE__ */ f({
|
|
516
533
|
__name: "MTextField",
|
|
517
534
|
props: {
|
|
518
535
|
modelValue: {},
|
|
@@ -531,11 +548,12 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
531
548
|
type: Boolean,
|
|
532
549
|
default: !1
|
|
533
550
|
},
|
|
534
|
-
fieldBg: {}
|
|
551
|
+
fieldBg: {},
|
|
552
|
+
debounce: { default: 0 }
|
|
535
553
|
},
|
|
536
|
-
emits: ["update:modelValue"],
|
|
554
|
+
emits: ["update:modelValue", "debounced"],
|
|
537
555
|
setup(t, { emit: n }) {
|
|
538
|
-
let r = t, i = n, o = O(), f = k(), p = S(null), { resolvedFieldBg: g } = K(p, () => r.fieldBg), _ = a(() => r.clearable && String(r.modelValue).length > 0 && !r.disabled),
|
|
556
|
+
let r = t, i = n, o = O(), f = k(), p = S(null), { resolvedFieldBg: g } = K(p, () => r.fieldBg), { debounced: _, cancel: v } = q((e) => i("debounced", e), r.debounce), b = a(() => r.clearable && String(r.modelValue).length > 0 && !r.disabled), x = a(() => {
|
|
539
557
|
let e = !!f.trailing || r.clearable, t = r.leadingIcon ? "pl-12" : "pl-4", n = e ? "pr-12" : "pr-4", i = [
|
|
540
558
|
"peer block w-full text-body-large text-on-surface outline-none placeholder:text-transparent",
|
|
541
559
|
"transition-[border-color,border-width] duration-150",
|
|
@@ -553,7 +571,7 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
553
571
|
"rounded-t-sm bg-surface-container-highest border-b pt-6 pb-2",
|
|
554
572
|
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"
|
|
555
573
|
].join(" ");
|
|
556
|
-
}),
|
|
574
|
+
}), w = a(() => {
|
|
557
575
|
let e = [
|
|
558
576
|
"pointer-events-none absolute truncate transition-all duration-200",
|
|
559
577
|
r.leadingIcon ? r.variant === "outlined" ? "left-11" : "left-12" : r.variant === "outlined" ? "left-3" : "left-4",
|
|
@@ -573,11 +591,11 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
573
591
|
r.error ? "text-error peer-focus:text-error" : "text-on-surface-variant peer-focus:text-primary"
|
|
574
592
|
].join(" ");
|
|
575
593
|
});
|
|
576
|
-
function
|
|
594
|
+
function E(e) {
|
|
577
595
|
let t = e.target;
|
|
578
|
-
i("update:modelValue", t.value);
|
|
596
|
+
i("update:modelValue", t.value), r.debounce > 0 && _(t.value);
|
|
579
597
|
}
|
|
580
|
-
return (n, r) => (y(), c("div",
|
|
598
|
+
return (n, r) => (y(), c("div", ue, [l("div", {
|
|
581
599
|
ref_key: "fieldBgEl",
|
|
582
600
|
ref: p,
|
|
583
601
|
class: m(["relative", t.variant === "outlined" ? "mt-2" : ""]),
|
|
@@ -598,9 +616,9 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
598
616
|
disabled: t.disabled,
|
|
599
617
|
required: t.required,
|
|
600
618
|
placeholder: " ",
|
|
601
|
-
class: m(
|
|
602
|
-
onInput:
|
|
603
|
-
}, null, 42,
|
|
619
|
+
class: m(x.value),
|
|
620
|
+
onInput: E
|
|
621
|
+
}, null, 42, de)) : (y(), c("input", {
|
|
604
622
|
key: 2,
|
|
605
623
|
id: D(o),
|
|
606
624
|
type: t.type,
|
|
@@ -609,25 +627,27 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
609
627
|
required: t.required,
|
|
610
628
|
autocomplete: t.autocomplete,
|
|
611
629
|
placeholder: " ",
|
|
612
|
-
class: m(
|
|
613
|
-
onInput:
|
|
614
|
-
}, null, 42,
|
|
630
|
+
class: m(x.value),
|
|
631
|
+
onInput: E
|
|
632
|
+
}, null, 42, fe)),
|
|
615
633
|
l("label", {
|
|
616
634
|
for: D(o),
|
|
617
|
-
class: m(
|
|
618
|
-
}, [u(T(t.label), 1), t.required ? (y(), c("span",
|
|
619
|
-
n.$slots.trailing ? (y(), c("div",
|
|
635
|
+
class: m(w.value)
|
|
636
|
+
}, [u(T(t.label), 1), t.required ? (y(), c("span", me, "\xA0*")) : s("", !0)], 10, pe),
|
|
637
|
+
n.$slots.trailing ? (y(), c("div", he, [C(n.$slots, "trailing")])) : b.value ? (y(), c("button", {
|
|
620
638
|
key: 4,
|
|
621
639
|
type: "button",
|
|
622
640
|
class: "absolute right-3 top-1/2 -translate-y-1/2 flex h-6 w-6 cursor-pointer items-center justify-center rounded-full text-on-surface-variant transition-colors hover:bg-on-surface/8 hover:text-on-surface",
|
|
623
|
-
onClick: r[0] ||= (e) =>
|
|
641
|
+
onClick: r[0] ||= (e) => {
|
|
642
|
+
D(v)(), i("update:modelValue", "");
|
|
643
|
+
}
|
|
624
644
|
}, [d(e, {
|
|
625
645
|
name: "close",
|
|
626
646
|
size: 18
|
|
627
647
|
})])) : s("", !0)
|
|
628
|
-
], 6), t.error ? (y(), c("p",
|
|
648
|
+
], 6), t.error ? (y(), c("p", ge, T(t.error), 1)) : t.hint ? (y(), c("p", $, T(t.hint), 1)) : s("", !0)]));
|
|
629
649
|
}
|
|
630
|
-
}),
|
|
650
|
+
}), ve = /* @__PURE__ */ f({
|
|
631
651
|
__name: "MMenu",
|
|
632
652
|
props: { align: { default: "right" } },
|
|
633
653
|
setup(e, { expose: t }) {
|
|
@@ -698,7 +718,7 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
698
718
|
_: 3
|
|
699
719
|
})]))], 64));
|
|
700
720
|
}
|
|
701
|
-
}),
|
|
721
|
+
}), ye = { class: "flex-1" }, be = /* @__PURE__ */ f({
|
|
702
722
|
__name: "MMenuItem",
|
|
703
723
|
props: {
|
|
704
724
|
icon: {},
|
|
@@ -759,7 +779,7 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
759
779
|
size: 20,
|
|
760
780
|
class: m(["shrink-0", t.danger ? "text-error" : "text-on-surface-variant"])
|
|
761
781
|
}, null, 8, ["name", "class"])) : s("", !0),
|
|
762
|
-
l("span",
|
|
782
|
+
l("span", ye, [C(n.$slots, "default")]),
|
|
763
783
|
v.value ? (y(), o(e, {
|
|
764
784
|
key: 1,
|
|
765
785
|
name: "chevron_right",
|
|
@@ -793,6 +813,6 @@ var q = "inline-flex shrink-0 items-center justify-center transition-colors dura
|
|
|
793
813
|
}
|
|
794
814
|
});
|
|
795
815
|
//#endregion
|
|
796
|
-
export {
|
|
816
|
+
export { Z as a, K as c, P as d, I as f, le as i, H as l, ve as n, Y as o, _e as r, q as s, be as t, F as u };
|
|
797
817
|
|
|
798
|
-
//# sourceMappingURL=MMenuItem-
|
|
818
|
+
//# sourceMappingURL=MMenuItem-COdgD4m7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MMenuItem-COdgD4m7.js","names":["$slots","$slots"],"sources":["../src/composables/useLocale.ts","../src/components/MSpinner.vue","../src/components/MSpinner.vue","../src/composables/useFieldBg.ts","../src/composables/useDebounce.ts","../src/components/MIconButton.vue","../src/components/MIconButton.vue","../src/components/MButton.vue","../src/components/MButton.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 { inject, reactive, watchEffect, toValue, type InjectionKey, type MaybeRef } from 'vue'\n\nexport interface M3Locale {\n // Common\n search: string\n noResults: string\n close: string\n cancel: string\n confirm: string\n loading: string\n\n // Navigation\n previous: string\n next: string\n today: string\n more: string\n\n // Tables\n selectedCount: string\n recordCount: string\n expand: string\n columns: string\n exportCsv: string\n noGroup: string\n\n // Tour\n finish: string\n\n // File upload\n dropText: string\n selectText: string\n maxSizePrefix: string\n remove: string\n\n // Pickers\n selectDate: string\n selectTime: string\n selectRange: string\n pickStart: string\n pickEnd: string\n previousMonth: string\n nextMonth: string\n\n // Scheduler\n dayView: string\n weekView: string\n\n // Transfer list\n available: string\n selected: string\n noItems: string\n moveAllRight: string\n moveRight: string\n moveLeft: string\n moveAllLeft: string\n\n // Command palette / Spotlight\n searchCommand: string\n navigateHint: string\n selectHint: string\n openHint: string\n closeHint: string\n\n // Infinite scroll\n loadingMore: string\n noMoreItems: string\n\n // Rich text editor\n bold: string\n italic: string\n underline: string\n strikethrough: string\n highlight: string\n bulletList: string\n orderedList: string\n blockquote: string\n code: string\n alignLeft: string\n alignCenter: string\n alignRight: string\n undo: string\n redo: string\n link: string\n image: string\n paragraph: string\n heading1: string\n heading2: string\n heading3: string\n insertLink: string\n insertImage: string\n imageUrlLabel: string\n insert: string\n}\n\nexport const defaultLocale: M3Locale = {\n search: 'Search...',\n noResults: 'No results',\n close: 'Close',\n cancel: 'Cancel',\n confirm: 'Confirm',\n loading: 'Loading',\n\n previous: 'Previous',\n next: 'Next',\n today: 'Today',\n more: 'more',\n\n selectedCount: 'selected',\n recordCount: 'record',\n expand: 'Expand',\n columns: 'Columns',\n exportCsv: 'Export CSV',\n noGroup: 'No group',\n\n finish: 'Finish',\n\n dropText: 'Drop files here or',\n selectText: 'browse',\n maxSizePrefix: 'Max.',\n remove: 'Remove',\n\n selectDate: 'Select date',\n selectTime: 'Select time',\n selectRange: 'Select range',\n pickStart: 'Select start',\n pickEnd: 'Select end',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n\n dayView: 'Day',\n weekView: 'Week',\n\n available: 'Available',\n selected: 'Selected',\n noItems: 'No items',\n moveAllRight: 'Move all right',\n moveRight: 'Move selected right',\n moveLeft: 'Move selected left',\n moveAllLeft: 'Move all left',\n\n searchCommand: 'Search command...',\n navigateHint: 'navigate',\n selectHint: 'select',\n openHint: 'open',\n closeHint: 'close',\n\n loadingMore: 'Loading...',\n noMoreItems: 'No more items',\n\n bold: 'Bold',\n italic: 'Italic',\n underline: 'Underline',\n strikethrough: 'Strikethrough',\n highlight: 'Highlight',\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n blockquote: 'Blockquote',\n code: 'Code',\n alignLeft: 'Align left',\n alignCenter: 'Align center',\n alignRight: 'Align right',\n undo: 'Undo',\n redo: 'Redo',\n link: 'Link',\n image: 'Image',\n paragraph: 'Paragraph',\n heading1: 'Heading 1',\n heading2: 'Heading 2',\n heading3: 'Heading 3',\n insertLink: 'Insert link',\n insertImage: 'Insert image',\n imageUrlLabel: 'Image URL',\n insert: 'Insert',\n}\n\nexport const M3_LOCALE_KEY: InjectionKey<MaybeRef<Partial<M3Locale>>> = Symbol('m3-locale')\n\nexport function useLocale(): M3Locale {\n const provided = inject(M3_LOCALE_KEY, {})\n const locale = reactive({ ...defaultLocale }) as M3Locale\n\n watchEffect(() => {\n Object.assign(locale, defaultLocale, toValue(provided))\n })\n\n return locale\n}\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { useLocale } from '../composables/useLocale';\n\nconst props = withDefaults(\n defineProps<{\n size?: number;\n wavy?: boolean;\n label?: string;\n }>(),\n { size: 20, wavy: false },\n);\n\nconst locale = useLocale();\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=\"label ?? locale.loading\"\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 { useLocale } from '../composables/useLocale';\n\nconst props = withDefaults(\n defineProps<{\n size?: number;\n wavy?: boolean;\n label?: string;\n }>(),\n { size: 20, wavy: false },\n);\n\nconst locale = useLocale();\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=\"label ?? locale.loading\"\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","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","import { onBeforeUnmount } from 'vue'\n\nexport function useDebounce(fn: (...args: any[]) => void, ms: number) {\n let timer: ReturnType<typeof setTimeout> | null = null\n\n function debounced(...args: any[]) {\n if (timer) clearTimeout(timer)\n timer = setTimeout(() => {\n timer = null\n fn(...args)\n }, ms)\n }\n\n function cancel() {\n if (timer) {\n clearTimeout(timer)\n timer = null\n }\n }\n\n onBeforeUnmount(cancel)\n\n return { debounced, cancel }\n}\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 shape?: 'rounded' | 'squared'\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number\n disabled?: boolean\n to?: string | Record<string, any>\n }>(),\n {\n variant: 'standard',\n shape: 'rounded',\n size: 'sm',\n disabled: false,\n },\n)\n\nconst tag = computed(() => props.to ? 'RouterLink' : 'button')\n\nconst sizeMap = {\n xs: { px: 32, icon: 16 },\n sm: { px: 40, icon: 20 },\n md: { px: 48, icon: 24 },\n lg: { px: 56, icon: 28 },\n xl: { px: 64, icon: 32 },\n}\n\nconst resolved = computed(() => {\n if (typeof props.size === 'number') return { px: props.size, icon: Math.round(props.size * 0.55) }\n return sizeMap[props.size] ?? sizeMap.sm\n})\n\nconst base =\n 'inline-flex shrink-0 items-center justify-center transition-colors duration-150 cursor-pointer ' +\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]'\n\nconst shapeClass = computed(() => props.shape === 'squared' ? 'rounded-md' : 'rounded-full')\n\nfunction createRipple(event: PointerEvent) {\n if (props.disabled) 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\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, shapeClass, variantClasses, 'relative overflow-hidden']\"\n :style=\"{ width: `${resolved.px}px`, height: `${resolved.px}px` }\"\n @pointerdown=\"createRipple\"\n >\n <MIcon :name=\"icon\" :size=\"resolved.icon\" />\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 shape?: 'rounded' | 'squared'\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number\n disabled?: boolean\n to?: string | Record<string, any>\n }>(),\n {\n variant: 'standard',\n shape: 'rounded',\n size: 'sm',\n disabled: false,\n },\n)\n\nconst tag = computed(() => props.to ? 'RouterLink' : 'button')\n\nconst sizeMap = {\n xs: { px: 32, icon: 16 },\n sm: { px: 40, icon: 20 },\n md: { px: 48, icon: 24 },\n lg: { px: 56, icon: 28 },\n xl: { px: 64, icon: 32 },\n}\n\nconst resolved = computed(() => {\n if (typeof props.size === 'number') return { px: props.size, icon: Math.round(props.size * 0.55) }\n return sizeMap[props.size] ?? sizeMap.sm\n})\n\nconst base =\n 'inline-flex shrink-0 items-center justify-center transition-colors duration-150 cursor-pointer ' +\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]'\n\nconst shapeClass = computed(() => props.shape === 'squared' ? 'rounded-md' : 'rounded-full')\n\nfunction createRipple(event: PointerEvent) {\n if (props.disabled) 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\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, shapeClass, variantClasses, 'relative overflow-hidden']\"\n :style=\"{ width: `${resolved.px}px`, height: `${resolved.px}px` }\"\n @pointerdown=\"createRipple\"\n >\n <MIcon :name=\"icon\" :size=\"resolved.icon\" />\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 size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n shape?: 'rounded' | 'squared'\n to?: string | Record<string, any>\n }>(),\n {\n variant: 'filled',\n color: 'primary',\n type: 'button',\n disabled: false,\n loading: false,\n size: 'sm',\n shape: 'rounded',\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\nconst base =\n 'relative inline-flex items-center justify-center gap-2 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 shapeClass = computed(() => props.shape === 'squared' ? 'rounded-md' : 'rounded-full')\n\nconst sizeMap = {\n xs: { h: 'h-8', text: 'text-label-medium', icon: 16, spinner: 14, px: 'px-4', pxIcon: 'pl-3 pr-4', pxText: 'px-2' },\n sm: { h: 'h-10', text: 'text-label-large', icon: 20, spinner: 16, px: 'px-6', pxIcon: 'pl-4 pr-6', pxText: 'px-3' },\n md: { h: 'h-14', text: 'text-title-medium', icon: 20, spinner: 18, px: 'px-6', pxIcon: 'pl-5 pr-6', pxText: 'px-3' },\n lg: { h: 'h-16', text: 'text-title-large', icon: 22, spinner: 20, px: 'px-7', pxIcon: 'pl-6 pr-7', pxText: 'px-4' },\n xl: { h: 'h-20', text: 'text-headline-small', icon: 24, spinner: 22, px: 'px-8', pxIcon: 'pl-7 pr-8', pxText: 'px-4' },\n}\n\nconst s = computed(() => sizeMap[props.size] ?? sizeMap.sm)\nconst sizeClasses = computed(() => `${s.value.h} ${s.value.text}`)\nconst iconSize = computed(() => s.value.icon)\nconst spinnerSize = computed(() => s.value.spinner)\n\nconst px = computed(() => {\n if (props.variant === 'text') return s.value.pxText\n return (props.icon || props.loading) ? s.value.pxIcon : s.value.px\n})\n\nconst variantClasses = computed(() => {\n const err = isError.value\n switch (props.variant) {\n case 'filled':\n return err\n ? 'bg-error text-on-error enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n : 'bg-primary text-on-primary enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n case 'tonal':\n return err\n ? 'bg-error-container text-on-error-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n : 'bg-secondary-container text-on-secondary-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n case 'elevated':\n return err\n ? 'bg-surface-container-low text-error shadow-elevation-1 enabled:hover:shadow-elevation-2'\n : 'bg-surface-container-low text-primary shadow-elevation-1 enabled:hover:shadow-elevation-2'\n case 'outlined':\n return err\n ? 'border border-error text-error'\n : 'border border-outline text-primary'\n case 'text':\n return err\n ? 'text-error'\n : '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, shapeClass, sizeClasses, px, variantClasses]\"\n :style=\"customStyle\"\n @pointerdown=\"createRipple\"\n >\n <MSpinner v-if=\"loading\" :size=\"spinnerSize\" />\n <MIcon v-else-if=\"icon\" :name=\"icon\" :size=\"iconSize\" />\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 size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n shape?: 'rounded' | 'squared'\n to?: string | Record<string, any>\n }>(),\n {\n variant: 'filled',\n color: 'primary',\n type: 'button',\n disabled: false,\n loading: false,\n size: 'sm',\n shape: 'rounded',\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\nconst base =\n 'relative inline-flex items-center justify-center gap-2 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 shapeClass = computed(() => props.shape === 'squared' ? 'rounded-md' : 'rounded-full')\n\nconst sizeMap = {\n xs: { h: 'h-8', text: 'text-label-medium', icon: 16, spinner: 14, px: 'px-4', pxIcon: 'pl-3 pr-4', pxText: 'px-2' },\n sm: { h: 'h-10', text: 'text-label-large', icon: 20, spinner: 16, px: 'px-6', pxIcon: 'pl-4 pr-6', pxText: 'px-3' },\n md: { h: 'h-14', text: 'text-title-medium', icon: 20, spinner: 18, px: 'px-6', pxIcon: 'pl-5 pr-6', pxText: 'px-3' },\n lg: { h: 'h-16', text: 'text-title-large', icon: 22, spinner: 20, px: 'px-7', pxIcon: 'pl-6 pr-7', pxText: 'px-4' },\n xl: { h: 'h-20', text: 'text-headline-small', icon: 24, spinner: 22, px: 'px-8', pxIcon: 'pl-7 pr-8', pxText: 'px-4' },\n}\n\nconst s = computed(() => sizeMap[props.size] ?? sizeMap.sm)\nconst sizeClasses = computed(() => `${s.value.h} ${s.value.text}`)\nconst iconSize = computed(() => s.value.icon)\nconst spinnerSize = computed(() => s.value.spinner)\n\nconst px = computed(() => {\n if (props.variant === 'text') return s.value.pxText\n return (props.icon || props.loading) ? s.value.pxIcon : s.value.px\n})\n\nconst variantClasses = computed(() => {\n const err = isError.value\n switch (props.variant) {\n case 'filled':\n return err\n ? 'bg-error text-on-error enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n : 'bg-primary text-on-primary enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n case 'tonal':\n return err\n ? 'bg-error-container text-on-error-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n : 'bg-secondary-container text-on-secondary-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'\n case 'elevated':\n return err\n ? 'bg-surface-container-low text-error shadow-elevation-1 enabled:hover:shadow-elevation-2'\n : 'bg-surface-container-low text-primary shadow-elevation-1 enabled:hover:shadow-elevation-2'\n case 'outlined':\n return err\n ? 'border border-error text-error'\n : 'border border-outline text-primary'\n case 'text':\n return err\n ? 'text-error'\n : '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, shapeClass, sizeClasses, px, variantClasses]\"\n :style=\"customStyle\"\n @pointerdown=\"createRipple\"\n >\n <MSpinner v-if=\"loading\" :size=\"spinnerSize\" />\n <MIcon v-else-if=\"icon\" :name=\"icon\" :size=\"iconSize\" />\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { watch } from 'vue'\nimport MIconButton from './MIconButton.vue'\nimport { useLocale } from '../composables/useLocale'\n\nconst props = withDefaults(\n defineProps<{\n modelValue: boolean\n title?: string\n maxWidth?: string\n persistent?: boolean\n fullscreen?: boolean\n closeLabel?: string\n }>(),\n {\n maxWidth: 'max-w-md',\n persistent: false,\n fullscreen: false,\n },\n)\n\nconst locale = useLocale()\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 <!-- Basic dialog -->\n <Transition v-if=\"!fullscreen\" 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=\"closeLabel ?? locale.close\" @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\n <!-- Fullscreen dialog -->\n <Transition v-else name=\"m3-dialog-fs\">\n <div\n v-if=\"modelValue\"\n class=\"dialog-fs fixed inset-0 z-50 flex flex-col bg-surface\"\n >\n <div class=\"flex h-14 shrink-0 items-center gap-2 px-2\">\n <MIconButton v-if=\"!persistent\" icon=\"close\" :label=\"closeLabel ?? locale.close\" @click=\"close\" />\n <h2 class=\"flex-1 text-title-large font-medium text-on-surface\">\n <slot name=\"title\">{{ title }}</slot>\n </h2>\n <div v-if=\"$slots.actions\" class=\"flex items-center gap-2\">\n <slot name=\"actions\" />\n </div>\n </div>\n <div class=\"flex-1 overflow-y-auto px-6 py-4 text-body-medium text-on-surface-variant\">\n <slot />\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\n.m3-dialog-fs-enter-active,\n.m3-dialog-fs-leave-active {\n transition: transform 0.25s cubic-bezier(0.2, 0, 0, 1), opacity 0.15s ease;\n}\n.m3-dialog-fs-enter-from {\n transform: translateY(100%);\n opacity: 0;\n}\n.m3-dialog-fs-leave-to {\n transform: translateY(100%);\n opacity: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { watch } from 'vue'\nimport MIconButton from './MIconButton.vue'\nimport { useLocale } from '../composables/useLocale'\n\nconst props = withDefaults(\n defineProps<{\n modelValue: boolean\n title?: string\n maxWidth?: string\n persistent?: boolean\n fullscreen?: boolean\n closeLabel?: string\n }>(),\n {\n maxWidth: 'max-w-md',\n persistent: false,\n fullscreen: false,\n },\n)\n\nconst locale = useLocale()\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 <!-- Basic dialog -->\n <Transition v-if=\"!fullscreen\" 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=\"closeLabel ?? locale.close\" @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\n <!-- Fullscreen dialog -->\n <Transition v-else name=\"m3-dialog-fs\">\n <div\n v-if=\"modelValue\"\n class=\"dialog-fs fixed inset-0 z-50 flex flex-col bg-surface\"\n >\n <div class=\"flex h-14 shrink-0 items-center gap-2 px-2\">\n <MIconButton v-if=\"!persistent\" icon=\"close\" :label=\"closeLabel ?? locale.close\" @click=\"close\" />\n <h2 class=\"flex-1 text-title-large font-medium text-on-surface\">\n <slot name=\"title\">{{ title }}</slot>\n </h2>\n <div v-if=\"$slots.actions\" class=\"flex items-center gap-2\">\n <slot name=\"actions\" />\n </div>\n </div>\n <div class=\"flex-1 overflow-y-auto px-6 py-4 text-body-medium text-on-surface-variant\">\n <slot />\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\n.m3-dialog-fs-enter-active,\n.m3-dialog-fs-leave-active {\n transition: transform 0.25s cubic-bezier(0.2, 0, 0, 1), opacity 0.15s ease;\n}\n.m3-dialog-fs-enter-from {\n transform: translateY(100%);\n opacity: 0;\n}\n.m3-dialog-fs-leave-to {\n transform: translateY(100%);\n opacity: 0;\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\";\nimport { useDebounce } from \"../composables/useDebounce\";\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 clearable?: boolean;\n fieldBg?: string;\n debounce?: number;\n }>(),\n {\n type: \"text\",\n variant: \"filled\",\n rows: 3,\n clearable: false,\n debounce: 0,\n },\n);\n\nconst emit = defineEmits<{ \"update:modelValue\": [string]; debounced: [string] }>();\n\nconst id = useId();\nconst slots = useSlots();\n\nconst fieldBgEl = ref<HTMLElement | null>(null);\nconst { resolvedFieldBg } = useFieldBg(fieldBgEl, () => props.fieldBg);\n\nconst { debounced: emitDebounced, cancel: cancelDebounce } = useDebounce((v: string) => emit(\"debounced\", v), props.debounce)\n\nconst showClear = computed(() => props.clearable && String(props.modelValue).length > 0 && !props.disabled)\n\nconst inputClasses = computed(() => {\n const hasTrailing = !!slots.trailing || props.clearable;\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 unfloatedTop = props.variant === 'filled' ? 'top-[53%]' : 'top-1/2'\n const base = [\n \"pointer-events-none absolute truncate transition-all duration-200\",\n left,\n \"right-4\",\n `${unfloatedTop} -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 if (props.debounce > 0) emitDebounced(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 <div\n v-if=\"leadingIcon\"\n class=\"pointer-events-none absolute left-3.5 text-on-surface-variant\"\n :class=\"multiline ? 'top-[55%] -translate-y-1/2' : variant === 'filled' ? 'top-5' : 'top-4.5'\"\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 right-2 top-1/2 -translate-y-1/2\">\n <slot name=\"trailing\" />\n </div>\n <button\n v-else-if=\"showClear\"\n type=\"button\"\n class=\"absolute right-3 top-1/2 -translate-y-1/2 flex h-6 w-6 cursor-pointer items-center justify-center rounded-full text-on-surface-variant transition-colors hover:bg-on-surface/8 hover:text-on-surface\"\n @click=\"cancelDebounce(); emit('update:modelValue', '')\"\n >\n <MIcon name=\"close\" :size=\"18\" />\n </button>\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\";\nimport { useDebounce } from \"../composables/useDebounce\";\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 clearable?: boolean;\n fieldBg?: string;\n debounce?: number;\n }>(),\n {\n type: \"text\",\n variant: \"filled\",\n rows: 3,\n clearable: false,\n debounce: 0,\n },\n);\n\nconst emit = defineEmits<{ \"update:modelValue\": [string]; debounced: [string] }>();\n\nconst id = useId();\nconst slots = useSlots();\n\nconst fieldBgEl = ref<HTMLElement | null>(null);\nconst { resolvedFieldBg } = useFieldBg(fieldBgEl, () => props.fieldBg);\n\nconst { debounced: emitDebounced, cancel: cancelDebounce } = useDebounce((v: string) => emit(\"debounced\", v), props.debounce)\n\nconst showClear = computed(() => props.clearable && String(props.modelValue).length > 0 && !props.disabled)\n\nconst inputClasses = computed(() => {\n const hasTrailing = !!slots.trailing || props.clearable;\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 unfloatedTop = props.variant === 'filled' ? 'top-[53%]' : 'top-1/2'\n const base = [\n \"pointer-events-none absolute truncate transition-all duration-200\",\n left,\n \"right-4\",\n `${unfloatedTop} -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 if (props.debounce > 0) emitDebounced(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 <div\n v-if=\"leadingIcon\"\n class=\"pointer-events-none absolute left-3.5 text-on-surface-variant\"\n :class=\"multiline ? 'top-[55%] -translate-y-1/2' : variant === 'filled' ? 'top-5' : 'top-4.5'\"\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 right-2 top-1/2 -translate-y-1/2\">\n <slot name=\"trailing\" />\n </div>\n <button\n v-else-if=\"showClear\"\n type=\"button\"\n class=\"absolute right-3 top-1/2 -translate-y-1/2 flex h-6 w-6 cursor-pointer items-center justify-center rounded-full text-on-surface-variant transition-colors hover:bg-on-surface/8 hover:text-on-surface\"\n @click=\"cancelDebounce(); emit('update:modelValue', '')\"\n >\n <MIcon name=\"close\" :size=\"18\" />\n </button>\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, provide, 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\nprovide('m-menu-close', close)\ndefineExpose({ close, open })\n\nfunction onOutsideClick(e: MouseEvent) {\n const t = e.target as Node\n if (triggerEl.value?.contains(t)) return\n if (dropdownEl.value?.contains(t)) return\n if ((t as Element).closest?.('.m3-submenu')) return\n 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-hidden rounded-lg bg-surface-container shadow-elevation-2\"\n :style=\"{ ...dropStyle, transformOrigin: origin }\"\n >\n <div class=\"overflow-y-auto py-1\" :style=\"{ maxHeight: dropStyle.maxHeight }\">\n <slot :close=\"close\" />\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, provide, 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\nprovide('m-menu-close', close)\ndefineExpose({ close, open })\n\nfunction onOutsideClick(e: MouseEvent) {\n const t = e.target as Node\n if (triggerEl.value?.contains(t)) return\n if (dropdownEl.value?.contains(t)) return\n if ((t as Element).closest?.('.m3-submenu')) return\n 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-hidden rounded-lg bg-surface-container shadow-elevation-2\"\n :style=\"{ ...dropStyle, transformOrigin: origin }\"\n >\n <div class=\"overflow-y-auto py-1\" :style=\"{ maxHeight: dropStyle.maxHeight }\">\n <slot :close=\"close\" />\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, ref, useSlots } from 'vue'\nimport MIcon from './MIcon.vue'\n\nconst props = withDefaults(defineProps<{\n icon?: string\n to?: string | Record<string, any>\n disabled?: boolean\n danger?: boolean\n}>(), {\n disabled: false,\n danger: false,\n})\n\nconst emit = defineEmits<{ click: [] }>()\n\nconst slots = useSlots()\nconst tag = computed(() => props.to ? 'RouterLink' : 'button')\nconst hasChildren = computed(() => !!slots.children)\nconst menuClose = inject<(() => void) | null>('m-menu-close', null)\n\nfunction handleClick() {\n if (props.disabled || hasChildren.value) return\n emit('click')\n menuClose?.()\n}\nconst showSub = ref(false)\nconst itemEl = ref<HTMLElement>()\nconst subStyle = ref<Record<string, string>>({})\n\nfunction onMouseEnter() {\n if (!hasChildren.value || props.disabled) return\n showSub.value = true\n if (!itemEl.value) return\n const rect = itemEl.value.getBoundingClientRect()\n const right = rect.right + 200 > window.innerWidth\n subStyle.value = {\n position: 'fixed',\n top: `${rect.top}px`,\n ...(right\n ? { right: `${window.innerWidth - rect.left}px` }\n : { left: `${rect.right}px` }),\n zIndex: '501',\n }\n}\n\nfunction onMouseLeave(e: MouseEvent) {\n const related = e.relatedTarget as Element | null\n if (related?.closest('.m3-submenu')) return\n showSub.value = false\n}\n\nfunction onSubLeave(e: MouseEvent) {\n const related = e.relatedTarget as Element | null\n if (related?.closest('.m3-submenu') || itemEl.value?.contains(related as Node)) return\n showSub.value = false\n}\n</script>\n\n<template>\n <div\n ref=\"itemEl\"\n @mouseenter=\"onMouseEnter\"\n @mouseleave=\"onMouseLeave\"\n >\n <component\n :is=\"tag\"\n :to=\"to || undefined\"\n :type=\"to ? undefined : 'button'\"\n class=\"flex w-full items-center gap-3 px-4 py-2.5 text-left text-body-large transition-colors\"\n :class=\"[\n disabled ? 'cursor-not-allowed opacity-[0.38] text-on-surface' : 'cursor-pointer',\n !disabled && danger ? 'text-error hover:bg-error/8' : '',\n !disabled && !danger ? 'text-on-surface hover:bg-on-surface/8' : '',\n ]\"\n :disabled=\"disabled || undefined\"\n @click=\"handleClick\"\n >\n <MIcon v-if=\"icon\" :name=\"icon\" :size=\"20\" class=\"shrink-0\" :class=\"danger ? 'text-error' : 'text-on-surface-variant'\" />\n <span class=\"flex-1\"><slot /></span>\n <MIcon v-if=\"hasChildren\" name=\"chevron_right\" :size=\"18\" class=\"shrink-0 text-on-surface-variant\" />\n </component>\n\n <!-- Submenu -->\n <Teleport v-if=\"hasChildren\" to=\"body\">\n <Transition\n enter-active-class=\"transition-opacity duration-100\"\n enter-from-class=\"opacity-0\"\n leave-active-class=\"transition-opacity duration-75\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"showSub\"\n class=\"m3-submenu min-w-44 overflow-hidden rounded-lg bg-surface-container py-1 shadow-elevation-2\"\n :style=\"subStyle\"\n @mouseleave=\"onSubLeave\"\n >\n <slot name=\"children\" />\n </div>\n </Transition>\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, ref, useSlots } from 'vue'\nimport MIcon from './MIcon.vue'\n\nconst props = withDefaults(defineProps<{\n icon?: string\n to?: string | Record<string, any>\n disabled?: boolean\n danger?: boolean\n}>(), {\n disabled: false,\n danger: false,\n})\n\nconst emit = defineEmits<{ click: [] }>()\n\nconst slots = useSlots()\nconst tag = computed(() => props.to ? 'RouterLink' : 'button')\nconst hasChildren = computed(() => !!slots.children)\nconst menuClose = inject<(() => void) | null>('m-menu-close', null)\n\nfunction handleClick() {\n if (props.disabled || hasChildren.value) return\n emit('click')\n menuClose?.()\n}\nconst showSub = ref(false)\nconst itemEl = ref<HTMLElement>()\nconst subStyle = ref<Record<string, string>>({})\n\nfunction onMouseEnter() {\n if (!hasChildren.value || props.disabled) return\n showSub.value = true\n if (!itemEl.value) return\n const rect = itemEl.value.getBoundingClientRect()\n const right = rect.right + 200 > window.innerWidth\n subStyle.value = {\n position: 'fixed',\n top: `${rect.top}px`,\n ...(right\n ? { right: `${window.innerWidth - rect.left}px` }\n : { left: `${rect.right}px` }),\n zIndex: '501',\n }\n}\n\nfunction onMouseLeave(e: MouseEvent) {\n const related = e.relatedTarget as Element | null\n if (related?.closest('.m3-submenu')) return\n showSub.value = false\n}\n\nfunction onSubLeave(e: MouseEvent) {\n const related = e.relatedTarget as Element | null\n if (related?.closest('.m3-submenu') || itemEl.value?.contains(related as Node)) return\n showSub.value = false\n}\n</script>\n\n<template>\n <div\n ref=\"itemEl\"\n @mouseenter=\"onMouseEnter\"\n @mouseleave=\"onMouseLeave\"\n >\n <component\n :is=\"tag\"\n :to=\"to || undefined\"\n :type=\"to ? undefined : 'button'\"\n class=\"flex w-full items-center gap-3 px-4 py-2.5 text-left text-body-large transition-colors\"\n :class=\"[\n disabled ? 'cursor-not-allowed opacity-[0.38] text-on-surface' : 'cursor-pointer',\n !disabled && danger ? 'text-error hover:bg-error/8' : '',\n !disabled && !danger ? 'text-on-surface hover:bg-on-surface/8' : '',\n ]\"\n :disabled=\"disabled || undefined\"\n @click=\"handleClick\"\n >\n <MIcon v-if=\"icon\" :name=\"icon\" :size=\"20\" class=\"shrink-0\" :class=\"danger ? 'text-error' : 'text-on-surface-variant'\" />\n <span class=\"flex-1\"><slot /></span>\n <MIcon v-if=\"hasChildren\" name=\"chevron_right\" :size=\"18\" class=\"shrink-0 text-on-surface-variant\" />\n </component>\n\n <!-- Submenu -->\n <Teleport v-if=\"hasChildren\" to=\"body\">\n <Transition\n enter-active-class=\"transition-opacity duration-100\"\n enter-from-class=\"opacity-0\"\n leave-active-class=\"transition-opacity duration-75\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"showSub\"\n class=\"m3-submenu min-w-44 overflow-hidden rounded-lg bg-surface-container py-1 shadow-elevation-2\"\n :style=\"subStyle\"\n @mouseleave=\"onSubLeave\"\n >\n <slot name=\"children\" />\n </div>\n </Transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":";;;;AA8FA,IAAa,IAA0B;CACrC,QAAQ;CACR,WAAW;CACX,OAAO;CACP,QAAQ;CACR,SAAS;CACT,SAAS;CAET,UAAU;CACV,MAAM;CACN,OAAO;CACP,MAAM;CAEN,eAAe;CACf,aAAa;CACb,QAAQ;CACR,SAAS;CACT,WAAW;CACX,SAAS;CAET,QAAQ;CAER,UAAU;CACV,YAAY;CACZ,eAAe;CACf,QAAQ;CAER,YAAY;CACZ,YAAY;CACZ,aAAa;CACb,WAAW;CACX,SAAS;CACT,eAAe;CACf,WAAW;CAEX,SAAS;CACT,UAAU;CAEV,WAAW;CACX,UAAU;CACV,SAAS;CACT,cAAc;CACd,WAAW;CACX,UAAU;CACV,aAAa;CAEb,eAAe;CACf,cAAc;CACd,YAAY;CACZ,UAAU;CACV,WAAW;CAEX,aAAa;CACb,aAAa;CAEb,MAAM;CACN,QAAQ;CACR,WAAW;CACX,eAAe;CACf,WAAW;CACX,YAAY;CACZ,aAAa;CACb,YAAY;CACZ,MAAM;CACN,WAAW;CACX,aAAa;CACb,YAAY;CACZ,MAAM;CACN,MAAM;CACN,MAAM;CACN,OAAO;CACP,WAAW;CACX,UAAU;CACV,UAAU;CACV,UAAU;CACV,YAAY;CACZ,aAAa;CACb,eAAe;CACf,QAAQ;AACV,GAEa,IAA2D,OAAO,WAAW;AAE1F,SAAgB,IAAsB;CACpC,IAAM,IAAW,EAAO,GAAe,CAAC,CAAC,GACnC,IAAS,EAAS,EAAE,GAAG,EAAc,CAAC;CAM5C,OAJA,QAAkB;EAChB,OAAO,OAAO,GAAQ,GAAe,EAAQ,CAAQ,CAAC;CACxD,CAAC,GAEM;AACT;;;;;;;;;;kCC3KM,IAAS,GACT,IAAQ;;;;;;;;;;;EAZd,IAAM,IAAQ,GASR,IAAS,EAAU,GAOnB,IAAI,SAAgB,EAAM,OAAO,IAAI,IAAI,IAAS,KAAK,IAAI,GAC3D,IAAK,QAAe,EAAM,OAAO,CAAC,GAGlC,IAAW,QAAe;GAC9B,IAAM,IAAK,EAAG,OACR,IAAI,EAAE,OACN,IAAM,IAAI,KACV,IAAO,IAAQ,IAEf,IAAgB,CAAC,GACnB,IAAM,GACN,IAAK,GACP,IAAK;GAEP,KAAK,IAAI,IAAI,GAAG,KAAK,GAAM,KAAK;IAC9B,IAAM,IAAS,IAAI,KAAK,KAAK,IAAK,IAAO,KAAK,KAAK,GAC7C,IAAK,IAAI,IAAM,KAAK,IAAI,IAAQ,CAAK,GACrC,IAAI,IAAK,IAAK,KAAK,IAAI,CAAK,GAC5B,IAAI,IAAK,IAAK,KAAK,IAAI,CAAK;IAIlC,AAHI,IAAI,MAAG,KAAO,KAAK,MAAM,IAAI,MAAO,KAAK,IAAI,MAAO,CAAC,IACzD,EAAI,KAAK,GAAG,MAAM,IAAI,MAAM,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,GAChE,IAAK,GACL,IAAK;GACP;GAGA,IAAM,IAAU,IAAM,KAChB,IAAM,IAAM,GACZ,IAAO,GAAG,EAAQ,QAAQ,CAAC,EAAE,GAAG,EAAI,QAAQ,CAAC;GAInD,OAAO;IAAE,MAAM,EAAI,KAAK,EAAE,IAAI;IAAK;IAAM,KAAK,EAAI,QAAQ,CAAC;GAAE;EAC/D,CAAC;yBAIC,EAiCO,QAAA;GAhCL,OAAM;GACL,OAAK,EAAA;IAAA,OAAA,GAAc,EAAA,KAAI;IAAA,QAAA,GAAiB,EAAA,KAAI;GAAA,CAAA;GAC7C,MAAK;GACJ,cAAY,EAAA,SAAS,EAAA,CAAA,EAAO;MAIpB,EAAA,QAEP,EAAA,GAIF,EAkBM,OAAA;;GAhBH,OAAO,EAAA;GACP,QAAQ,EAAA;GACR,SAAO,OAAS,EAAA,KAAI,GAAI,EAAA;GACzB,MAAK;GACL,OAAM;GACL,OAAK,EAAA,qBAAuB,EAAA,MAAE,KAAM,EAAA,MAAE,GAAA;MAEvC,EAQE,QAAA;GAPC,GAAG,EAAA,MAAS;GACb,QAAO;GACN,gBAAc;GACf,kBAAe;GACd,oBAAkB,EAAA,MAAS;GAC5B,OAAM;GACL,OAAK,EAAA,EAAA,iBAAqB,EAAA,MAAS,IAAG,CAAA;+BAtBlC,EAAA,GADT,EAGE,QAHF,EAGE;;IElEA,IAAgB;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAS,EAAY,GAAgC;CACnD,KAAK,IAAM,KAAO,GAChB,IAAI,EAAG,UAAU,SAAS,CAAG,GAAG,OAAO,eAAe,EAAI,MAAM,CAAC,EAAE;CAErE,OAAO;AACT;AAEA,SAAS,EAAc,GAAwB;CAC7C,IAAI,CAAC,KAAS,MAAU,eAAe,OAAO;CAC9C,IAAM,IAAI,EAAM,MAAM,oBAAoB;CAC1C,IAAI,GAAG;EACL,IAAM,IAAQ,EAAE,GAAI,MAAM,GAAG,EAAE,KAAK,MAAM,EAAE,KAAK,CAAC;EAClD,IAAI,EAAM,WAAW,KAAK,WAAW,EAAM,EAAG,MAAM,GAAG,OAAO;CAChE;CACA,OAAO;AACT;AAWA,SAAgB,EACd,GACA,GACA;CACA,IAAM,IAAa,EAAY,sBAAsB;CAErD,SAAS,EAAa,GAAe;EAEnC,AADA,EAAW,QAAQ,GACnB,EAAY,OAAO,MAAM,YAAY,cAAc,EAAY,KAAK,CAAK;CAC3E;CAEA,SAAS,IAAY;EACnB,IAAI,IAAyB,EAAY,OAAO,iBAAiB;EACjE,OAAO,IAAI;GACT,IAAM,IAAS,EAAY,CAAE;GAC7B,IAAI,GAAQ;IAAE,EAAa,CAAM;IAAG;GAAO;GAC3C,IAAI,MAAO,SAAS,MAAM;IAAE,EAAa,sBAAsB;IAAG;GAAO;GACzE,IAAM,IAAK,iBAAiB,CAAE,EAAE;GAChC,IAAI,CAAC,EAAc,CAAE,GAAG;IAAE,EAAa,CAAE;IAAG;GAAO;GACnD,IAAK,EAAG;EACV;EACA,EAAa,sBAAsB;CACrC;CAEA,IAAI,IAAoC;CAexC,OAbA,QAAgB;EAGd,AAFA,EAAU,GACV,IAAW,IAAI,uBAAuB,EAAU,CAAC,GACjD,EAAS,QAAQ,SAAS,iBAAiB;GACzC,YAAY;GACZ,iBAAiB;IAAC;IAAS;IAAS;GAAY;EAClD,CAAC;CACH,CAAC,GAED,QAAsB,GAAU,WAAW,CAAC,GAIrC,EAAE,iBAFe,QAAe,EAAY,KAAK,EAAW,KAE1D,EAAgB;AAC3B;;;ACxFA,SAAgB,EAAY,GAA8B,GAAY;CACpE,IAAI,IAA8C;CAElD,SAAS,EAAU,GAAG,GAAa;EAEjC,AADI,KAAO,aAAa,CAAK,GAC7B,IAAQ,iBAAiB;GAEvB,AADA,IAAQ,MACR,EAAG,GAAG,CAAI;EACZ,GAAG,CAAE;CACP;CAEA,SAAS,IAAS;EAChB,AAEE,OADA,aAAa,CAAK,GACV;CAEZ;CAIA,OAFA,EAAgB,CAAM,GAEf;EAAE;EAAW;CAAO;AAC7B;;;ACcA,IAAM,IACJ;;;;;;;;;;;;;;;EAlCF,IAAM,IAAQ,GAkBR,IAAM,QAAe,EAAM,KAAK,eAAe,QAAQ,GAEvD,IAAU;GACd,IAAI;IAAE,IAAI;IAAI,MAAM;GAAG;GACvB,IAAI;IAAE,IAAI;IAAI,MAAM;GAAG;GACvB,IAAI;IAAE,IAAI;IAAI,MAAM;GAAG;GACvB,IAAI;IAAE,IAAI;IAAI,MAAM;GAAG;GACvB,IAAI;IAAE,IAAI;IAAI,MAAM;GAAG;EACzB,GAEM,IAAW,QACX,OAAO,EAAM,QAAS,WAAiB;GAAE,IAAI,EAAM;GAAM,MAAM,KAAK,MAAM,EAAM,OAAO,GAAI;EAAE,IAC1F,EAAQ,EAAM,SAAS,EAAQ,EACvC,GAMK,IAAa,QAAe,EAAM,UAAU,YAAY,eAAe,cAAc;EAE3F,SAAS,EAAa,GAAqB;GACzC,IAAI,EAAM,UAAU;GACpB,IAAM,IAAS,EAAM,eACf,IAAO,EAAO,sBAAsB,GACpC,IAAI,KAAK,IAAI,EAAK,OAAO,EAAK,MAAM,IAAI,GACxC,IAAK,SAAS,cAAc,MAAM;GAIxC,AAHA,EAAG,YAAY,aACf,EAAG,MAAM,UAAU,SAAS,EAAE,YAAY,EAAE,SAAS,EAAM,UAAU,EAAK,MAAM,IAAI,EAAE,UAAU,EAAM,UAAU,EAAK,OAAO,IAAI,EAAE,KAClI,EAAO,YAAY,CAAE,GACrB,EAAG,iBAAiB,sBAAsB,EAAG,OAAO,GAAG,EAAE,MAAM,GAAK,CAAC;EACvE;EAEA,IAAM,IAAiB,QAAe;GACpC,QAAQ,EAAM,SAAd;IACE,KAAK,UACH,OAAO;IACT,KAAK,SACH,OAAO;IACT,KAAK,YACH,OAAO;IACT,SACE,OAAO;GACX;EACF,CAAC;yBAIC,EAWY,EAVL,EAAA,KAAG,GAAA;GACP,IAAI,EAAA,MAAM,KAAA;GACV,MAAM,EAAA,KAAK,KAAA,IAAS;GACpB,cAAY,EAAA,SAAS,KAAA;GACrB,UAAU,EAAA;GACV,OAAK,EAAA;IAAG;IAAM,EAAA;IAAY,EAAA;IAAc;GAAA,CAAA;GACxC,OAAK,EAAA;IAAA,OAAA,GAAc,EAAA,MAAS,GAAE;IAAA,QAAA,GAAiB,EAAA,MAAS,GAAE;GAAA,CAAA;GAC1D,eAAa;;oBAE8B,CAA5C,EAA4C,GAAA;IAApC,MAAM,EAAA;IAAO,MAAM,EAAA,MAAS;;;;;;;;;;;;IE1BlC,IACJ;;;;;;;;;;;;;;;;;;;;EAlDF,IAAM,IAAe,CAAC,WAAW,OAAO,GAGlC,IAAQ,GA4BR,IAAM,QAAe,EAAM,KAAK,eAAe,QAAQ,GAEvD,IAAgB,QACd,CAAC,CAAC,EAAM,SAAS,CAAE,EAAmC,SAAS,EAAM,KAAK,CAClF,GAEM,IAAc,QAAe;GAC5B,MAAc,OACnB,OAAO;IACL,mBAAmB,EAAM;IACzB,sBAAsB;IACtB,6BAA6B,EAAM,QAAQ;IAC3C,gCAAgC,EAAM;GACxC;EACF,CAAC,GAEK,IAAU,QAAe,EAAM,UAAU,OAAO,GAUhD,IAAa,QAAe,EAAM,UAAU,YAAY,eAAe,cAAc,GAErF,IAAU;GACd,IAAI;IAAE,GAAG;IAAO,MAAM;IAAqB,MAAM;IAAI,SAAS;IAAI,IAAI;IAAQ,QAAQ;IAAa,QAAQ;GAAO;GAClH,IAAI;IAAE,GAAG;IAAQ,MAAM;IAAoB,MAAM;IAAI,SAAS;IAAI,IAAI;IAAQ,QAAQ;IAAa,QAAQ;GAAO;GAClH,IAAI;IAAE,GAAG;IAAQ,MAAM;IAAqB,MAAM;IAAI,SAAS;IAAI,IAAI;IAAQ,QAAQ;IAAa,QAAQ;GAAO;GACnH,IAAI;IAAE,GAAG;IAAQ,MAAM;IAAoB,MAAM;IAAI,SAAS;IAAI,IAAI;IAAQ,QAAQ;IAAa,QAAQ;GAAO;GAClH,IAAI;IAAE,GAAG;IAAQ,MAAM;IAAuB,MAAM;IAAI,SAAS;IAAI,IAAI;IAAQ,QAAQ;IAAa,QAAQ;GAAO;EACvH,GAEM,IAAI,QAAe,EAAQ,EAAM,SAAS,EAAQ,EAAE,GACpD,IAAc,QAAe,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,MAAM,GAC3D,IAAW,QAAe,EAAE,MAAM,IAAI,GACtC,IAAc,QAAe,EAAE,MAAM,OAAO,GAE5C,IAAK,QACL,EAAM,YAAY,SAAe,EAAE,MAAM,SACrC,EAAM,QAAQ,EAAM,UAAW,EAAE,MAAM,SAAS,EAAE,MAAM,EACjE,GAEK,IAAiB,QAAe;GACpC,IAAM,IAAM,EAAQ;GACpB,QAAQ,EAAM,SAAd;IACE,KAAK,UACH,OAAO,IACH,uFACA;IACN,KAAK,SACH,OAAO,IACH,2GACA;IACN,KAAK,YACH,OAAO,IACH,4FACA;IACN,KAAK,YACH,OAAO,IACH,mCACA;IACN,KAAK,QACH,OAAO,IACH,eACA;IACN,SACE,OAAO;GACX;EACF,CAAC;EAED,SAAS,EAAa,GAAqB;GACzC,IAAI,EAAM,YAAY,EAAM,SAAS;GACrC,IAAM,IAAS,EAAM,eACf,IAAO,EAAO,sBAAsB,GACpC,IAAI,KAAK,IAAI,EAAK,OAAO,EAAK,MAAM,IAAI,GACxC,IAAK,SAAS,cAAc,MAAM;GAIxC,AAHA,EAAG,YAAY,aACf,EAAG,MAAM,UAAU,SAAS,EAAE,YAAY,EAAE,SAAS,EAAM,UAAU,EAAK,MAAM,IAAI,EAAE,UAAU,EAAM,UAAU,EAAK,OAAO,IAAI,EAAE,KAClI,EAAO,YAAY,CAAE,GACrB,EAAG,iBAAiB,sBAAsB,EAAG,OAAO,GAAG,EAAE,MAAM,GAAK,CAAC;EACvE;yBAIE,EAYY,EAXL,EAAA,KAAG,GAAA;GACP,IAAI,EAAA,MAAM,KAAA;GACV,MAAM,EAAA,KAAK,KAAA,IAAY,EAAA;GACvB,UAAU,EAAA,YAAY,EAAA;GACtB,OAAK,EAAA;IAAG;IAAM,EAAA;IAAY,EAAA;IAAa,EAAA;IAAI,EAAA;GAAc,CAAA;GACzD,OAAK,EAAE,EAAA,KAAW;GAClB,eAAa;;oBAEiC,CAA/B,EAAA,WAAA,EAAA,GAAhB,EAA+C,GAAA;;IAArB,MAAM,EAAA;4BACd,EAAA,QAAA,EAAA,GAAlB,EAAwD,GAAA;;IAA/B,MAAM,EAAA;IAAO,MAAM,EAAA;+CAC5C,EAAQ,EAAA,QAAA,SAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EElIZ,IAAM,IAAQ,GAgBR,IAAS,EAAU,GAEnB,IAAO;EAEb,SAAS,IAAQ;GACX,EAAM,cACV,EAAK,qBAAqB,EAAK;EACjC;EAEA,SAAS,EAAU,GAAsB;GACvC,AAAI,EAAM,QAAQ,YAAU,EAAM;EACpC;SAEA,QACQ,EAAM,aACX,MAAS;GACR,AAAI,KACF,SAAS,iBAAiB,WAAW,CAAS,GAC9C,SAAS,KAAK,MAAM,WAAW,aAE/B,SAAS,oBAAoB,WAAW,CAAS,GACjD,SAAS,KAAK,MAAM,WAAW;EAEnC,CACF,mBAIE,EAgDW,GAAA,EAhDD,IAAG,OAAM,GAAA,CAEE,EAAA,mBA2BnB,EAkBa,GAAA;;GAlBM,MAAK;;oBAiBhB,CAfE,EAAA,cAAA,EAAA,GADR,EAgBM,OAhBN,IAgBM,CAZJ,EAQM,OARN,IAQM;IAPgB,EAAA,0BAAA,EAAA,GAApB,EAAkG,GAAA;;KAAlE,MAAK;KAAS,OAAO,EAAA,cAAc,EAAA,CAAA,EAAO;KAAQ,SAAO;;IACzF,EAEK,MAFL,IAEK,CADH,EAAqC,EAAA,QAAA,SAAA,CAAA,SAAA,CAAA,EAAA,EAAf,EAAA,KAAK,GAAA,CAAA,CAAA,GAAA,EAAA,CAAA,CAAA;IAElBA,EAAAA,OAAO,WAAA,EAAA,GAAlB,EAEM,OAFN,IAEM,CADJ,EAAuB,EAAA,QAAA,WAAA,CAAA,GAAA,KAAA,GAAA,EAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;OAG3B,EAEM,OAFN,IAEM,CADJ,EAAQ,EAAA,QAAA,WAAA,CAAA,GAAA,KAAA,GAAA,EAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA;;SA1CK,EAAA,GAAnB,EAwBa,GAAA;;GAxBkB,MAAK;;oBAuB5B,CArBE,EAAA,cAAA,EAAA,GADR,EAsBM,OAAA;;IApBJ,OAAM;IACL,SAAK,EAAO,GAAK,CAAA,MAAA,CAAA;OAElB,EAgBM,OAAA,EAfJ,OAAK,EAAA,CAAC,wGACE,EAAA,QAAQ,CAAA,EAAA,GAAA;IAEhB,EAKM,OALN,GAKM,CAJJ,EAEK,MAFL,IAEK,CADH,EAAqC,EAAA,QAAA,SAAA,CAAA,SAAA,CAAA,EAAA,EAAf,EAAA,KAAK,GAAA,CAAA,CAAA,GAAA,EAAA,CAAA,CAAA,GAET,EAAA,0BAAA,EAAA,GAApB,EAAkG,GAAA;;KAAlE,MAAK;KAAS,OAAO,EAAA,cAAc,EAAA,CAAA,EAAO;KAAQ,SAAO;;IAE3F,EAEM,OAFN,IAEM,CADJ,EAAQ,EAAA,QAAA,WAAA,CAAA,GAAA,KAAA,GAAA,EAAA,CAAA,CAAA;IAECA,EAAAA,OAAO,WAAA,EAAA,GAAlB,EAEM,OAFN,IAEM,CADJ,EAAuB,EAAA,QAAA,WAAA,CAAA,GAAA,KAAA,GAAA,EAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEjEnC,IAAM,IAAQ,GA2BR,IAAO,GAEP,IAAK,EAAM,GACX,IAAQ,EAAS,GAEjB,IAAY,EAAwB,IAAI,GACxC,EAAE,uBAAoB,EAAW,SAAiB,EAAM,OAAO,GAE/D,EAAE,WAAW,GAAe,QAAQ,MAAmB,GAAa,MAAc,EAAK,aAAa,CAAC,GAAG,EAAM,QAAQ,GAEtH,IAAY,QAAe,EAAM,aAAa,OAAO,EAAM,UAAU,EAAE,SAAS,KAAK,CAAC,EAAM,QAAQ,GAEpG,IAAe,QAAe;GAClC,IAAM,IAAc,CAAC,CAAC,EAAM,YAAY,EAAM,WACxC,IAAK,EAAM,cAAc,UAAU,QACnC,IAAK,IAAc,UAAU,QAE7B,IAAO;IACX;IACA;IACA;IAJW,EAAM,YAAY,0BAA0B;IAMvD;IACA;GACF;GAYA,OAVI,EAAM,YAAY,aACb;IACL,GAAG;IACH;IACA,EAAM,QACF,mDACA;GACN,EAAE,KAAK,GAAG,IAGL;IACL,GAAG;IACH;IACA,EAAM,QACF,qDACA;GACN,EAAE,KAAK,GAAG;EACZ,CAAC,GAEK,IAAe,QAAe;GAUlC,IAAM,IAAO;IACX;IAVW,EAAM,cACf,EAAM,YAAY,aAChB,YACA,YACF,EAAM,YAAY,aAChB,WACA;IAMJ;IACA,GALmB,EAAM,YAAY,WAAW,cAAc,UAK9C;GAClB;GAkBA,OAhBI,EAAM,YAAY,aAIb;IACL,GAAG;IACH;IACA;IACA;IACA,EAAM,QACF,qCACA;GACN,EAAE,KAAK,GAAG,IAIL;IACL,GAAG;IACH;IACA;IACA,EAAM,QACF,qCACA;GACN,EAAE,KAAK,GAAG;EACZ,CAAC;EAED,SAAS,EAAQ,GAAc;GAC7B,IAAM,IAAS,EAAM;GAErB,AADA,EAAK,qBAAqB,EAAO,KAAK,GAClC,EAAM,WAAW,KAAG,EAAc,EAAO,KAAK;EACpD;yBAIE,EA+DM,OA/DN,IA+DM,CAzDJ,EAqDM,OAAA;YApDA;GAAJ,KAAI;GACJ,OAAK,EAAA,CAAC,YACE,EAAA,YAAO,aAAA,SAAA,EAAA,CAAA;GACd,OAAK,EAAE,EAAA,YAAO,aAAA,EAAA,cAAkC,EAAA,CAAA,EAAe,IAAK,KAAA,CAAS;;GAGtE,EAAA,eAAA,EAAA,GADR,EAMM,OAAA;;IAJJ,OAAK,EAAA,CAAC,iEACE,EAAA,YAAS,+BAAkC,EAAA,YAAO,WAAA,UAAA,SAAA,CAAA;OAE1D,EAAwC,GAAA;IAAhC,MAAM,EAAA;IAAc,MAAM;;GAI5B,EAAA,aAAA,EAAA,GADR,EAUE,YAAA;;IARC,IAAI,EAAA,CAAA;IACJ,OAAO,OAAO,EAAA,UAAU;IACxB,MAAM,EAAA;IACN,UAAU,EAAA;IACV,UAAU,EAAA;IACX,aAAY;IACX,OAAK,EAAE,EAAA,KAAY;IACZ;6BAEV,EAWE,SAAA;;IATC,IAAI,EAAA,CAAA;IACJ,MAAM,EAAA;IACN,OAAO,EAAA;IACP,UAAU,EAAA;IACV,UAAU,EAAA;IACV,cAAc,EAAA;IACf,aAAY;IACX,OAAK,EAAE,EAAA,KAAY;IACZ;;GAGV,EAEQ,SAAA;IAFA,KAAK,EAAA,CAAA;IAAK,OAAK,EAAE,EAAA,KAAY;WAChC,EAAA,KAAK,GAAA,CAAA,GAAe,EAAA,YAAA,EAAA,GAAZ,EAAuD,QAAvD,IAAyC,OAAO,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,IAAA,EAAA;GAGlDC,EAAAA,OAAO,YAAA,EAAA,GAAlB,EAEM,OAFN,IAEM,CADJ,EAAwB,EAAA,QAAA,UAAA,CAAA,CAAA,KAGb,EAAA,SAAA,EAAA,GADb,EAOS,UAAA;;IALP,MAAK;IACL,OAAM;IACL,SAAK,AAAA,EAAA,QAAA,MAAA;KAAoB,AAAlB,EAAA,CAAA,EAAc,GAAI,EAAI,qBAAA,EAAA;IAAA;OAE9B,EAAiC,GAAA;IAA1B,MAAK;IAAS,MAAM;;SAItB,EAAA,SAAA,EAAA,GAAT,EAAuE,KAAvE,IAAuE,EAAZ,EAAA,KAAK,GAAA,CAAA,KAClD,EAAA,QAAA,EAAA,GAAd,EAAuF,KAAvF,GAAuF,EAAX,EAAA,IAAI,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA;;;;;;EE5LpF,IAAM,IAAQ,GAQR,IAAO,EAAI,EAAK,GAChB,IAAY,EAAwB,IAAI,GACxC,IAAa,EAAwB,IAAI,GACzC,IAAY,EAA4B,CAAC,CAAC;EAEhD,SAAS,IAAa;GACpB,IAAI,CAAC,EAAU,OAAO;GACtB,IAAM,IAAO,EAAU,MAAM,sBAAsB,GAC7C,IAAa,OAAO,cAAc,EAAK,SAAS,GAChD,IAAY,IAAa,OAAO,EAAK,MAAM,GAE3C,IAAgC,EACpC,WAAW,GAAG,KAAK,IAAI,IAAY,EAAK,MAAM,KAAK,GAAY,GAAG,EAAE,IACtE;GAcA,AAZI,IACF,EAAM,SAAS,GAAG,OAAO,cAAc,EAAK,MAAM,EAAE,MAEpD,EAAM,MAAM,GAAG,EAAK,SAAS,EAAE,KAG7B,EAAM,UAAU,UAClB,EAAM,QAAQ,GAAG,OAAO,aAAa,EAAK,MAAM,MAEhD,EAAM,OAAO,GAAG,EAAK,KAAK,KAG5B,EAAU,QAAQ;EACpB;EAEA,SAAS,IAAS;GAEhB,AADK,EAAK,SAAO,EAAW,GAC5B,EAAK,QAAQ,CAAC,EAAK;EACrB;EAEA,SAAS,IAAQ;GACf,EAAK,QAAQ;EACf;EAGA,AADA,EAAQ,gBAAgB,CAAK,GAC7B,EAAa;GAAE;GAAO;EAAK,CAAC;EAE5B,SAAS,EAAe,GAAe;GACrC,IAAM,IAAI,EAAE;GACR,EAAU,OAAO,SAAS,CAAC,KAC3B,EAAW,OAAO,SAAS,CAAC,KAC3B,EAAc,UAAU,aAAa,KAC1C,EAAM;EACR;EAEA,SAAS,EAAS,GAAU;GAG1B,IAFI,CAAC,EAAK,SACN,EAAW,OAAO,SAAS,EAAE,MAAc,KAC3C,CAAC,EAAU,OAAO;GACtB,IAAM,IAAO,EAAU,MAAM,sBAAsB;GACnD,IAAI,EAAK,SAAS,KAAK,EAAK,MAAM,OAAO,aAAa;IAAE,EAAM;IAAG;GAAO;GACxE,EAAW;EACb;EAEA,SAAS,EAAU,GAAkB;GACnC,AAAI,EAAE,QAAQ,YAAU,EAAM;EAChC;EAQA,AANA,QAAgB;GAGd,AAFA,SAAS,iBAAiB,aAAa,CAAc,GACrD,SAAS,iBAAiB,WAAW,CAAS,GAC9C,OAAO,iBAAiB,UAAU,GAAU,EAAI;EAClD,CAAC,GAED,QAAkB;GAGhB,AAFA,SAAS,oBAAoB,aAAa,CAAc,GACxD,SAAS,oBAAoB,WAAW,CAAS,GACjD,OAAO,oBAAoB,UAAU,GAAU,EAAI;EACrD,CAAC;EAED,IAAM,IAAS,QACb,EAAM,UAAU,UAAU,cAAc,UAC1C;qCAIE,EAEM,OAAA;YAFG;GAAJ,KAAI;GAAY,OAAM;GAAgB,SAAO;MAChD,EAAoC,EAAA,QAAA,WAAA,EAAd,MAAM,EAAA,MAAI,CAAA,CAAA,GAAA,GAAA,IAAA,EAAA,GAGlC,EAoBW,GAAA,EApBD,IAAG,OAAM,GAAA,CACjB,EAkBa,GAAA;GAjBX,sBAAmB;GACnB,oBAAiB;GACjB,kBAAe;GACf,sBAAmB;GACnB,oBAAiB;GACjB,kBAAe;;oBAWT,CARE,EAAA,SAAA,EAAA,GADR,EASM,OAAA;;aAPA;IAAJ,KAAI;IACJ,OAAM;IACL,OAAK,EAAA;KAAA,GAAO,EAAA;KAAS,iBAAmB,EAAA;IAAM,CAAA;OAE/C,EAEM,OAAA;IAFD,OAAM;IAAwB,OAAK,EAAA,EAAA,WAAe,EAAA,MAAU,UAAS,CAAA;OACxE,EAAuB,EAAA,QAAA,WAAA,EAAT,SAAK,CAAA,CAAA,GAAA,CAAA,CAAA,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;EE5G7B,IAAM,IAAQ,GAUR,IAAO,GAEP,IAAQ,EAAS,GACjB,IAAM,QAAe,EAAM,KAAK,eAAe,QAAQ,GACvD,IAAc,QAAe,CAAC,CAAC,EAAM,QAAQ,GAC7C,IAAY,EAA4B,gBAAgB,IAAI;EAElE,SAAS,IAAc;GACjB,EAAM,YAAY,EAAY,UAClC,EAAK,OAAO,GACZ,IAAY;EACd;EACA,IAAM,IAAU,EAAI,EAAK,GACnB,IAAS,EAAiB,GAC1B,IAAW,EAA4B,CAAC,CAAC;EAE/C,SAAS,IAAe;GAGtB,IAFI,CAAC,EAAY,SAAS,EAAM,aAChC,EAAQ,QAAQ,IACZ,CAAC,EAAO,QAAO;GACnB,IAAM,IAAO,EAAO,MAAM,sBAAsB,GAC1C,IAAQ,EAAK,QAAQ,MAAM,OAAO;GACxC,EAAS,QAAQ;IACf,UAAU;IACV,KAAK,GAAG,EAAK,IAAI;IACjB,GAAI,IACA,EAAE,OAAO,GAAG,OAAO,aAAa,EAAK,KAAK,IAAI,IAC9C,EAAE,MAAM,GAAG,EAAK,MAAM,IAAI;IAC9B,QAAQ;GACV;EACF;EAEA,SAAS,EAAa,GAAe;GACnB,EAAE,eACL,QAAQ,aAAa,MAClC,EAAQ,QAAQ;EAClB;EAEA,SAAS,EAAW,GAAe;GACjC,IAAM,IAAU,EAAE;GACd,GAAS,QAAQ,aAAa,KAAK,EAAO,OAAO,SAAS,CAAe,MAC7E,EAAQ,QAAQ;EAClB;yBAIE,EAyCM,OAAA;YAxCA;GAAJ,KAAI;GACH,cAAY;GACZ,cAAY;YAEb,EAgBY,EAfL,EAAA,KAAG,GAAA;GACP,IAAI,EAAA,MAAM,KAAA;GACV,MAAM,EAAA,KAAK,KAAA,IAAS;GACrB,OAAK,EAAA,CAAC,0FAAwF;IAC5E,EAAA,WAAQ,sDAAA;KAAoF,EAAA,YAAY,EAAA,SAAM,gCAAA;KAAgD,EAAA,YAAQ,CAAK,EAAA,SAAM,0CAAA;;GAKlM,UAAU,EAAA,YAAY,KAAA;GACtB,SAAO;;oBAEiH;IAA5G,EAAA,QAAA,EAAA,GAAb,EAAyH,GAAA;;KAArG,MAAM,EAAA;KAAO,MAAM;KAAI,OAAK,EAAA,CAAC,YAAmB,EAAA,SAAM,eAAA,yBAAA,CAAA;;IAC1E,EAAoC,QAApC,IAAoC,CAAf,EAAQ,EAAA,QAAA,SAAA,CAAA,CAAA;IAChB,EAAA,SAAA,EAAA,GAAb,EAAqG,GAAA;;KAA3E,MAAK;KAAiB,MAAM;KAAI,OAAM;;;;;;;;;OAIlD,EAAA,SAAA,EAAA,GAAhB,EAgBW,GAAA;;GAhBkB,IAAG;MAC9B,EAca,GAAA;GAbX,sBAAmB;GACnB,oBAAiB;GACjB,sBAAmB;GACnB,kBAAe;;oBAST,CANE,EAAA,SAAA,EAAA,GADR,EAOM,OAAA;;IALJ,OAAM;IACL,OAAK,EAAE,EAAA,KAAQ;IACf,cAAY;OAEb,EAAwB,EAAA,QAAA,UAAA,CAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA"}
|
|
@@ -14,11 +14,14 @@ type __VLS_Props = {
|
|
|
14
14
|
clearable?: boolean;
|
|
15
15
|
fieldBg?: string;
|
|
16
16
|
noResultsText?: string;
|
|
17
|
+
debounce?: number;
|
|
17
18
|
};
|
|
18
19
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
19
20
|
"update:modelValue": (args_0: unknown) => any;
|
|
21
|
+
debounced: (args_0: string) => any;
|
|
20
22
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
21
23
|
"onUpdate:modelValue"?: ((args_0: unknown) => any) | undefined;
|
|
24
|
+
onDebounced?: ((args_0: string) => any) | undefined;
|
|
22
25
|
}>, {
|
|
23
26
|
required: boolean;
|
|
24
27
|
modelValue: undefined;
|
|
@@ -26,6 +29,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
26
29
|
mode: "docked" | "modal";
|
|
27
30
|
disabled: boolean;
|
|
28
31
|
clearable: boolean;
|
|
32
|
+
debounce: number;
|
|
29
33
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
30
34
|
declare const _default: typeof __VLS_export;
|
|
31
35
|
export default _default;
|
|
@@ -11,14 +11,18 @@ type __VLS_Props = {
|
|
|
11
11
|
leadingIcon?: string;
|
|
12
12
|
clearable?: boolean;
|
|
13
13
|
fieldBg?: string;
|
|
14
|
+
debounce?: number;
|
|
14
15
|
};
|
|
15
16
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
16
17
|
"update:modelValue": (args_0: string) => any;
|
|
18
|
+
debounced: (args_0: string) => any;
|
|
17
19
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
18
20
|
"onUpdate:modelValue"?: ((args_0: string) => any) | undefined;
|
|
21
|
+
onDebounced?: ((args_0: string) => any) | undefined;
|
|
19
22
|
}>, {
|
|
20
23
|
variant: "filled" | "outlined";
|
|
21
24
|
clearable: boolean;
|
|
25
|
+
debounce: number;
|
|
22
26
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
23
27
|
declare const _default: typeof __VLS_export;
|
|
24
28
|
export default _default;
|
|
@@ -16,11 +16,14 @@ type __VLS_Props = {
|
|
|
16
16
|
maxChips?: number;
|
|
17
17
|
noResultsText?: string;
|
|
18
18
|
hideSelected?: boolean;
|
|
19
|
+
debounce?: number;
|
|
19
20
|
};
|
|
20
21
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
21
22
|
"update:modelValue": (args_0: unknown[]) => any;
|
|
23
|
+
debounced: (args_0: string) => any;
|
|
22
24
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
23
25
|
"onUpdate:modelValue"?: ((args_0: unknown[]) => any) | undefined;
|
|
26
|
+
onDebounced?: ((args_0: string) => any) | undefined;
|
|
24
27
|
}>, {
|
|
25
28
|
required: boolean;
|
|
26
29
|
modelValue: unknown[];
|
|
@@ -28,6 +31,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
28
31
|
mode: "docked" | "modal";
|
|
29
32
|
disabled: boolean;
|
|
30
33
|
clearable: boolean;
|
|
34
|
+
debounce: number;
|
|
31
35
|
maxChips: number;
|
|
32
36
|
hideSelected: boolean;
|
|
33
37
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -12,14 +12,18 @@ type __VLS_Props = {
|
|
|
12
12
|
leadingIcon?: string;
|
|
13
13
|
stepper?: boolean;
|
|
14
14
|
fieldBg?: string;
|
|
15
|
+
debounce?: number;
|
|
15
16
|
};
|
|
16
17
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
17
18
|
"update:modelValue": (args_0: number | null) => any;
|
|
19
|
+
debounced: (args_0: number | null) => any;
|
|
18
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
19
21
|
"onUpdate:modelValue"?: ((args_0: number | null) => any) | undefined;
|
|
22
|
+
onDebounced?: ((args_0: number | null) => any) | undefined;
|
|
20
23
|
}>, {
|
|
21
24
|
modelValue: number | null;
|
|
22
25
|
variant: "filled" | "outlined";
|
|
26
|
+
debounce: number;
|
|
23
27
|
step: number;
|
|
24
28
|
stepper: boolean;
|
|
25
29
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -27,9 +27,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
27
27
|
"onUpdate:modelValue"?: ((args_0: boolean) => any) | undefined;
|
|
28
28
|
}>, {
|
|
29
29
|
loading: boolean;
|
|
30
|
+
debounce: number;
|
|
30
31
|
hotkey: string;
|
|
31
32
|
results: SpotlightResult[];
|
|
32
|
-
debounce: number;
|
|
33
33
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
34
34
|
declare const _default: typeof __VLS_export;
|
|
35
35
|
export default _default;
|
|
@@ -12,17 +12,21 @@ type __VLS_Props = {
|
|
|
12
12
|
maxTags?: number;
|
|
13
13
|
duplicates?: boolean;
|
|
14
14
|
clearable?: boolean;
|
|
15
|
+
debounce?: number;
|
|
15
16
|
};
|
|
16
17
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
17
18
|
"update:modelValue": (args_0: string[]) => any;
|
|
19
|
+
debounced: (args_0: string[]) => any;
|
|
18
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
19
21
|
"onUpdate:modelValue"?: ((args_0: string[]) => any) | undefined;
|
|
22
|
+
onDebounced?: ((args_0: string[]) => any) | undefined;
|
|
20
23
|
}>, {
|
|
21
24
|
required: boolean;
|
|
22
25
|
modelValue: string[];
|
|
23
26
|
variant: "filled" | "outlined";
|
|
24
27
|
disabled: boolean;
|
|
25
28
|
clearable: boolean;
|
|
29
|
+
debounce: number;
|
|
26
30
|
duplicates: boolean;
|
|
27
31
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
32
|
declare const _default: typeof __VLS_export;
|