@m3ui-vue/m3ui-vue 0.3.1 → 0.4.0

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.
Files changed (82) hide show
  1. package/dist/{MMenuItem-C6RwHl-l.js → MMenuItem-FyttjOj_.js} +399 -207
  2. package/dist/MMenuItem-FyttjOj_.js.map +1 -0
  3. package/dist/components/MAutocomplete.vue.d.ts +2 -0
  4. package/dist/components/MBox.vue.d.ts +2 -2
  5. package/dist/components/MButton.vue.d.ts +4 -0
  6. package/dist/components/MButtonGroup.vue.d.ts +28 -0
  7. package/dist/components/MCarousel.vue.d.ts +21 -12
  8. package/dist/components/MColorPickerModal.vue.d.ts +18 -0
  9. package/dist/components/MDataTable.vue.d.ts +1 -1
  10. package/dist/components/MDatePickerModal.vue.d.ts +21 -0
  11. package/dist/components/MDateRangePickerModal.vue.d.ts +24 -0
  12. package/dist/components/MDialog.vue.d.ts +9 -1
  13. package/dist/components/MExpansionPanel.vue.d.ts +3 -2
  14. package/dist/components/MFab.vue.d.ts +14 -2
  15. package/dist/components/MFlex.vue.d.ts +2 -2
  16. package/dist/components/MIconButton.vue.d.ts +4 -2
  17. package/dist/components/MInfiniteScroll.vue.d.ts +1 -1
  18. package/dist/components/MList.vue.d.ts +2 -0
  19. package/dist/components/MLoadingOverlay.vue.d.ts +1 -1
  20. package/dist/components/MMenu.vue.d.ts +3 -1
  21. package/dist/components/MMenuItem.vue.d.ts +14 -3
  22. package/dist/components/MMultiAutocomplete.vue.d.ts +2 -0
  23. package/dist/components/MMultiSelect.vue.d.ts +2 -0
  24. package/dist/components/MNavigationDrawer.vue.d.ts +1 -1
  25. package/dist/components/MNotificationHost.vue.d.ts +3 -0
  26. package/dist/components/MSelect.vue.d.ts +2 -0
  27. package/dist/components/MSlider.vue.d.ts +15 -4
  28. package/dist/components/MSplitButton.vue.d.ts +39 -0
  29. package/dist/components/MSplitter.vue.d.ts +1 -1
  30. package/dist/components/MStack.vue.d.ts +2 -2
  31. package/dist/components/MTable.vue.d.ts +1 -1
  32. package/dist/components/MTimePickerModal.vue.d.ts +21 -0
  33. package/dist/components/MToolbar.vue.d.ts +30 -0
  34. package/dist/components/MTooltip.vue.d.ts +8 -2
  35. package/dist/components/MWindow.vue.d.ts +2 -2
  36. package/dist/composables/useDevice.d.ts +3 -0
  37. package/dist/composables/useNotification.d.ts +64 -0
  38. package/dist/composables/useToast.d.ts +8 -0
  39. package/dist/index.d.ts +12 -0
  40. package/dist/m3ui-vue.css +1 -1
  41. package/dist/m3ui.js +5220 -2994
  42. package/dist/m3ui.js.map +1 -1
  43. package/dist/rich-text-editor.js +10 -10
  44. package/dist/styles.css +1 -1
  45. package/package.json +1 -1
  46. package/src/components/MAutocomplete.vue +108 -13
  47. package/src/components/MButton.vue +38 -16
  48. package/src/components/MButtonGroup.vue +158 -0
  49. package/src/components/MCarousel.vue +223 -101
  50. package/src/components/MColorPicker.vue +1 -4
  51. package/src/components/MColorPickerModal.vue +276 -0
  52. package/src/components/MDatePicker.vue +1 -4
  53. package/src/components/MDatePickerModal.vue +265 -0
  54. package/src/components/MDateRangePicker.vue +1 -4
  55. package/src/components/MDateRangePickerModal.vue +264 -0
  56. package/src/components/MDialog.vue +38 -1
  57. package/src/components/MExpansionPanel.vue +10 -32
  58. package/src/components/MFab.vue +92 -11
  59. package/src/components/MIconButton.vue +36 -6
  60. package/src/components/MList.vue +6 -3
  61. package/src/components/MListItem.vue +9 -3
  62. package/src/components/MMenu.vue +10 -5
  63. package/src/components/MMenuItem.vue +93 -10
  64. package/src/components/MMultiAutocomplete.vue +104 -10
  65. package/src/components/MMultiSelect.vue +106 -13
  66. package/src/components/MNotificationHost.vue +163 -0
  67. package/src/components/MSelect.vue +99 -16
  68. package/src/components/MSlider.vue +367 -134
  69. package/src/components/MSnackbar.vue +3 -0
  70. package/src/components/MSplitButton.vue +240 -0
  71. package/src/components/MTabs.vue +82 -39
  72. package/src/components/MTagInput.vue +11 -1
  73. package/src/components/MTimePicker.vue +1 -4
  74. package/src/components/MTimePickerModal.vue +458 -0
  75. package/src/components/MToolbar.vue +75 -0
  76. package/src/components/MTooltip.vue +60 -10
  77. package/src/components/_MContextMenuPanel.vue +2 -2
  78. package/src/composables/useDevice.ts +29 -0
  79. package/src/composables/useNotification.ts +93 -0
  80. package/src/composables/useToast.ts +42 -5
  81. package/src/index.ts +12 -0
  82. package/dist/MMenuItem-C6RwHl-l.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { d as e, i as t, n, o as r, r as i, t as a } from "./MMenuItem-C6RwHl-l.js";
1
+ import { a as e, d as t, i as n, n as r, r as i, t as a } from "./MMenuItem-FyttjOj_.js";
2
2
  import { t as o } from "./MIcon-CaEooCmZ.js";
3
3
  import { t as s } from "./_plugin-vue_export-helper-B3ysoDQm.js";
4
4
  import { Fragment as c, computed as l, createCommentVNode as u, createElementBlock as d, createElementVNode as f, createTextVNode as p, createVNode as m, defineComponent as h, normalizeClass as g, normalizeStyle as _, onBeforeUnmount as v, onMounted as y, openBlock as b, ref as x, renderList as S, shallowRef as C, toDisplayString as w, watch as T, withCtx as E, withKeys as D } from "vue";
@@ -26,7 +26,7 @@ var O = {
26
26
  },
27
27
  emits: ["update:modelValue"],
28
28
  setup(s, { emit: h }) {
29
- let P = e(), F = s, I = l(() => ({
29
+ let P = t(), F = s, I = l(() => ({
30
30
  bold: P.bold,
31
31
  italic: P.italic,
32
32
  underline: P.underline,
@@ -194,9 +194,9 @@ var O = {
194
194
  function Z() {
195
195
  G.value && z.value?.chain().focus().setImage({ src: G.value }).run(), W.value = !1;
196
196
  }
197
- return (e, l) => (b(), d("div", { class: g(["overflow-hidden rounded-lg border transition-colors duration-150", s.disabled ? "border-outline-variant/50 opacity-60" : "border-outline-variant focus-within:border-primary"]) }, [
197
+ return (t, l) => (b(), d("div", { class: g(["overflow-hidden rounded-lg border transition-colors duration-150", s.disabled ? "border-outline-variant/50 opacity-60" : "border-outline-variant focus-within:border-primary"]) }, [
198
198
  R.value ? (b(), d("div", O, [
199
- m(n, { align: "left" }, {
199
+ m(r, { align: "left" }, {
200
200
  trigger: E(() => [f("button", k, [p(w(K.value) + " ", 1), m(o, {
201
201
  name: "arrow_drop_down",
202
202
  size: 20
@@ -258,18 +258,18 @@ var O = {
258
258
  class: "rte-content bg-surface px-4 py-3 text-body-large text-on-surface",
259
259
  style: _({ minHeight: s.minHeight })
260
260
  }, null, 4),
261
- m(t, {
261
+ m(n, {
262
262
  modelValue: H.value,
263
263
  "onUpdate:modelValue": l[6] ||= (e) => H.value = e,
264
264
  title: I.value.insertLink
265
265
  }, {
266
- actions: E(() => [m(r, {
266
+ actions: E(() => [m(e, {
267
267
  variant: "text",
268
268
  onClick: l[5] ||= (e) => H.value = !1
269
269
  }, {
270
270
  default: E(() => [p(w(I.value.cancel), 1)]),
271
271
  _: 1
272
- }), m(r, { onClick: Y }, {
272
+ }), m(e, { onClick: Y }, {
273
273
  default: E(() => [p(w(I.value.insert), 1)]),
274
274
  _: 1
275
275
  })]),
@@ -282,18 +282,18 @@ var O = {
282
282
  }, null, 8, ["modelValue"])]),
283
283
  _: 1
284
284
  }, 8, ["modelValue", "title"]),
285
- m(t, {
285
+ m(n, {
286
286
  modelValue: W.value,
287
287
  "onUpdate:modelValue": l[9] ||= (e) => W.value = e,
288
288
  title: I.value.insertImage
289
289
  }, {
290
- actions: E(() => [m(r, {
290
+ actions: E(() => [m(e, {
291
291
  variant: "text",
292
292
  onClick: l[8] ||= (e) => W.value = !1
293
293
  }, {
294
294
  default: E(() => [p(w(I.value.cancel), 1)]),
295
295
  _: 1
296
- }), m(r, { onClick: Z }, {
296
+ }), m(e, { onClick: Z }, {
297
297
  default: E(() => [p(w(I.value.insert), 1)]),
298
298
  _: 1
299
299
  })]),
package/dist/styles.css CHANGED
@@ -1,2 +1,2 @@
1
- .code-editor-container[data-v-b0a66a4b] .cm-editor{height:100%;min-height:inherit;font-family:Roboto Mono,Fira Code,Consolas,monospace;font-size:.8125rem;line-height:1.6}.code-editor-container[data-v-b0a66a4b] .cm-editor.cm-focused{outline:none}.code-editor-container[data-v-b0a66a4b] .cm-scroller{min-height:inherit}.code-editor-container[data-v-b0a66a4b] .cm-content{padding:12px 0}.code-editor-container[data-v-b0a66a4b] .cm-line{padding:0 16px}.code-editor-container[data-v-b0a66a4b] .cm-gutters{background:var(--color-surface-container);border-right:1px solid var(--color-outline-variant);color:var(--color-outline);padding:0 4px;font-size:.75rem}.code-editor-container[data-v-b0a66a4b] .cm-activeLineGutter{background:var(--color-surface-container-high);color:var(--color-on-surface-variant)}.code-editor-container[data-v-b0a66a4b] .cm-activeLine{background:var(--color-surface-container-lowest)}.code-editor-container[data-v-b0a66a4b] .cm-selectionBackground{background:var(--color-primary-container)!important}.code-editor-container[data-v-b0a66a4b] .cm-cursor{border-left-color:var(--color-primary);border-left-width:2px}.code-editor-container[data-v-b0a66a4b] .cm-matchingBracket{background:var(--color-tertiary-container);color:var(--color-on-tertiary-container);border-radius:2px}.code-editor-container[data-v-b0a66a4b] .cm-foldGutter span{color:var(--color-on-surface-variant)}@keyframes m3-wavy-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes m3-wavy-travel{0%{stroke-dashoffset:0}to{stroke-dashoffset:calc(var(--m3-wave-len) * -1px)}}@media (prefers-reduced-motion:reduce){.animate-\[m3-wavy-spin_2\.8s_linear_infinite\]{animation:2.8s linear infinite m3-wavy-spin}.animate-\[m3-wavy-travel_2s_linear_infinite\]{animation:none!important}}.m3-dialog-enter-active[data-v-4ccfbc3c],.m3-dialog-leave-active[data-v-4ccfbc3c]{transition:opacity .15s}.m3-dialog-enter-from[data-v-4ccfbc3c],.m3-dialog-leave-to[data-v-4ccfbc3c]{opacity:0}.m3-dialog-enter-active .dialog-box[data-v-4ccfbc3c],.m3-dialog-leave-active .dialog-box[data-v-4ccfbc3c]{transition:transform .15s}.m3-dialog-enter-from .dialog-box[data-v-4ccfbc3c],.m3-dialog-leave-to .dialog-box[data-v-4ccfbc3c]{transform:scale(.95)}.bs-scrim[data-v-5b1fb748]{transition:opacity .3s}.bs-enter-from .bs-scrim[data-v-5b1fb748],.bs-leave-to .bs-scrim[data-v-5b1fb748]{opacity:0}.bs-panel[data-v-5b1fb748]{transition:transform .32s cubic-bezier(.2,0,0,1),opacity .24s}.bs-enter-from .bs-panel[data-v-5b1fb748]{opacity:0;transform:translateY(40%)}.bs-leave-to .bs-panel[data-v-5b1fb748]{opacity:0;transform:translateY(100%)!important}.m3-carousel-right-enter-active,.m3-carousel-right-leave-active,.m3-carousel-left-enter-active,.m3-carousel-left-leave-active{transition:transform .5s cubic-bezier(.2,0,0,1),opacity .5s cubic-bezier(.2,0,0,1)}.m3-carousel-right-enter-from{opacity:0;transform:translate(100%)}.m3-carousel-right-leave-to,.m3-carousel-left-enter-from{opacity:0;transform:translate(-100%)}.m3-carousel-left-leave-to{opacity:0;transform:translate(100%)}.hue-slider[data-v-872ab758]{background:linear-gradient(90deg,red 0%,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.hue-slider[data-v-872ab758]::-webkit-slider-thumb{-webkit-appearance:none;cursor:pointer;background:#fff;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 3px #0006}.hue-slider[data-v-872ab758]::-moz-range-thumb{cursor:pointer;background:#fff;border:none;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 3px #0006}.m3-cmd-enter-active[data-v-4d6cca63],.m3-cmd-leave-active[data-v-4d6cca63]{transition:opacity .15s}.m3-cmd-enter-from[data-v-4d6cca63],.m3-cmd-leave-to[data-v-4d6cca63]{opacity:0}.m3-cmd-enter-active .cmd-box[data-v-4d6cca63],.m3-cmd-leave-active .cmd-box[data-v-4d6cca63]{transition:transform .15s}.m3-cmd-enter-from .cmd-box[data-v-4d6cca63],.m3-cmd-leave-to .cmd-box[data-v-4d6cca63]{transform:scale(.95)translateY(-10px)}.dt-expand-grid[data-v-857139c7]{grid-template-rows:0fr;transition:grid-template-rows .25s cubic-bezier(.2,0,0,1);display:grid}.dt-expand-grid.dt-expand-open[data-v-857139c7]{grid-template-rows:1fr}.dt-expand-body[data-v-857139c7]{min-height:0;overflow:hidden}.expand-grid[data-v-89e4475b]{grid-template-rows:1fr;display:grid}.expand-body[data-v-89e4475b]{min-height:0;overflow:hidden}.expand-enter-active[data-v-89e4475b]{transition:grid-template-rows .28s cubic-bezier(.2,0,0,1)}.expand-enter-active>.expand-body[data-v-89e4475b]{transition:opacity .22s}.expand-enter-from[data-v-89e4475b]{grid-template-rows:0fr}.expand-enter-from>.expand-body[data-v-89e4475b]{opacity:0}.expand-leave-active[data-v-89e4475b]{transition:grid-template-rows .22s cubic-bezier(.4,0,1,1)}.expand-leave-active>.expand-body[data-v-89e4475b]{transition:opacity .15s}.expand-leave-to[data-v-89e4475b]{grid-template-rows:0fr}.expand-leave-to>.expand-body[data-v-89e4475b]{opacity:0}.m3-file-enter-active[data-v-6b150427],.m3-file-leave-active[data-v-6b150427]{transition:all .2s}.m3-file-enter-from[data-v-6b150427],.m3-file-leave-to[data-v-6b150427]{opacity:0;transform:translateY(-8px)}.mli-expand-grid{grid-template-rows:1fr;display:grid}.mli-expand-body{min-height:0;padding-left:2rem;overflow:hidden}.mli-expand-enter-active{transition:grid-template-rows .3s cubic-bezier(.2,0,0,1)}.mli-expand-enter-active>.mli-expand-body{transition:opacity .2s cubic-bezier(.2,0,0,1) 80ms}.mli-expand-enter-from{grid-template-rows:0fr}.mli-expand-enter-from>.mli-expand-body{opacity:0}.mli-expand-leave-active{transition:grid-template-rows .25s cubic-bezier(.4,0,1,1)}.mli-expand-leave-active>.mli-expand-body{transition:opacity .12s cubic-bezier(.4,0,1,1)}.mli-expand-leave-to{grid-template-rows:0fr}.mli-expand-leave-to>.mli-expand-body{opacity:0}input[type=number][data-v-8b2327d2]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number][data-v-8b2327d2]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}input[type=number][data-v-8b2327d2]{-moz-appearance:textfield}.nd-scrim[data-v-ec337590]{transition:opacity .28s}.nd-enter-from .nd-scrim[data-v-ec337590],.nd-leave-to .nd-scrim[data-v-ec337590]{opacity:0}.nd-panel[data-v-ec337590]{transition:transform .3s cubic-bezier(.2,0,0,1)}.nd-enter-from .nd-panel-left[data-v-ec337590],.nd-leave-to .nd-panel-left[data-v-ec337590]{transform:translate(-100%)}.nd-enter-from .nd-panel-right[data-v-ec337590],.nd-leave-to .nd-panel-right[data-v-ec337590]{transform:translate(100%)}.nd-enter-from .nd-panel-top[data-v-ec337590],.nd-leave-to .nd-panel-top[data-v-ec337590]{transform:translateY(-100%)}.nd-enter-from .nd-panel-bottom[data-v-ec337590],.nd-leave-to .nd-panel-bottom[data-v-ec337590]{transform:translateY(100%)}.nd-section-grid[data-v-ec337590]{grid-template-rows:1fr;display:grid}.nd-section-body[data-v-ec337590]{min-height:0;overflow:hidden}.nd-section-enter-active[data-v-ec337590]{transition:grid-template-rows .35s cubic-bezier(.2,0,0,1)}.nd-section-enter-active>.nd-section-body[data-v-ec337590]{transition:opacity .25s cubic-bezier(.2,0,0,1) 80ms}.nd-section-enter-from[data-v-ec337590]{grid-template-rows:0fr}.nd-section-enter-from>.nd-section-body[data-v-ec337590]{opacity:0}.nd-section-leave-active[data-v-ec337590]{transition:grid-template-rows .28s cubic-bezier(.4,0,1,1)}.nd-section-leave-active>.nd-section-body[data-v-ec337590]{transition:opacity .15s cubic-bezier(.4,0,1,1)}.nd-section-leave-to[data-v-ec337590]{grid-template-rows:0fr}.nd-section-leave-to>.nd-section-body[data-v-ec337590]{opacity:0}.nd-inline[data-v-ec337590]{transition:width .3s cubic-bezier(.2,0,0,1);overflow:hidden}.nd-inline[data-v-ec337590]>*{min-width:var(--nd-width,18rem)}.nd-inline.nd-collapsed[data-v-ec337590]>*{min-width:0}.nd-toggle[data-v-ec337590]{align-items:center;display:flex}.nd-toggle-inner[data-v-ec337590]{flex-shrink:0;justify-content:center;align-items:center;width:72px;height:64px;display:flex}.nd-label[data-v-ec337590]{transition:opacity .2s cubic-bezier(.2,0,0,1) 80ms}.nd-inline.nd-collapsed .nd-label[data-v-ec337590],.nd-inline.nd-collapsed[data-v-ec337590] .nd-label{opacity:0;transition:opacity .1s cubic-bezier(.2,0,0,1)}.nd-inline .nd-collapse-h[data-v-ec337590]{max-height:80px;transition:max-height .3s cubic-bezier(.2,0,0,1)}.nd-inline.nd-collapsed .nd-collapse-h[data-v-ec337590]{max-height:0}.nd-inline .nd-section-body[data-v-ec337590]>*,.nd-inline[data-v-ec337590] .nd-section-body>*{transition:padding .3s cubic-bezier(.2,0,0,1)}.nd-children-divider[data-v-ec337590]{border-top:1px solid #0000;height:0;margin:0 .75rem;transition:border-color .1s,margin .1s}.nd-inline.nd-collapsed .nd-children-divider[data-v-ec337590]{border-top-color:var(--color-outline-variant);margin:.25rem .75rem;transition:border-color .2s .3s,margin .2s .3s}@keyframes m3-wave-flow{0%{transform:translate(0)}to{transform:translate(-20px)}}@keyframes m3-progress-indeterminate{0%{left:-40%}to{left:100%}}@media (prefers-reduced-motion:reduce){.animate-\[m3-wave-flow_1\.2s_linear_infinite\],.animate-\[m3-wave-flow_0\.9s_linear_infinite\],.animate-\[m3-progress-indeterminate_1\.6s_ease-in-out_infinite\]{animation:none!important}}.m3-radio-dot[data-v-cdb650b5]{transform-box:fill-box;transform-origin:50%;transition:transform .15s;transform:scale(0)}.m3-radio-dot.is-checked[data-v-cdb650b5]{transform:scale(1)}.ss-scrim[data-v-ba5b6f4b]{transition:opacity .28s}.ss-enter-from .ss-scrim[data-v-ba5b6f4b],.ss-leave-to .ss-scrim[data-v-ba5b6f4b]{opacity:0}.ss-panel[data-v-ba5b6f4b]{transition:transform .32s cubic-bezier(.2,0,0,1),opacity .24s}.ss-enter-from .ss-panel[data-v-ba5b6f4b]{opacity:0;transform:translate(40%)}.ss-leave-to .ss-panel[data-v-ba5b6f4b]{opacity:0;transform:translate(100%)!important}@keyframes skeleton-wave-move-32ecf05b{0%{transform:translate(-100%)}60%{transform:translate(100%)}to{transform:translate(100%)}}.skeleton-wave[data-v-32ecf05b]{position:relative;overflow:hidden}.skeleton-wave[data-v-32ecf05b]:after{content:"";background:linear-gradient(90deg, transparent 0%, var(--color-on-surface) 50%, transparent 100%);opacity:.06;animation:1.8s ease-in-out infinite skeleton-wave-move-32ecf05b;position:absolute;inset:0}.toast-row[data-v-64ce9e7c]{grid-template-rows:1fr;padding-bottom:8px;display:grid}.toast-row>.toast-inner[data-v-64ce9e7c]{min-height:0}.m3-toast-bot-enter-active[data-v-64ce9e7c]{transition:grid-template-rows .22s cubic-bezier(.2,0,0,1),padding-bottom .22s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-bot-enter-active>.toast-inner[data-v-64ce9e7c]{transition:opacity .18s,transform .22s cubic-bezier(.2,0,0,1)}.m3-toast-bot-enter-from[data-v-64ce9e7c]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-bot-enter-from>.toast-inner[data-v-64ce9e7c]{opacity:0;transform:translateY(20px)scale(.94)}.m3-toast-bot-leave-active[data-v-64ce9e7c]{transition:grid-template-rows .3s cubic-bezier(.2,0,0,1),padding-bottom .3s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-bot-leave-active>.toast-inner[data-v-64ce9e7c]{transition:opacity .18s,transform .18s}.m3-toast-bot-leave-to[data-v-64ce9e7c]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-bot-leave-to>.toast-inner[data-v-64ce9e7c]{opacity:0;transform:scale(.92)}.m3-toast-top-enter-active[data-v-64ce9e7c]{transition:grid-template-rows .22s cubic-bezier(.2,0,0,1),padding-bottom .22s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-top-enter-active>.toast-inner[data-v-64ce9e7c]{transition:opacity .18s,transform .22s cubic-bezier(.2,0,0,1)}.m3-toast-top-enter-from[data-v-64ce9e7c]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-top-enter-from>.toast-inner[data-v-64ce9e7c]{opacity:0;transform:translateY(-20px)scale(.94)}.m3-toast-top-leave-active[data-v-64ce9e7c]{transition:grid-template-rows .3s cubic-bezier(.2,0,0,1),padding-bottom .3s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-top-leave-active>.toast-inner[data-v-64ce9e7c]{transition:opacity .18s,transform .18s}.m3-toast-top-leave-to[data-v-64ce9e7c]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-top-leave-to>.toast-inner[data-v-64ce9e7c]{opacity:0;transform:scale(.92)}@keyframes m3-toast-progress-64ce9e7c{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.m3-spot-enter-active[data-v-1fa0da82],.m3-spot-leave-active[data-v-1fa0da82]{transition:opacity .15s}.m3-spot-enter-from[data-v-1fa0da82],.m3-spot-leave-to[data-v-1fa0da82]{opacity:0}.m3-spot-enter-active .spot-box[data-v-1fa0da82],.m3-spot-leave-active .spot-box[data-v-1fa0da82]{transition:transform .15s,opacity .15s}.m3-spot-enter-from .spot-box[data-v-1fa0da82]{opacity:0;transform:scale(.96)translateY(-8px)}.m3-spot-leave-to .spot-box[data-v-1fa0da82]{opacity:0;transform:scale(.98)}.m3-tour-highlight{box-shadow:0 0 0 4px var(--color-primary);border-radius:8px;position:relative;z-index:201!important}.m3-tour-enter-active,.m3-tour-leave-active{transition:opacity .2s}.m3-tour-enter-from,.m3-tour-leave-to{opacity:0}.m3-markdown[data-v-23db2c2c] h1{font-size:var(--text-headline-large);line-height:var(--text-headline-large--line-height);color:var(--color-on-surface);margin:1em 0 .5em;font-weight:600}.m3-markdown[data-v-23db2c2c] h2{font-size:var(--text-headline-medium);line-height:var(--text-headline-medium--line-height);color:var(--color-on-surface);margin:1em 0 .5em;font-weight:600}.m3-markdown[data-v-23db2c2c] h3{font-size:var(--text-headline-small);line-height:var(--text-headline-small--line-height);color:var(--color-on-surface);margin:.75em 0 .25em;font-weight:600}.m3-markdown[data-v-23db2c2c] h4{font-size:var(--text-title-large);line-height:var(--text-title-large--line-height);color:var(--color-on-surface);margin:.75em 0 .25em;font-weight:600}.m3-markdown[data-v-23db2c2c] p{margin:.5em 0}.m3-markdown[data-v-23db2c2c] a{color:var(--color-primary);text-underline-offset:2px;text-decoration:underline}.m3-markdown[data-v-23db2c2c] a:hover{opacity:.8}.m3-markdown[data-v-23db2c2c] strong{color:var(--color-on-surface);font-weight:600}.m3-markdown[data-v-23db2c2c] em{font-style:italic}.m3-markdown[data-v-23db2c2c] ul{margin:.5em 0;padding-left:1.5em;list-style-type:disc}.m3-markdown[data-v-23db2c2c] ol{margin:.5em 0;padding-left:1.5em;list-style-type:decimal}.m3-markdown[data-v-23db2c2c] li{margin:.25em 0}.m3-markdown[data-v-23db2c2c] li::marker{color:var(--color-on-surface-variant)}.m3-markdown[data-v-23db2c2c] blockquote{border-left:3px solid var(--color-primary);background:var(--color-surface-container);color:var(--color-on-surface-variant);border-radius:0 8px 8px 0;margin:.75em 0;padding:.5em 1em}.m3-markdown[data-v-23db2c2c] code{background:var(--color-surface-container-highest);color:var(--color-primary);border-radius:4px;padding:.15em .4em;font-family:Roboto Mono,Fira Code,Consolas,monospace;font-size:.875em}.m3-markdown[data-v-23db2c2c] pre{background:var(--color-surface-container-highest);border:1px solid var(--color-outline-variant);border-radius:12px;margin:.75em 0;padding:1em;overflow-x:auto}.m3-markdown[data-v-23db2c2c] pre code{color:var(--color-on-surface);background:0 0;padding:0;font-size:.8125rem;line-height:1.6}.m3-markdown[data-v-23db2c2c] .hljs-keyword,.m3-markdown[data-v-23db2c2c] .hljs-selector-tag,.m3-markdown[data-v-23db2c2c] .hljs-built_in,.m3-markdown[data-v-23db2c2c] .hljs-tag .hljs-keyword{color:var(--color-primary)}.m3-markdown[data-v-23db2c2c] .hljs-string,.m3-markdown[data-v-23db2c2c] .hljs-regexp,.m3-markdown[data-v-23db2c2c] .hljs-template-variable{color:var(--color-tertiary)}.m3-markdown[data-v-23db2c2c] .hljs-number,.m3-markdown[data-v-23db2c2c] .hljs-literal{color:var(--color-error)}.m3-markdown[data-v-23db2c2c] .hljs-title.function_,.m3-markdown[data-v-23db2c2c] .hljs-title.function_>.hljs-keyword{color:var(--color-secondary);font-weight:500}.m3-markdown[data-v-23db2c2c] .hljs-type,.m3-markdown[data-v-23db2c2c] .hljs-title.class_{color:var(--color-primary);font-style:italic}.m3-markdown[data-v-23db2c2c] .hljs-comment,.m3-markdown[data-v-23db2c2c] .hljs-quote{color:var(--color-outline);font-style:italic}.m3-markdown[data-v-23db2c2c] .hljs-attr,.m3-markdown[data-v-23db2c2c] .hljs-attribute{color:var(--color-tertiary)}.m3-markdown[data-v-23db2c2c] .hljs-tag{color:var(--color-on-surface-variant)}.m3-markdown[data-v-23db2c2c] .hljs-name{color:var(--color-primary)}.m3-markdown[data-v-23db2c2c] .hljs-punctuation,.m3-markdown[data-v-23db2c2c] .hljs-operator,.m3-markdown[data-v-23db2c2c] .hljs-meta,.m3-markdown[data-v-23db2c2c] .hljs-meta .hljs-keyword{color:var(--color-on-surface-variant)}.m3-markdown[data-v-23db2c2c] .hljs-variable,.m3-markdown[data-v-23db2c2c] .hljs-property,.m3-markdown[data-v-23db2c2c] .hljs-symbol,.m3-markdown[data-v-23db2c2c] .hljs-params{color:var(--color-on-surface)}.m3-markdown[data-v-23db2c2c] .m3-code-block{position:relative}.m3-markdown[data-v-23db2c2c] .m3-code-copy{background:var(--color-surface-container);width:28px;height:28px;color:var(--color-on-surface-variant);cursor:pointer;opacity:0;z-index:1;border:none;border-radius:6px;justify-content:center;align-items:center;transition:opacity .15s;display:flex;position:absolute;top:8px;right:8px}.m3-markdown[data-v-23db2c2c] .m3-code-block:hover .m3-code-copy{opacity:1}.m3-markdown[data-v-23db2c2c] .m3-code-copy:hover{background:var(--color-surface-container-high);color:var(--color-on-surface)}.m3-markdown[data-v-23db2c2c] .m3-code-line{display:block}.m3-markdown[data-v-23db2c2c] .m3-line-hl{background:color-mix(in srgb, var(--color-primary) 8%, transparent);border-left:2px solid color-mix(in srgb, var(--color-primary) 40%, transparent);margin:0 -1em;padding:0 1em 0 calc(1em - 2px)}.m3-markdown[data-v-23db2c2c] hr{border:none;border-top:1px solid var(--color-outline-variant);margin:1.5em 0}.m3-markdown[data-v-23db2c2c] table{border-collapse:collapse;width:100%;margin:.75em 0}.m3-markdown[data-v-23db2c2c] th{background:var(--color-surface-container);text-align:left;border-bottom:2px solid var(--color-outline-variant);font-weight:600;font-size:var(--text-label-large);color:var(--color-on-surface);padding:.5em .75em}.m3-markdown[data-v-23db2c2c] td{border-bottom:1px solid var(--color-outline-variant);padding:.5em .75em}.m3-markdown[data-v-23db2c2c] img{border-radius:12px;max-width:100%;height:auto;margin:.5em 0}.rte-content[data-v-e6829e5c] .tiptap{min-height:inherit;outline:none}.rte-content[data-v-e6829e5c] .tiptap p.is-editor-empty:first-child:before{content:attr(data-placeholder);float:left;color:var(--color-on-surface-variant);opacity:.5;pointer-events:none;height:0}.rte-content[data-v-e6829e5c] h1{font-size:var(--text-headline-large);line-height:var(--text-headline-large--line-height);margin:.75em 0 .25em;font-weight:600}.rte-content[data-v-e6829e5c] h2{font-size:var(--text-headline-medium);line-height:var(--text-headline-medium--line-height);margin:.75em 0 .25em;font-weight:600}.rte-content[data-v-e6829e5c] h3{font-size:var(--text-headline-small);line-height:var(--text-headline-small--line-height);margin:.75em 0 .25em;font-weight:600}.rte-content[data-v-e6829e5c] p{margin:.5em 0}.rte-content[data-v-e6829e5c] ul{margin:.5em 0;padding-left:1.5em;list-style-type:disc}.rte-content[data-v-e6829e5c] ol{margin:.5em 0;padding-left:1.5em;list-style-type:decimal}.rte-content[data-v-e6829e5c] blockquote{border-left:3px solid var(--color-primary);color:var(--color-on-surface-variant);margin:.5em 0;padding-left:1em}.rte-content[data-v-e6829e5c] code{background:var(--color-surface-container-highest);border-radius:4px;padding:.15em .4em;font-size:.875em}.rte-content[data-v-e6829e5c] pre{background:var(--color-surface-container-highest);border-radius:8px;margin:.5em 0;padding:1em;overflow-x:auto}.rte-content[data-v-e6829e5c] pre code{background:0 0;padding:0}.rte-content[data-v-e6829e5c] a{color:var(--color-primary);text-decoration:underline}.rte-content[data-v-e6829e5c] mark{background:var(--color-tertiary-container);color:var(--color-on-tertiary-container);border-radius:2px;padding:.1em .2em}.rte-content[data-v-e6829e5c] img{border-radius:8px;max-width:100%;height:auto;margin:.5em 0}
1
+ .code-editor-container[data-v-b0a66a4b] .cm-editor{height:100%;min-height:inherit;font-family:Roboto Mono,Fira Code,Consolas,monospace;font-size:.8125rem;line-height:1.6}.code-editor-container[data-v-b0a66a4b] .cm-editor.cm-focused{outline:none}.code-editor-container[data-v-b0a66a4b] .cm-scroller{min-height:inherit}.code-editor-container[data-v-b0a66a4b] .cm-content{padding:12px 0}.code-editor-container[data-v-b0a66a4b] .cm-line{padding:0 16px}.code-editor-container[data-v-b0a66a4b] .cm-gutters{background:var(--color-surface-container);border-right:1px solid var(--color-outline-variant);color:var(--color-outline);padding:0 4px;font-size:.75rem}.code-editor-container[data-v-b0a66a4b] .cm-activeLineGutter{background:var(--color-surface-container-high);color:var(--color-on-surface-variant)}.code-editor-container[data-v-b0a66a4b] .cm-activeLine{background:var(--color-surface-container-lowest)}.code-editor-container[data-v-b0a66a4b] .cm-selectionBackground{background:var(--color-primary-container)!important}.code-editor-container[data-v-b0a66a4b] .cm-cursor{border-left-color:var(--color-primary);border-left-width:2px}.code-editor-container[data-v-b0a66a4b] .cm-matchingBracket{background:var(--color-tertiary-container);color:var(--color-on-tertiary-container);border-radius:2px}.code-editor-container[data-v-b0a66a4b] .cm-foldGutter span{color:var(--color-on-surface-variant)}@keyframes m3-wavy-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes m3-wavy-travel{0%{stroke-dashoffset:0}to{stroke-dashoffset:calc(var(--m3-wave-len) * -1px)}}@media (prefers-reduced-motion:reduce){.animate-\[m3-wavy-spin_2\.8s_linear_infinite\]{animation:2.8s linear infinite m3-wavy-spin}.animate-\[m3-wavy-travel_2s_linear_infinite\]{animation:none!important}}.m3-dialog-enter-active[data-v-2e3c3567],.m3-dialog-leave-active[data-v-2e3c3567]{transition:opacity .15s}.m3-dialog-enter-from[data-v-2e3c3567],.m3-dialog-leave-to[data-v-2e3c3567]{opacity:0}.m3-dialog-enter-active .dialog-box[data-v-2e3c3567],.m3-dialog-leave-active .dialog-box[data-v-2e3c3567]{transition:transform .15s}.m3-dialog-enter-from .dialog-box[data-v-2e3c3567],.m3-dialog-leave-to .dialog-box[data-v-2e3c3567]{transform:scale(.95)}.m3-dialog-fs-enter-active[data-v-2e3c3567],.m3-dialog-fs-leave-active[data-v-2e3c3567]{transition:transform .25s cubic-bezier(.2,0,0,1),opacity .15s}.m3-dialog-fs-enter-from[data-v-2e3c3567],.m3-dialog-fs-leave-to[data-v-2e3c3567]{opacity:0;transform:translateY(100%)}.toast-row[data-v-0859cf20]{grid-template-rows:1fr;padding-bottom:8px;display:grid}.toast-row>.toast-inner[data-v-0859cf20]{min-height:0}.m3-toast-bot-enter-active[data-v-0859cf20]{transition:grid-template-rows .22s cubic-bezier(.2,0,0,1),padding-bottom .22s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-bot-enter-active>.toast-inner[data-v-0859cf20]{transition:opacity .18s,transform .22s cubic-bezier(.2,0,0,1)}.m3-toast-bot-enter-from[data-v-0859cf20]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-bot-enter-from>.toast-inner[data-v-0859cf20]{opacity:0;transform:translateY(20px)scale(.94)}.m3-toast-bot-leave-active[data-v-0859cf20]{transition:grid-template-rows .3s cubic-bezier(.2,0,0,1),padding-bottom .3s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-bot-leave-active>.toast-inner[data-v-0859cf20]{transition:opacity .18s,transform .18s}.m3-toast-bot-leave-to[data-v-0859cf20]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-bot-leave-to>.toast-inner[data-v-0859cf20]{opacity:0;transform:scale(.92)}.m3-toast-top-enter-active[data-v-0859cf20]{transition:grid-template-rows .22s cubic-bezier(.2,0,0,1),padding-bottom .22s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-top-enter-active>.toast-inner[data-v-0859cf20]{transition:opacity .18s,transform .22s cubic-bezier(.2,0,0,1)}.m3-toast-top-enter-from[data-v-0859cf20]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-top-enter-from>.toast-inner[data-v-0859cf20]{opacity:0;transform:translateY(-20px)scale(.94)}.m3-toast-top-leave-active[data-v-0859cf20]{transition:grid-template-rows .3s cubic-bezier(.2,0,0,1),padding-bottom .3s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-top-leave-active>.toast-inner[data-v-0859cf20]{transition:opacity .18s,transform .18s}.m3-toast-top-leave-to[data-v-0859cf20]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-top-leave-to>.toast-inner[data-v-0859cf20]{opacity:0;transform:scale(.92)}@keyframes m3-toast-progress-0859cf20{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.notif-row[data-v-6eb78ef7]{grid-template-rows:1fr;padding-bottom:6px;display:grid}.notif-row>.notif-inner[data-v-6eb78ef7]{min-height:0}.m3-notif-bot-enter-active[data-v-6eb78ef7]{transition:grid-template-rows .2s,padding-bottom .2s;overflow:hidden}.m3-notif-bot-enter-active>.notif-inner[data-v-6eb78ef7]{transition:opacity .15s,transform .2s}.m3-notif-bot-enter-from[data-v-6eb78ef7]{grid-template-rows:0fr;padding-bottom:0}.m3-notif-bot-enter-from>.notif-inner[data-v-6eb78ef7]{opacity:0;transform:translateY(12px)scale(.95)}.m3-notif-bot-leave-active[data-v-6eb78ef7]{transition:grid-template-rows .25s,padding-bottom .25s;overflow:hidden}.m3-notif-bot-leave-active>.notif-inner[data-v-6eb78ef7]{transition:opacity .15s,transform .15s}.m3-notif-bot-leave-to[data-v-6eb78ef7]{grid-template-rows:0fr;padding-bottom:0}.m3-notif-bot-leave-to>.notif-inner[data-v-6eb78ef7]{opacity:0;transform:scale(.93)}.m3-notif-top-enter-active[data-v-6eb78ef7]{transition:grid-template-rows .2s,padding-bottom .2s;overflow:hidden}.m3-notif-top-enter-active>.notif-inner[data-v-6eb78ef7]{transition:opacity .15s,transform .2s}.m3-notif-top-enter-from[data-v-6eb78ef7]{grid-template-rows:0fr;padding-bottom:0}.m3-notif-top-enter-from>.notif-inner[data-v-6eb78ef7]{opacity:0;transform:translateY(-12px)scale(.95)}.m3-notif-top-leave-active[data-v-6eb78ef7]{transition:grid-template-rows .25s,padding-bottom .25s;overflow:hidden}.m3-notif-top-leave-active>.notif-inner[data-v-6eb78ef7]{transition:opacity .15s,transform .15s}.m3-notif-top-leave-to[data-v-6eb78ef7]{grid-template-rows:0fr;padding-bottom:0}.m3-notif-top-leave-to>.notif-inner[data-v-6eb78ef7]{opacity:0;transform:scale(.93)}.m3-ac-modal-enter-active[data-v-32ed54a5],.m3-ac-modal-leave-active[data-v-32ed54a5]{transition:opacity .15s}.m3-ac-modal-enter-from[data-v-32ed54a5],.m3-ac-modal-leave-to[data-v-32ed54a5]{opacity:0}.m3-ac-modal-enter-active .ac-modal-box[data-v-32ed54a5],.m3-ac-modal-leave-active .ac-modal-box[data-v-32ed54a5]{transition:transform .15s}.m3-ac-modal-enter-from .ac-modal-box[data-v-32ed54a5],.m3-ac-modal-leave-to .ac-modal-box[data-v-32ed54a5]{transform:scale(.95)}.bs-scrim[data-v-5b1fb748]{transition:opacity .3s}.bs-enter-from .bs-scrim[data-v-5b1fb748],.bs-leave-to .bs-scrim[data-v-5b1fb748]{opacity:0}.bs-panel[data-v-5b1fb748]{transition:transform .32s cubic-bezier(.2,0,0,1),opacity .24s}.bs-enter-from .bs-panel[data-v-5b1fb748]{opacity:0;transform:translateY(40%)}.bs-leave-to .bs-panel[data-v-5b1fb748]{opacity:0;transform:translateY(100%)!important}.carousel-track[data-v-f1acc440]{scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none}.carousel-track[data-v-f1acc440]::-webkit-scrollbar{display:none}.snap-center[data-v-f1acc440]>*{scroll-snap-align:center}.snap-start[data-v-f1acc440]>*{scroll-snap-align:start}.hue-slider[data-v-cf276414]{background:linear-gradient(90deg,red 0%,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.hue-slider[data-v-cf276414]::-webkit-slider-thumb{-webkit-appearance:none;cursor:pointer;background:#fff;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 3px #0006}.hue-slider[data-v-cf276414]::-moz-range-thumb{cursor:pointer;background:#fff;border:none;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 3px #0006}.hue-slider[data-v-59c0237f]{background:linear-gradient(90deg,red 0%,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.hue-slider[data-v-59c0237f]::-webkit-slider-thumb{-webkit-appearance:none;cursor:pointer;background:#fff;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 3px #0006}.hue-slider[data-v-59c0237f]::-moz-range-thumb{cursor:pointer;background:#fff;border:none;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 3px #0006}.m3-cp-modal-enter-active[data-v-59c0237f],.m3-cp-modal-leave-active[data-v-59c0237f]{transition:opacity .15s}.m3-cp-modal-enter-from[data-v-59c0237f],.m3-cp-modal-leave-to[data-v-59c0237f]{opacity:0}.m3-cp-modal-enter-active .cp-box[data-v-59c0237f],.m3-cp-modal-leave-active .cp-box[data-v-59c0237f]{transition:transform .15s}.m3-cp-modal-enter-from .cp-box[data-v-59c0237f],.m3-cp-modal-leave-to .cp-box[data-v-59c0237f]{transform:scale(.95)}.m3-cmd-enter-active[data-v-4d6cca63],.m3-cmd-leave-active[data-v-4d6cca63]{transition:opacity .15s}.m3-cmd-enter-from[data-v-4d6cca63],.m3-cmd-leave-to[data-v-4d6cca63]{opacity:0}.m3-cmd-enter-active .cmd-box[data-v-4d6cca63],.m3-cmd-leave-active .cmd-box[data-v-4d6cca63]{transition:transform .15s}.m3-cmd-enter-from .cmd-box[data-v-4d6cca63],.m3-cmd-leave-to .cmd-box[data-v-4d6cca63]{transform:scale(.95)translateY(-10px)}.dt-expand-grid[data-v-857139c7]{grid-template-rows:0fr;transition:grid-template-rows .25s cubic-bezier(.2,0,0,1);display:grid}.dt-expand-grid.dt-expand-open[data-v-857139c7]{grid-template-rows:1fr}.dt-expand-body[data-v-857139c7]{min-height:0;overflow:hidden}.m3-dp-modal-enter-active[data-v-ac5f05d4],.m3-dp-modal-leave-active[data-v-ac5f05d4]{transition:opacity .15s}.m3-dp-modal-enter-from[data-v-ac5f05d4],.m3-dp-modal-leave-to[data-v-ac5f05d4]{opacity:0}.m3-dp-modal-enter-active .dp-box[data-v-ac5f05d4],.m3-dp-modal-leave-active .dp-box[data-v-ac5f05d4]{transition:transform .15s}.m3-dp-modal-enter-from .dp-box[data-v-ac5f05d4],.m3-dp-modal-leave-to .dp-box[data-v-ac5f05d4]{transform:scale(.95)}.m3-drp-modal-enter-active[data-v-fcb7a791],.m3-drp-modal-leave-active[data-v-fcb7a791]{transition:opacity .15s}.m3-drp-modal-enter-from[data-v-fcb7a791],.m3-drp-modal-leave-to[data-v-fcb7a791]{opacity:0}.m3-drp-modal-enter-active .drp-box[data-v-fcb7a791],.m3-drp-modal-leave-active .drp-box[data-v-fcb7a791]{transition:transform .15s}.m3-drp-modal-enter-from .drp-box[data-v-fcb7a791],.m3-drp-modal-leave-to .drp-box[data-v-fcb7a791]{transform:scale(.95)}.expand-grid[data-v-31731809]{grid-template-rows:0fr;transition:grid-template-rows .3s ease-in-out;display:grid}.expand-grid.expand-open[data-v-31731809]{grid-template-rows:1fr}.expand-body[data-v-31731809]{min-height:0;overflow:hidden}.m3-fab-content-enter-active[data-v-02ba313e]{transition:opacity .2s,transform .2s cubic-bezier(.2,0,0,1)}.m3-fab-content-leave-active[data-v-02ba313e]{transition:opacity .15s,transform .15s}.m3-fab-content-enter-from[data-v-02ba313e]{opacity:0;transform:scale(.85)}.m3-fab-content-leave-to[data-v-02ba313e]{opacity:0;transform:scale(.9)}.m3-file-enter-active[data-v-6b150427],.m3-file-leave-active[data-v-6b150427]{transition:all .2s}.m3-file-enter-from[data-v-6b150427],.m3-file-leave-to[data-v-6b150427]{opacity:0;transform:translateY(-8px)}.mli-expand-grid{grid-template-rows:1fr;display:grid}.mli-expand-body{min-height:0;padding-left:2rem;overflow:hidden}.mli-expand-enter-active{transition:grid-template-rows .3s cubic-bezier(.2,0,0,1)}.mli-expand-enter-active>.mli-expand-body{transition:opacity .2s cubic-bezier(.2,0,0,1) 80ms}.mli-expand-enter-from{grid-template-rows:0fr}.mli-expand-enter-from>.mli-expand-body{opacity:0}.mli-expand-leave-active{transition:grid-template-rows .25s cubic-bezier(.4,0,1,1)}.mli-expand-leave-active>.mli-expand-body{transition:opacity .12s cubic-bezier(.4,0,1,1)}.mli-expand-leave-to{grid-template-rows:0fr}.mli-expand-leave-to>.mli-expand-body{opacity:0}.m3-mac-modal-enter-active[data-v-9af9951c],.m3-mac-modal-leave-active[data-v-9af9951c]{transition:opacity .15s}.m3-mac-modal-enter-from[data-v-9af9951c],.m3-mac-modal-leave-to[data-v-9af9951c]{opacity:0}.m3-mac-modal-enter-active .mac-modal-box[data-v-9af9951c],.m3-mac-modal-leave-active .mac-modal-box[data-v-9af9951c]{transition:transform .15s}.m3-mac-modal-enter-from .mac-modal-box[data-v-9af9951c],.m3-mac-modal-leave-to .mac-modal-box[data-v-9af9951c]{transform:scale(.95)}.m3-ms-modal-enter-active[data-v-fc4bb9ca],.m3-ms-modal-leave-active[data-v-fc4bb9ca]{transition:opacity .15s}.m3-ms-modal-enter-from[data-v-fc4bb9ca],.m3-ms-modal-leave-to[data-v-fc4bb9ca]{opacity:0}.m3-ms-modal-enter-active .ms-modal-box[data-v-fc4bb9ca],.m3-ms-modal-leave-active .ms-modal-box[data-v-fc4bb9ca]{transition:transform .15s}.m3-ms-modal-enter-from .ms-modal-box[data-v-fc4bb9ca],.m3-ms-modal-leave-to .ms-modal-box[data-v-fc4bb9ca]{transform:scale(.95)}input[type=number][data-v-8b2327d2]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number][data-v-8b2327d2]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}input[type=number][data-v-8b2327d2]{-moz-appearance:textfield}.nd-scrim[data-v-ec337590]{transition:opacity .28s}.nd-enter-from .nd-scrim[data-v-ec337590],.nd-leave-to .nd-scrim[data-v-ec337590]{opacity:0}.nd-panel[data-v-ec337590]{transition:transform .3s cubic-bezier(.2,0,0,1)}.nd-enter-from .nd-panel-left[data-v-ec337590],.nd-leave-to .nd-panel-left[data-v-ec337590]{transform:translate(-100%)}.nd-enter-from .nd-panel-right[data-v-ec337590],.nd-leave-to .nd-panel-right[data-v-ec337590]{transform:translate(100%)}.nd-enter-from .nd-panel-top[data-v-ec337590],.nd-leave-to .nd-panel-top[data-v-ec337590]{transform:translateY(-100%)}.nd-enter-from .nd-panel-bottom[data-v-ec337590],.nd-leave-to .nd-panel-bottom[data-v-ec337590]{transform:translateY(100%)}.nd-section-grid[data-v-ec337590]{grid-template-rows:1fr;display:grid}.nd-section-body[data-v-ec337590]{min-height:0;overflow:hidden}.nd-section-enter-active[data-v-ec337590]{transition:grid-template-rows .35s cubic-bezier(.2,0,0,1)}.nd-section-enter-active>.nd-section-body[data-v-ec337590]{transition:opacity .25s cubic-bezier(.2,0,0,1) 80ms}.nd-section-enter-from[data-v-ec337590]{grid-template-rows:0fr}.nd-section-enter-from>.nd-section-body[data-v-ec337590]{opacity:0}.nd-section-leave-active[data-v-ec337590]{transition:grid-template-rows .28s cubic-bezier(.4,0,1,1)}.nd-section-leave-active>.nd-section-body[data-v-ec337590]{transition:opacity .15s cubic-bezier(.4,0,1,1)}.nd-section-leave-to[data-v-ec337590]{grid-template-rows:0fr}.nd-section-leave-to>.nd-section-body[data-v-ec337590]{opacity:0}.nd-inline[data-v-ec337590]{transition:width .3s cubic-bezier(.2,0,0,1);overflow:hidden}.nd-inline[data-v-ec337590]>*{min-width:var(--nd-width,18rem)}.nd-inline.nd-collapsed[data-v-ec337590]>*{min-width:0}.nd-toggle[data-v-ec337590]{align-items:center;display:flex}.nd-toggle-inner[data-v-ec337590]{flex-shrink:0;justify-content:center;align-items:center;width:72px;height:64px;display:flex}.nd-label[data-v-ec337590]{transition:opacity .2s cubic-bezier(.2,0,0,1) 80ms}.nd-inline.nd-collapsed .nd-label[data-v-ec337590],.nd-inline.nd-collapsed[data-v-ec337590] .nd-label{opacity:0;transition:opacity .1s cubic-bezier(.2,0,0,1)}.nd-inline .nd-collapse-h[data-v-ec337590]{max-height:80px;transition:max-height .3s cubic-bezier(.2,0,0,1)}.nd-inline.nd-collapsed .nd-collapse-h[data-v-ec337590]{max-height:0}.nd-inline .nd-section-body[data-v-ec337590]>*,.nd-inline[data-v-ec337590] .nd-section-body>*{transition:padding .3s cubic-bezier(.2,0,0,1)}.nd-children-divider[data-v-ec337590]{border-top:1px solid #0000;height:0;margin:0 .75rem;transition:border-color .1s,margin .1s}.nd-inline.nd-collapsed .nd-children-divider[data-v-ec337590]{border-top-color:var(--color-outline-variant);margin:.25rem .75rem;transition:border-color .2s .3s,margin .2s .3s}@keyframes m3-wave-flow{0%{transform:translate(0)}to{transform:translate(-20px)}}@keyframes m3-progress-indeterminate{0%{left:-40%}to{left:100%}}@media (prefers-reduced-motion:reduce){.animate-\[m3-wave-flow_1\.2s_linear_infinite\],.animate-\[m3-wave-flow_0\.9s_linear_infinite\],.animate-\[m3-progress-indeterminate_1\.6s_ease-in-out_infinite\]{animation:none!important}}.m3-radio-dot[data-v-cdb650b5]{transform-box:fill-box;transform-origin:50%;transition:transform .15s;transform:scale(0)}.m3-radio-dot.is-checked[data-v-cdb650b5]{transform:scale(1)}.m3-select-modal-enter-active[data-v-bc6f9740],.m3-select-modal-leave-active[data-v-bc6f9740]{transition:opacity .15s}.m3-select-modal-enter-from[data-v-bc6f9740],.m3-select-modal-leave-to[data-v-bc6f9740]{opacity:0}.m3-select-modal-enter-active .select-modal-box[data-v-bc6f9740],.m3-select-modal-leave-active .select-modal-box[data-v-bc6f9740]{transition:transform .15s}.m3-select-modal-enter-from .select-modal-box[data-v-bc6f9740],.m3-select-modal-leave-to .select-modal-box[data-v-bc6f9740]{transform:scale(.95)}.ss-scrim[data-v-ba5b6f4b]{transition:opacity .28s}.ss-enter-from .ss-scrim[data-v-ba5b6f4b],.ss-leave-to .ss-scrim[data-v-ba5b6f4b]{opacity:0}.ss-panel[data-v-ba5b6f4b]{transition:transform .32s cubic-bezier(.2,0,0,1),opacity .24s}.ss-enter-from .ss-panel[data-v-ba5b6f4b]{opacity:0;transform:translate(40%)}.ss-leave-to .ss-panel[data-v-ba5b6f4b]{opacity:0;transform:translate(100%)!important}@keyframes skeleton-wave-move-32ecf05b{0%{transform:translate(-100%)}60%{transform:translate(100%)}to{transform:translate(100%)}}.skeleton-wave[data-v-32ecf05b]{position:relative;overflow:hidden}.skeleton-wave[data-v-32ecf05b]:after{content:"";background:linear-gradient(90deg, transparent 0%, var(--color-on-surface) 50%, transparent 100%);opacity:.06;animation:1.8s ease-in-out infinite skeleton-wave-move-32ecf05b;position:absolute;inset:0}.toggle-btn[data-v-ec1435bc]{transition:border-radius .25s,background-color .15s}.m3-spot-enter-active[data-v-1fa0da82],.m3-spot-leave-active[data-v-1fa0da82]{transition:opacity .15s}.m3-spot-enter-from[data-v-1fa0da82],.m3-spot-leave-to[data-v-1fa0da82]{opacity:0}.m3-spot-enter-active .spot-box[data-v-1fa0da82],.m3-spot-leave-active .spot-box[data-v-1fa0da82]{transition:transform .15s,opacity .15s}.m3-spot-enter-from .spot-box[data-v-1fa0da82]{opacity:0;transform:scale(.96)translateY(-8px)}.m3-spot-leave-to .spot-box[data-v-1fa0da82]{opacity:0;transform:scale(.98)}.m3-tp-modal-enter-active[data-v-a2a090e9],.m3-tp-modal-leave-active[data-v-a2a090e9]{transition:opacity .15s}.m3-tp-modal-enter-from[data-v-a2a090e9],.m3-tp-modal-leave-to[data-v-a2a090e9]{opacity:0}.m3-tp-modal-enter-active .tp-box[data-v-a2a090e9],.m3-tp-modal-leave-active .tp-box[data-v-a2a090e9]{transition:transform .15s}.m3-tp-modal-enter-from .tp-box[data-v-a2a090e9],.m3-tp-modal-leave-to .tp-box[data-v-a2a090e9]{transform:scale(.95)}.m3-tour-highlight{box-shadow:0 0 0 4px var(--color-primary);border-radius:8px;position:relative;z-index:201!important}.m3-tour-enter-active,.m3-tour-leave-active{transition:opacity .2s}.m3-tour-enter-from,.m3-tour-leave-to{opacity:0}.m3-markdown[data-v-23db2c2c] h1{font-size:var(--text-headline-large);line-height:var(--text-headline-large--line-height);color:var(--color-on-surface);margin:1em 0 .5em;font-weight:600}.m3-markdown[data-v-23db2c2c] h2{font-size:var(--text-headline-medium);line-height:var(--text-headline-medium--line-height);color:var(--color-on-surface);margin:1em 0 .5em;font-weight:600}.m3-markdown[data-v-23db2c2c] h3{font-size:var(--text-headline-small);line-height:var(--text-headline-small--line-height);color:var(--color-on-surface);margin:.75em 0 .25em;font-weight:600}.m3-markdown[data-v-23db2c2c] h4{font-size:var(--text-title-large);line-height:var(--text-title-large--line-height);color:var(--color-on-surface);margin:.75em 0 .25em;font-weight:600}.m3-markdown[data-v-23db2c2c] p{margin:.5em 0}.m3-markdown[data-v-23db2c2c] a{color:var(--color-primary);text-underline-offset:2px;text-decoration:underline}.m3-markdown[data-v-23db2c2c] a:hover{opacity:.8}.m3-markdown[data-v-23db2c2c] strong{color:var(--color-on-surface);font-weight:600}.m3-markdown[data-v-23db2c2c] em{font-style:italic}.m3-markdown[data-v-23db2c2c] ul{margin:.5em 0;padding-left:1.5em;list-style-type:disc}.m3-markdown[data-v-23db2c2c] ol{margin:.5em 0;padding-left:1.5em;list-style-type:decimal}.m3-markdown[data-v-23db2c2c] li{margin:.25em 0}.m3-markdown[data-v-23db2c2c] li::marker{color:var(--color-on-surface-variant)}.m3-markdown[data-v-23db2c2c] blockquote{border-left:3px solid var(--color-primary);background:var(--color-surface-container);color:var(--color-on-surface-variant);border-radius:0 8px 8px 0;margin:.75em 0;padding:.5em 1em}.m3-markdown[data-v-23db2c2c] code{background:var(--color-surface-container-highest);color:var(--color-primary);border-radius:4px;padding:.15em .4em;font-family:Roboto Mono,Fira Code,Consolas,monospace;font-size:.875em}.m3-markdown[data-v-23db2c2c] pre{background:var(--color-surface-container-highest);border:1px solid var(--color-outline-variant);border-radius:12px;margin:.75em 0;padding:1em;overflow-x:auto}.m3-markdown[data-v-23db2c2c] pre code{color:var(--color-on-surface);background:0 0;padding:0;font-size:.8125rem;line-height:1.6}.m3-markdown[data-v-23db2c2c] .hljs-keyword,.m3-markdown[data-v-23db2c2c] .hljs-selector-tag,.m3-markdown[data-v-23db2c2c] .hljs-built_in,.m3-markdown[data-v-23db2c2c] .hljs-tag .hljs-keyword{color:var(--color-primary)}.m3-markdown[data-v-23db2c2c] .hljs-string,.m3-markdown[data-v-23db2c2c] .hljs-regexp,.m3-markdown[data-v-23db2c2c] .hljs-template-variable{color:var(--color-tertiary)}.m3-markdown[data-v-23db2c2c] .hljs-number,.m3-markdown[data-v-23db2c2c] .hljs-literal{color:var(--color-error)}.m3-markdown[data-v-23db2c2c] .hljs-title.function_,.m3-markdown[data-v-23db2c2c] .hljs-title.function_>.hljs-keyword{color:var(--color-secondary);font-weight:500}.m3-markdown[data-v-23db2c2c] .hljs-type,.m3-markdown[data-v-23db2c2c] .hljs-title.class_{color:var(--color-primary);font-style:italic}.m3-markdown[data-v-23db2c2c] .hljs-comment,.m3-markdown[data-v-23db2c2c] .hljs-quote{color:var(--color-outline);font-style:italic}.m3-markdown[data-v-23db2c2c] .hljs-attr,.m3-markdown[data-v-23db2c2c] .hljs-attribute{color:var(--color-tertiary)}.m3-markdown[data-v-23db2c2c] .hljs-tag{color:var(--color-on-surface-variant)}.m3-markdown[data-v-23db2c2c] .hljs-name{color:var(--color-primary)}.m3-markdown[data-v-23db2c2c] .hljs-punctuation,.m3-markdown[data-v-23db2c2c] .hljs-operator,.m3-markdown[data-v-23db2c2c] .hljs-meta,.m3-markdown[data-v-23db2c2c] .hljs-meta .hljs-keyword{color:var(--color-on-surface-variant)}.m3-markdown[data-v-23db2c2c] .hljs-variable,.m3-markdown[data-v-23db2c2c] .hljs-property,.m3-markdown[data-v-23db2c2c] .hljs-symbol,.m3-markdown[data-v-23db2c2c] .hljs-params{color:var(--color-on-surface)}.m3-markdown[data-v-23db2c2c] .m3-code-block{position:relative}.m3-markdown[data-v-23db2c2c] .m3-code-copy{background:var(--color-surface-container);width:28px;height:28px;color:var(--color-on-surface-variant);cursor:pointer;opacity:0;z-index:1;border:none;border-radius:6px;justify-content:center;align-items:center;transition:opacity .15s;display:flex;position:absolute;top:8px;right:8px}.m3-markdown[data-v-23db2c2c] .m3-code-block:hover .m3-code-copy{opacity:1}.m3-markdown[data-v-23db2c2c] .m3-code-copy:hover{background:var(--color-surface-container-high);color:var(--color-on-surface)}.m3-markdown[data-v-23db2c2c] .m3-code-line{display:block}.m3-markdown[data-v-23db2c2c] .m3-line-hl{background:color-mix(in srgb, var(--color-primary) 8%, transparent);border-left:2px solid color-mix(in srgb, var(--color-primary) 40%, transparent);margin:0 -1em;padding:0 1em 0 calc(1em - 2px)}.m3-markdown[data-v-23db2c2c] hr{border:none;border-top:1px solid var(--color-outline-variant);margin:1.5em 0}.m3-markdown[data-v-23db2c2c] table{border-collapse:collapse;width:100%;margin:.75em 0}.m3-markdown[data-v-23db2c2c] th{background:var(--color-surface-container);text-align:left;border-bottom:2px solid var(--color-outline-variant);font-weight:600;font-size:var(--text-label-large);color:var(--color-on-surface);padding:.5em .75em}.m3-markdown[data-v-23db2c2c] td{border-bottom:1px solid var(--color-outline-variant);padding:.5em .75em}.m3-markdown[data-v-23db2c2c] img{border-radius:12px;max-width:100%;height:auto;margin:.5em 0}.rte-content[data-v-e6829e5c] .tiptap{min-height:inherit;outline:none}.rte-content[data-v-e6829e5c] .tiptap p.is-editor-empty:first-child:before{content:attr(data-placeholder);float:left;color:var(--color-on-surface-variant);opacity:.5;pointer-events:none;height:0}.rte-content[data-v-e6829e5c] h1{font-size:var(--text-headline-large);line-height:var(--text-headline-large--line-height);margin:.75em 0 .25em;font-weight:600}.rte-content[data-v-e6829e5c] h2{font-size:var(--text-headline-medium);line-height:var(--text-headline-medium--line-height);margin:.75em 0 .25em;font-weight:600}.rte-content[data-v-e6829e5c] h3{font-size:var(--text-headline-small);line-height:var(--text-headline-small--line-height);margin:.75em 0 .25em;font-weight:600}.rte-content[data-v-e6829e5c] p{margin:.5em 0}.rte-content[data-v-e6829e5c] ul{margin:.5em 0;padding-left:1.5em;list-style-type:disc}.rte-content[data-v-e6829e5c] ol{margin:.5em 0;padding-left:1.5em;list-style-type:decimal}.rte-content[data-v-e6829e5c] blockquote{border-left:3px solid var(--color-primary);color:var(--color-on-surface-variant);margin:.5em 0;padding-left:1em}.rte-content[data-v-e6829e5c] code{background:var(--color-surface-container-highest);border-radius:4px;padding:.15em .4em;font-size:.875em}.rte-content[data-v-e6829e5c] pre{background:var(--color-surface-container-highest);border-radius:8px;margin:.5em 0;padding:1em;overflow-x:auto}.rte-content[data-v-e6829e5c] pre code{background:0 0;padding:0}.rte-content[data-v-e6829e5c] a{color:var(--color-primary);text-decoration:underline}.rte-content[data-v-e6829e5c] mark{background:var(--color-tertiary-container);color:var(--color-on-tertiary-container);border-radius:2px;padding:.1em .2em}.rte-content[data-v-e6829e5c] img{border-radius:8px;max-width:100%;height:auto;margin:.5em 0}
2
2
  /*$vite$:1*/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m3ui-vue/m3ui-vue",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Material 3 component library for Vue 3 + Tailwind CSS v4",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, ref, useId, onMounted, onUnmounted, watch, nextTick } from 'vue'
3
3
  import MIcon from './MIcon.vue'
4
+ import MIconButton from './MIconButton.vue'
4
5
  import { useFieldBg } from '../composables/useFieldBg'
5
6
  import { useLocale } from '../composables/useLocale'
6
7
  import type { SelectOption } from './MSelect.vue'
@@ -12,6 +13,7 @@ const props = withDefaults(
12
13
  label?: string
13
14
  placeholder?: string
14
15
  variant?: 'filled' | 'outlined'
16
+ mode?: 'docked' | 'modal'
15
17
  disabled?: boolean
16
18
  error?: string
17
19
  hint?: string
@@ -24,6 +26,7 @@ const props = withDefaults(
24
26
  {
25
27
  modelValue: undefined,
26
28
  variant: 'filled',
29
+ mode: 'docked',
27
30
  disabled: false,
28
31
  required: false,
29
32
  clearable: false,
@@ -35,6 +38,8 @@ const emit = defineEmits<{ 'update:modelValue': [unknown] }>()
35
38
  const locale = useLocale()
36
39
  const id = useId()
37
40
  const open = ref(false)
41
+ const modalOpen = ref(false)
42
+ const modalSearch = ref('')
38
43
  const search = ref('')
39
44
  const highlightIndex = ref(-1)
40
45
  const fieldEl = ref<HTMLElement | null>(null)
@@ -75,8 +80,19 @@ function computeDropPos() {
75
80
  }
76
81
  }
77
82
 
83
+ const modalFilteredOptions = computed(() => {
84
+ if (!modalSearch.value) return props.options
85
+ const q = modalSearch.value.toLowerCase()
86
+ return props.options.filter((o) => o.label.toLowerCase().includes(q))
87
+ })
88
+
78
89
  function openDropdown() {
79
90
  if (props.disabled || open.value) return
91
+ if (props.mode === 'modal') {
92
+ modalOpen.value = true
93
+ modalSearch.value = ''
94
+ return
95
+ }
80
96
  computeDropPos()
81
97
  open.value = true
82
98
  highlightIndex.value = -1
@@ -84,7 +100,9 @@ function openDropdown() {
84
100
 
85
101
  function closeDropdown() {
86
102
  open.value = false
103
+ modalOpen.value = false
87
104
  search.value = ''
105
+ modalSearch.value = ''
88
106
  highlightIndex.value = -1
89
107
  }
90
108
 
@@ -95,6 +113,10 @@ function select(opt: SelectOption) {
95
113
  nextTick(() => inputEl.value?.blur())
96
114
  }
97
115
 
116
+ watch(modalOpen, (v) => {
117
+ document.body.style.overflow = v ? 'hidden' : ''
118
+ })
119
+
98
120
  function onInputFocus() {
99
121
  search.value = ''
100
122
  openDropdown()
@@ -114,23 +136,15 @@ function onInput(e: Event) {
114
136
  }
115
137
 
116
138
  function onOutsideClick(e: MouseEvent) {
139
+ if (modalOpen.value) return
117
140
  const t = e.target as Node
118
141
  if (!fieldEl.value?.contains(t) && !dropdownEl.value?.contains(t)) closeDropdown()
119
142
  }
120
143
 
121
144
  function onScroll(e: Event) {
122
145
  if (!open.value) return
123
- // Scrolling inside the dropdown list itself -- do nothing
124
146
  if (dropdownEl.value?.contains(e.target as Node)) return
125
- // Recompute position to track the trigger element as the page scrolls
126
- if (!fieldEl.value) return
127
- const rect = fieldEl.value.getBoundingClientRect()
128
- // Only close if the trigger has scrolled completely out of the viewport
129
- if (rect.bottom < 0 || rect.top > window.innerHeight) {
130
- closeDropdown()
131
- return
132
- }
133
- computeDropPos()
147
+ closeDropdown()
134
148
  }
135
149
 
136
150
  function onKeydown(e: KeyboardEvent) {
@@ -189,6 +203,7 @@ onMounted(() => {
189
203
  onUnmounted(() => {
190
204
  document.removeEventListener('mousedown', onOutsideClick)
191
205
  window.removeEventListener('scroll', onScroll, true)
206
+ document.body.style.overflow = ''
192
207
  })
193
208
 
194
209
  // Recompute dropdown position when filtered options change while open
@@ -311,9 +326,10 @@ const labelClasses = computed(() => {
311
326
  <!-- Arrow icon -->
312
327
  <div class="pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 flex h-6 items-center">
313
328
  <MIcon
314
- :name="open ? 'arrow_drop_up' : 'arrow_drop_down'"
329
+ name="arrow_drop_down"
315
330
  :size="24"
316
331
  class="text-on-surface-variant transition-transform duration-200"
332
+ :class="open || modalOpen ? 'rotate-180' : ''"
317
333
  />
318
334
  </div>
319
335
  </div>
@@ -322,7 +338,7 @@ const labelClasses = computed(() => {
322
338
  <p v-else-if="hint" class="px-4 text-body-small text-on-surface-variant">{{ hint }}</p>
323
339
  </div>
324
340
 
325
- <!-- Dropdown teleported to body to escape overflow clipping -->
341
+ <!-- Docked dropdown -->
326
342
  <Teleport to="body">
327
343
  <Transition
328
344
  enter-active-class="transition-[opacity,transform] duration-150"
@@ -333,7 +349,7 @@ const labelClasses = computed(() => {
333
349
  leave-to-class="opacity-0 -translate-y-1 scale-[0.98]"
334
350
  >
335
351
  <div
336
- v-if="open"
352
+ v-if="open && mode === 'docked'"
337
353
  ref="dropdownEl"
338
354
  class="fixed z-500 max-h-60 overflow-auto rounded-sm bg-surface-container py-1 shadow-elevation-2"
339
355
  :style="dropPos"
@@ -369,5 +385,84 @@ const labelClasses = computed(() => {
369
385
  </p>
370
386
  </div>
371
387
  </Transition>
388
+
389
+ <!-- Modal -->
390
+ <Transition name="m3-ac-modal">
391
+ <div
392
+ v-if="modalOpen && mode === 'modal'"
393
+ class="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4"
394
+ @click.self="closeDropdown"
395
+ >
396
+ <div class="ac-modal-box flex max-h-[80vh] w-full max-w-sm flex-col overflow-hidden rounded-[28px] bg-surface-container-high shadow-elevation-3">
397
+ <div class="flex items-center justify-between px-6 pt-6 pb-4">
398
+ <h2 class="text-headline-small text-on-surface">{{ label || placeholder }}</h2>
399
+ <MIconButton icon="close" :label="locale.close" @click="closeDropdown" />
400
+ </div>
401
+
402
+ <div class="px-6 pb-3">
403
+ <div class="flex items-center gap-2 rounded-full bg-surface-container-highest px-3 py-2">
404
+ <MIcon name="search" :size="16" class="shrink-0 text-on-surface-variant" />
405
+ <input
406
+ v-model="modalSearch"
407
+ type="text"
408
+ :placeholder="locale.search"
409
+ class="w-full bg-transparent text-body-medium text-on-surface outline-none placeholder:text-on-surface-variant"
410
+ />
411
+ </div>
412
+ </div>
413
+
414
+ <div class="h-px bg-outline-variant" />
415
+
416
+ <div class="flex-1 overflow-y-auto py-2">
417
+ <div
418
+ v-for="(opt, i) in modalFilteredOptions"
419
+ :key="i"
420
+ class="flex cursor-pointer items-center gap-4 px-6 py-3.5 text-body-large transition-colors"
421
+ :class="[
422
+ opt.disabled
423
+ ? 'cursor-not-allowed opacity-38 text-on-surface'
424
+ : 'text-on-surface hover:bg-on-surface/8',
425
+ eq(opt.value, modelValue) ? 'bg-primary/8' : '',
426
+ ]"
427
+ @click="select(opt)"
428
+ >
429
+ <MIcon
430
+ :name="eq(opt.value, modelValue) ? 'radio_button_checked' : 'radio_button_unchecked'"
431
+ :size="20"
432
+ :class="eq(opt.value, modelValue) ? 'text-primary' : 'text-on-surface-variant'"
433
+ />
434
+ <span :class="eq(opt.value, modelValue) ? 'text-primary font-medium' : ''">
435
+ {{ opt.label }}
436
+ </span>
437
+ </div>
438
+ <p
439
+ v-if="!modalFilteredOptions.length"
440
+ class="px-6 py-4 text-center text-body-medium text-on-surface-variant"
441
+ >
442
+ {{ resolvedNoResultsText }}
443
+ </p>
444
+ </div>
445
+ </div>
446
+ </div>
447
+ </Transition>
372
448
  </Teleport>
373
449
  </template>
450
+
451
+ <style scoped>
452
+ .m3-ac-modal-enter-active,
453
+ .m3-ac-modal-leave-active {
454
+ transition: opacity 0.15s ease;
455
+ }
456
+ .m3-ac-modal-enter-from,
457
+ .m3-ac-modal-leave-to {
458
+ opacity: 0;
459
+ }
460
+ .m3-ac-modal-enter-active .ac-modal-box,
461
+ .m3-ac-modal-leave-active .ac-modal-box {
462
+ transition: transform 0.15s ease;
463
+ }
464
+ .m3-ac-modal-enter-from .ac-modal-box,
465
+ .m3-ac-modal-leave-to .ac-modal-box {
466
+ transform: scale(0.95);
467
+ }
468
+ </style>
@@ -19,6 +19,8 @@ const props = withDefaults(
19
19
  disabled?: boolean
20
20
  loading?: boolean
21
21
  icon?: string
22
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
23
+ shape?: 'rounded' | 'squared'
22
24
  to?: string | Record<string, any>
23
25
  }>(),
24
26
  {
@@ -27,6 +29,8 @@ const props = withDefaults(
27
29
  type: 'button',
28
30
  disabled: false,
29
31
  loading: false,
32
+ size: 'sm',
33
+ shape: 'rounded',
30
34
  },
31
35
  )
32
36
 
@@ -48,39 +52,57 @@ const customStyle = computed(() => {
48
52
 
49
53
  const isError = computed(() => props.color === 'error')
50
54
 
51
- // State-layer overlay: before: pseudo-element uses currentColor (the button's text color)
52
- // so it's always the correct M3 state-layer color for every variant automatically.
53
55
  const base =
54
- 'relative inline-flex items-center justify-center gap-2 h-10 rounded-full text-label-large font-medium ' +
56
+ 'relative inline-flex items-center justify-center gap-2 font-medium ' +
55
57
  'whitespace-nowrap overflow-hidden transition-[box-shadow,background-color,color] duration-150 select-none cursor-pointer ' +
56
58
  'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:shadow-none ' +
57
59
  "before:content-[''] before:pointer-events-none before:absolute before:inset-0 " +
58
60
  'before:bg-current before:opacity-0 before:transition-opacity before:duration-150 ' +
59
61
  'enabled:hover:before:opacity-[0.08] enabled:active:before:opacity-[0.12]'
60
62
 
63
+ const shapeClass = computed(() => props.shape === 'squared' ? 'rounded-md' : 'rounded-full')
64
+
65
+ const sizeMap = {
66
+ xs: { h: 'h-8', text: 'text-label-medium', icon: 16, spinner: 14, px: 'px-4', pxIcon: 'pl-3 pr-4', pxText: 'px-2' },
67
+ sm: { h: 'h-10', text: 'text-label-large', icon: 20, spinner: 16, px: 'px-6', pxIcon: 'pl-4 pr-6', pxText: 'px-3' },
68
+ md: { h: 'h-14', text: 'text-title-medium', icon: 20, spinner: 18, px: 'px-6', pxIcon: 'pl-5 pr-6', pxText: 'px-3' },
69
+ lg: { h: 'h-16', text: 'text-title-large', icon: 22, spinner: 20, px: 'px-7', pxIcon: 'pl-6 pr-7', pxText: 'px-4' },
70
+ xl: { h: 'h-20', text: 'text-headline-small', icon: 24, spinner: 22, px: 'px-8', pxIcon: 'pl-7 pr-8', pxText: 'px-4' },
71
+ }
72
+
73
+ const s = computed(() => sizeMap[props.size] ?? sizeMap.sm)
74
+ const sizeClasses = computed(() => `${s.value.h} ${s.value.text}`)
75
+ const iconSize = computed(() => s.value.icon)
76
+ const spinnerSize = computed(() => s.value.spinner)
77
+
78
+ const px = computed(() => {
79
+ if (props.variant === 'text') return s.value.pxText
80
+ return (props.icon || props.loading) ? s.value.pxIcon : s.value.px
81
+ })
82
+
61
83
  const variantClasses = computed(() => {
62
84
  const err = isError.value
63
85
  switch (props.variant) {
64
86
  case 'filled':
65
87
  return err
66
- ? 'px-6 bg-error text-on-error enabled:hover:shadow-elevation-1 enabled:active:shadow-none'
67
- : 'px-6 bg-primary text-on-primary enabled:hover:shadow-elevation-1 enabled:active:shadow-none'
88
+ ? 'bg-error text-on-error enabled:hover:shadow-elevation-1 enabled:active:shadow-none'
89
+ : 'bg-primary text-on-primary enabled:hover:shadow-elevation-1 enabled:active:shadow-none'
68
90
  case 'tonal':
69
91
  return err
70
- ? 'px-6 bg-error-container text-on-error-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'
71
- : 'px-6 bg-secondary-container text-on-secondary-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'
92
+ ? 'bg-error-container text-on-error-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'
93
+ : 'bg-secondary-container text-on-secondary-container enabled:hover:shadow-elevation-1 enabled:active:shadow-none'
72
94
  case 'elevated':
73
95
  return err
74
- ? 'px-6 bg-surface-container-low text-error shadow-elevation-1 enabled:hover:shadow-elevation-2'
75
- : 'px-6 bg-surface-container-low text-primary shadow-elevation-1 enabled:hover:shadow-elevation-2'
96
+ ? 'bg-surface-container-low text-error shadow-elevation-1 enabled:hover:shadow-elevation-2'
97
+ : 'bg-surface-container-low text-primary shadow-elevation-1 enabled:hover:shadow-elevation-2'
76
98
  case 'outlined':
77
99
  return err
78
- ? 'px-6 border border-error text-error'
79
- : 'px-6 border border-outline text-primary'
100
+ ? 'border border-error text-error'
101
+ : 'border border-outline text-primary'
80
102
  case 'text':
81
103
  return err
82
- ? 'px-3 text-error'
83
- : 'px-3 text-primary'
104
+ ? 'text-error'
105
+ : 'text-primary'
84
106
  default:
85
107
  return ''
86
108
  }
@@ -105,12 +127,12 @@ function createRipple(event: PointerEvent) {
105
127
  :to="to || undefined"
106
128
  :type="to ? undefined : type"
107
129
  :disabled="disabled || loading"
108
- :class="[base, variantClasses]"
130
+ :class="[base, shapeClass, sizeClasses, px, variantClasses]"
109
131
  :style="customStyle"
110
132
  @pointerdown="createRipple"
111
133
  >
112
- <MSpinner v-if="loading" :size="18" />
113
- <MIcon v-else-if="icon" :name="icon" :size="20" />
134
+ <MSpinner v-if="loading" :size="spinnerSize" />
135
+ <MIcon v-else-if="icon" :name="icon" :size="iconSize" />
114
136
  <slot />
115
137
  </component>
116
138
  </template>
@@ -0,0 +1,158 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import MIcon from './MIcon.vue'
4
+
5
+ export interface ButtonGroupOption {
6
+ value: unknown
7
+ label?: string
8
+ icon?: string
9
+ disabled?: boolean
10
+ }
11
+
12
+ const props = withDefaults(defineProps<{
13
+ modelValue: unknown
14
+ options: ButtonGroupOption[]
15
+ variant?: 'standard' | 'connected'
16
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
17
+ multiSelect?: boolean
18
+ selectionRequired?: boolean
19
+ color?: 'primary' | 'secondary' | 'tertiary'
20
+ }>(), {
21
+ variant: 'standard',
22
+ size: 'sm',
23
+ multiSelect: false,
24
+ selectionRequired: false,
25
+ color: 'primary',
26
+ })
27
+
28
+ const emit = defineEmits<{ 'update:modelValue': [unknown] }>()
29
+
30
+ function eq(a: unknown, b: unknown): boolean {
31
+ if (a === b) return true
32
+ if (typeof a !== 'object' || typeof b !== 'object' || a == null || b == null) return false
33
+ return JSON.stringify(a) === JSON.stringify(b)
34
+ }
35
+
36
+ function isSelected(value: unknown) {
37
+ if (props.modelValue == null) return false
38
+ if (Array.isArray(props.modelValue)) return props.modelValue.some(v => eq(v, value))
39
+ return eq(props.modelValue, value)
40
+ }
41
+
42
+ function toggle(opt: ButtonGroupOption) {
43
+ if (opt.disabled) return
44
+ if (props.multiSelect) {
45
+ const arr = Array.isArray(props.modelValue) ? [...props.modelValue] : props.modelValue != null ? [props.modelValue] : []
46
+ const idx = arr.findIndex(v => eq(v, opt.value))
47
+ if (idx >= 0) {
48
+ if (props.selectionRequired && arr.length <= 1) return
49
+ arr.splice(idx, 1)
50
+ } else {
51
+ arr.push(opt.value)
52
+ }
53
+ emit('update:modelValue', arr)
54
+ } else {
55
+ if (isSelected(opt.value) && !props.selectionRequired) {
56
+ emit('update:modelValue', null)
57
+ } else {
58
+ emit('update:modelValue', opt.value)
59
+ }
60
+ }
61
+ }
62
+
63
+ const sizeMap = {
64
+ xs: { h: 'h-8', px: 'px-3', text: 'text-label-medium', icon: 16, check: 14 },
65
+ sm: { h: 'h-10', px: 'px-4', text: 'text-label-large', icon: 18, check: 16 },
66
+ md: { h: 'h-14', px: 'px-6', text: 'text-title-medium', icon: 20, check: 18 },
67
+ lg: { h: 'h-16', px: 'px-7', text: 'text-title-large', icon: 22, check: 20 },
68
+ xl: { h: 'h-20', px: 'px-8', text: 'text-headline-small', icon: 24, check: 22 },
69
+ }
70
+
71
+ const s = computed(() => sizeMap[props.size] ?? sizeMap.sm)
72
+
73
+ const fullRadius = computed(() => {
74
+ const hMap = { xs: '16px', sm: '20px', md: '28px', lg: '32px', xl: '40px' }
75
+ return hMap[props.size] ?? '20px'
76
+ })
77
+
78
+ const transitionMs = computed(() => {
79
+ const msMap = { xs: 350, sm: 300, md: 250, lg: 200, xl: 180 }
80
+ return msMap[props.size] ?? 250
81
+ })
82
+
83
+ const selectedColors = computed(() => {
84
+ const map = {
85
+ primary: 'bg-primary text-on-primary',
86
+ secondary: 'bg-secondary text-on-secondary',
87
+ tertiary: 'bg-tertiary text-on-tertiary',
88
+ }
89
+ return map[props.color] ?? map.primary
90
+ })
91
+
92
+ const unselectedColors = 'bg-surface-container-highest text-on-surface'
93
+
94
+ function createRipple(event: PointerEvent) {
95
+ const button = event.currentTarget as HTMLElement
96
+ const rect = button.getBoundingClientRect()
97
+ const d = Math.max(rect.width, rect.height) * 2
98
+ const el = document.createElement('span')
99
+ el.className = 'm3-ripple'
100
+ 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`
101
+ button.appendChild(el)
102
+ el.addEventListener('animationend', () => el.remove(), { once: true })
103
+ }
104
+
105
+ function btnStyle(i: number, selected: boolean) {
106
+ const count = props.options.length
107
+ const full = fullRadius.value
108
+ const inner = '6px'
109
+ let tl: string, tr: string, br: string, bl: string
110
+ if (props.variant === 'standard' || selected) {
111
+ tl = tr = br = bl = full
112
+ } else {
113
+ tl = bl = i === 0 ? full : inner
114
+ tr = br = i === count - 1 ? full : inner
115
+ }
116
+ return {
117
+ borderTopLeftRadius: tl,
118
+ borderTopRightRadius: tr,
119
+ borderBottomRightRadius: br,
120
+ borderBottomLeftRadius: bl,
121
+ transition: `border-top-left-radius ${transitionMs.value}ms ease, border-top-right-radius ${transitionMs.value}ms ease, border-bottom-right-radius ${transitionMs.value}ms ease, border-bottom-left-radius ${transitionMs.value}ms ease, background-color ${transitionMs.value}ms ease, color ${transitionMs.value}ms ease`,
122
+ }
123
+ }
124
+ </script>
125
+
126
+ <template>
127
+ <div
128
+ class="inline-flex"
129
+ :class="variant === 'standard' ? 'gap-1.5' : 'gap-0.5'"
130
+ role="group"
131
+ >
132
+ <button
133
+ v-for="(opt, i) in options"
134
+ :key="String(opt.value)"
135
+ type="button"
136
+ class="btn-group-item relative inline-flex items-center justify-center gap-2 overflow-hidden font-medium"
137
+ :class="[
138
+ s.h, s.px, s.text,
139
+ opt.disabled ? 'cursor-not-allowed opacity-[0.38]' : 'cursor-pointer',
140
+ isSelected(opt.value) ? selectedColors : unselectedColors,
141
+ ]"
142
+ :style="btnStyle(i, isSelected(opt.value))"
143
+ :disabled="opt.disabled"
144
+ :aria-pressed="isSelected(opt.value)"
145
+ @pointerdown="createRipple"
146
+ @click="toggle(opt)"
147
+ >
148
+ <MIcon
149
+ v-if="isSelected(opt.value)"
150
+ name="check"
151
+ :size="s.check"
152
+ />
153
+ <MIcon v-else-if="opt.icon" :name="opt.icon" :size="s.icon" />
154
+ <span v-if="opt.label">{{ opt.label }}</span>
155
+ </button>
156
+ </div>
157
+ </template>
158
+