@m3ui-vue/m3ui-vue 0.1.11 → 0.2.1

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 (98) hide show
  1. package/dist/{MMenuItem-_n5OG5MT.js → MMenuItem-DpoEsH91.js} +215 -122
  2. package/dist/MMenuItem-DpoEsH91.js.map +1 -0
  3. package/dist/components/MAlert.vue.d.ts +1 -0
  4. package/dist/components/MButton.vue.d.ts +1 -1
  5. package/dist/components/MCalendar.vue.d.ts +3 -0
  6. package/dist/components/MCarousel.vue.d.ts +36 -0
  7. package/dist/components/MChip.vue.d.ts +3 -3
  8. package/dist/components/MCommandPalette.vue.d.ts +3 -2
  9. package/dist/components/MConfirmDialog.vue.d.ts +0 -2
  10. package/dist/components/MDataTable.vue.d.ts +25 -2
  11. package/dist/components/MDatePicker.vue.d.ts +2 -0
  12. package/dist/components/MDateRangePicker.vue.d.ts +5 -0
  13. package/dist/components/MDialog.vue.d.ts +1 -0
  14. package/dist/components/MFab.vue.d.ts +1 -1
  15. package/dist/components/MFileUpload.vue.d.ts +15 -1
  16. package/dist/components/MFlex.vue.d.ts +1 -1
  17. package/dist/components/MInfiniteScroll.vue.d.ts +7 -5
  18. package/dist/components/MMaskField.vue.d.ts +24 -0
  19. package/dist/components/MMultiSelect.vue.d.ts +20 -6
  20. package/dist/components/MNavigationDrawer.vue.d.ts +9 -3
  21. package/dist/components/MNumberField.vue.d.ts +27 -0
  22. package/dist/components/MRichTextEditor.vue.d.ts +28 -1
  23. package/dist/components/MScheduler.vue.d.ts +5 -0
  24. package/dist/components/MSelect.vue.d.ts +12 -9
  25. package/dist/components/MSnackbar.vue.d.ts +4 -1
  26. package/dist/components/MSpinner.vue.d.ts +1 -0
  27. package/dist/components/MSplitter.vue.d.ts +1 -1
  28. package/dist/components/MSpotlightSearch.vue.d.ts +3 -2
  29. package/dist/components/MStack.vue.d.ts +1 -1
  30. package/dist/components/MTable.vue.d.ts +3 -2
  31. package/dist/components/MTextField.vue.d.ts +2 -5
  32. package/dist/components/MTimePicker.vue.d.ts +1 -0
  33. package/dist/components/MTour.vue.d.ts +3 -0
  34. package/dist/components/MTransferList.vue.d.ts +19 -3
  35. package/dist/components/MTree.vue.d.ts +1 -1
  36. package/dist/components/_MDrawerItemList.vue.d.ts +57 -0
  37. package/dist/composables/useLocale.d.ts +74 -0
  38. package/dist/index.d.ts +10 -1
  39. package/dist/locales/de.d.ts +2 -0
  40. package/dist/locales/es.d.ts +2 -0
  41. package/dist/locales/fr.d.ts +2 -0
  42. package/dist/locales/index.d.ts +8 -0
  43. package/dist/locales/ja.d.ts +2 -0
  44. package/dist/locales/ko.d.ts +2 -0
  45. package/dist/locales/pt.d.ts +2 -0
  46. package/dist/locales/zh.d.ts +2 -0
  47. package/dist/m3ui-vue.css +1 -1
  48. package/dist/m3ui.js +3278 -2489
  49. package/dist/m3ui.js.map +1 -1
  50. package/dist/plugin.d.ts +3 -1
  51. package/dist/rich-text-editor.d.ts +1 -0
  52. package/dist/rich-text-editor.js +141 -113
  53. package/dist/rich-text-editor.js.map +1 -1
  54. package/dist/styles/palettes.css +660 -0
  55. package/dist/styles.css +1 -1
  56. package/package.json +6 -2
  57. package/src/components/MAlert.vue +5 -1
  58. package/src/components/MCalendar.vue +14 -5
  59. package/src/components/MCarousel.vue +203 -0
  60. package/src/components/MCommandPalette.vue +11 -7
  61. package/src/components/MConfirmDialog.vue +6 -5
  62. package/src/components/MDataTable.vue +78 -14
  63. package/src/components/MDatePicker.vue +11 -4
  64. package/src/components/MDateRangePicker.vue +15 -5
  65. package/src/components/MDialog.vue +5 -1
  66. package/src/components/MFileUpload.vue +22 -10
  67. package/src/components/MInfiniteScroll.vue +14 -9
  68. package/src/components/MMaskField.vue +198 -0
  69. package/src/components/MMultiSelect.vue +53 -24
  70. package/src/components/MNavigationDrawer.vue +282 -107
  71. package/src/components/MNumberField.vue +176 -0
  72. package/src/components/MRichTextEditor.vue +95 -34
  73. package/src/components/MScheduler.vue +12 -4
  74. package/src/components/MSelect.vue +41 -14
  75. package/src/components/MSnackbar.vue +8 -1
  76. package/src/components/MSpinner.vue +5 -1
  77. package/src/components/MSpotlightSearch.vue +11 -7
  78. package/src/components/MTable.vue +8 -4
  79. package/src/components/MTextField.vue +19 -10
  80. package/src/components/MTimePicker.vue +5 -1
  81. package/src/components/MTour.vue +12 -9
  82. package/src/components/MTransferList.vue +30 -15
  83. package/src/components/_MDrawerItemList.vue +105 -0
  84. package/src/composables/useColorPalette.ts +30 -20
  85. package/src/composables/useLocale.ts +181 -0
  86. package/src/index.ts +10 -1
  87. package/src/locales/de.ts +93 -0
  88. package/src/locales/es.ts +93 -0
  89. package/src/locales/fr.ts +93 -0
  90. package/src/locales/index.ts +8 -0
  91. package/src/locales/ja.ts +93 -0
  92. package/src/locales/ko.ts +93 -0
  93. package/src/locales/pt.ts +93 -0
  94. package/src/locales/zh.ts +93 -0
  95. package/src/plugin.ts +7 -1
  96. package/src/rich-text-editor.ts +1 -0
  97. package/src/styles/palettes.css +660 -0
  98. package/dist/MMenuItem-_n5OG5MT.js.map +0 -1
package/dist/plugin.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import type { App } from 'vue';
2
2
  import type { Palette } from './composables/useColorPalette';
3
+ import type { M3Locale } from './composables/useLocale';
3
4
  export interface M3UIOptions {
4
5
  palette?: string;
5
6
  customPalettes?: Palette[];
7
+ locale?: Partial<M3Locale>;
6
8
  }
7
9
  export declare function createM3UI(options?: M3UIOptions): {
8
- install(_app: App): void;
10
+ install(app: App): void;
9
11
  };
@@ -1 +1,2 @@
1
1
  export { default as MRichTextEditor } from './components/MRichTextEditor.vue';
2
+ export type { RichTextEditorLabels } from './components/MRichTextEditor.vue';
@@ -1,32 +1,60 @@
1
- import { i as e, n as t, o as n, r, t as i } from "./MMenuItem-_n5OG5MT.js";
2
- import { t as a } from "./MIcon-CaEooCmZ.js";
3
- import { t as o } from "./_plugin-vue_export-helper-B3ysoDQm.js";
4
- import { Fragment as s, computed as c, createCommentVNode as l, createElementBlock as u, createElementVNode as d, createTextVNode as f, createVNode as p, defineComponent as m, normalizeClass as h, normalizeStyle as g, onBeforeUnmount as _, onMounted as v, openBlock as y, ref as b, renderList as x, shallowRef as S, toDisplayString as C, watch as w, withCtx as T, withKeys as E } from "vue";
1
+ import { d as e, i as t, n, o as r, r as i, t as a } from "./MMenuItem-DpoEsH91.js";
2
+ import { t as o } from "./MIcon-CaEooCmZ.js";
3
+ import { t as s } from "./_plugin-vue_export-helper-B3ysoDQm.js";
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";
5
5
  //#region src/components/MRichTextEditor.vue?vue&type=script&setup=true&lang.ts
6
- var D = {
6
+ var O = {
7
7
  key: 0,
8
8
  class: "flex flex-wrap items-center gap-0.5 border-b border-outline-variant bg-surface-container px-2 py-1.5"
9
- }, O = {
9
+ }, k = {
10
10
  type: "button",
11
11
  class: "flex h-8 cursor-pointer items-center gap-1 rounded px-2 text-label-large text-on-surface-variant hover:bg-on-surface/8"
12
- }, k = ["title", "onClick"], A = {
12
+ }, A = ["title", "onClick"], j = {
13
13
  key: 0,
14
14
  class: "mx-1 h-6 w-px bg-outline-variant"
15
- }, j = /*#__PURE__*/ o(/* @__PURE__ */ m({
15
+ }, M = ["title"], N = ["title"], P = /*#__PURE__*/ s(/* @__PURE__ */ h({
16
16
  __name: "MRichTextEditor",
17
17
  props: {
18
18
  modelValue: {},
19
- placeholder: { default: "Escribe aquí..." },
19
+ placeholder: {},
20
20
  disabled: {
21
21
  type: Boolean,
22
22
  default: !1
23
23
  },
24
- minHeight: { default: "200px" }
24
+ minHeight: { default: "200px" },
25
+ labels: {}
25
26
  },
26
27
  emits: ["update:modelValue"],
27
- setup(o, { emit: m }) {
28
- let j = o, M = m, N = b(!1), P = S(null), F = b(null), I = b([]);
29
- v(async () => {
28
+ setup(s, { emit: h }) {
29
+ let P = e(), F = s, I = l(() => ({
30
+ bold: P.bold,
31
+ italic: P.italic,
32
+ underline: P.underline,
33
+ strikethrough: P.strikethrough,
34
+ highlight: P.highlight,
35
+ bulletList: P.bulletList,
36
+ orderedList: P.orderedList,
37
+ blockquote: P.blockquote,
38
+ code: P.code,
39
+ alignLeft: P.alignLeft,
40
+ alignCenter: P.alignCenter,
41
+ alignRight: P.alignRight,
42
+ undo: P.undo,
43
+ redo: P.redo,
44
+ link: P.link,
45
+ image: P.image,
46
+ paragraph: P.paragraph,
47
+ heading1: P.heading1,
48
+ heading2: P.heading2,
49
+ heading3: P.heading3,
50
+ insertLink: P.insertLink,
51
+ insertImage: P.insertImage,
52
+ imageUrlLabel: P.imageUrlLabel,
53
+ cancel: P.cancel,
54
+ insert: P.insert,
55
+ ...F.labels
56
+ })), L = h, R = x(!1), z = C(null), B = x(null), V = x([]);
57
+ y(async () => {
30
58
  let [{ Editor: e }, { default: t }, { default: n }, { default: r }, { default: i }, { default: a }, { default: o }, { default: s }, { TextStyle: c }, { default: l }] = await Promise.all([
31
59
  import("@tiptap/vue-3"),
32
60
  import("@tiptap/starter-kit"),
@@ -39,9 +67,9 @@ var D = {
39
67
  import("@tiptap/extension-text-style"),
40
68
  import("@tiptap/extension-color")
41
69
  ]), u = new e({
42
- element: F.value,
43
- content: j.modelValue,
44
- editable: !j.disabled,
70
+ element: B.value,
71
+ content: F.modelValue,
72
+ editable: !F.disabled,
45
73
  extensions: [
46
74
  t,
47
75
  n,
@@ -49,41 +77,41 @@ var D = {
49
77
  i.configure({ openOnClick: !1 }),
50
78
  a,
51
79
  o.configure({ multicolor: !0 }),
52
- s.configure({ placeholder: j.placeholder }),
80
+ s.configure({ placeholder: F.placeholder ?? "Start writing..." }),
53
81
  c,
54
82
  l
55
83
  ],
56
- onUpdate: ({ editor: e }) => M("update:modelValue", e.getHTML())
84
+ onUpdate: ({ editor: e }) => L("update:modelValue", e.getHTML())
57
85
  });
58
- P.value = u, I.value = [
86
+ z.value = u, V.value = [
59
87
  [
60
88
  {
61
89
  icon: "format_bold",
62
- label: "Negrita",
90
+ label: I.value.bold,
63
91
  action: () => u.chain().focus().toggleBold().run(),
64
92
  active: () => !!u.isActive("bold")
65
93
  },
66
94
  {
67
95
  icon: "format_italic",
68
- label: "Cursiva",
96
+ label: I.value.italic,
69
97
  action: () => u.chain().focus().toggleItalic().run(),
70
98
  active: () => !!u.isActive("italic")
71
99
  },
72
100
  {
73
101
  icon: "format_underlined",
74
- label: "Subrayado",
102
+ label: I.value.underline,
75
103
  action: () => u.chain().focus().toggleUnderline().run(),
76
104
  active: () => !!u.isActive("underline")
77
105
  },
78
106
  {
79
107
  icon: "format_strikethrough",
80
- label: "Tachado",
108
+ label: I.value.strikethrough,
81
109
  action: () => u.chain().focus().toggleStrike().run(),
82
110
  active: () => !!u.isActive("strike")
83
111
  },
84
112
  {
85
113
  icon: "ink_highlighter",
86
- label: "Resaltar",
114
+ label: I.value.highlight,
87
115
  action: () => u.chain().focus().toggleHighlight().run(),
88
116
  active: () => !!u.isActive("highlight")
89
117
  }
@@ -91,25 +119,25 @@ var D = {
91
119
  [
92
120
  {
93
121
  icon: "format_list_bulleted",
94
- label: "Lista",
122
+ label: I.value.bulletList,
95
123
  action: () => u.chain().focus().toggleBulletList().run(),
96
124
  active: () => !!u.isActive("bulletList")
97
125
  },
98
126
  {
99
127
  icon: "format_list_numbered",
100
- label: "Lista numerada",
128
+ label: I.value.orderedList,
101
129
  action: () => u.chain().focus().toggleOrderedList().run(),
102
130
  active: () => !!u.isActive("orderedList")
103
131
  },
104
132
  {
105
133
  icon: "format_quote",
106
- label: "Cita",
134
+ label: I.value.blockquote,
107
135
  action: () => u.chain().focus().toggleBlockquote().run(),
108
136
  active: () => !!u.isActive("blockquote")
109
137
  },
110
138
  {
111
139
  icon: "code",
112
- label: "Código",
140
+ label: I.value.code,
113
141
  action: () => u.chain().focus().toggleCode().run(),
114
142
  active: () => !!u.isActive("code")
115
143
  }
@@ -117,171 +145,171 @@ var D = {
117
145
  [
118
146
  {
119
147
  icon: "format_align_left",
120
- label: "Izquierda",
148
+ label: I.value.alignLeft,
121
149
  action: () => u.chain().focus().setTextAlign("left").run(),
122
150
  active: () => !!u.isActive({ textAlign: "left" })
123
151
  },
124
152
  {
125
153
  icon: "format_align_center",
126
- label: "Centro",
154
+ label: I.value.alignCenter,
127
155
  action: () => u.chain().focus().setTextAlign("center").run(),
128
156
  active: () => !!u.isActive({ textAlign: "center" })
129
157
  },
130
158
  {
131
159
  icon: "format_align_right",
132
- label: "Derecha",
160
+ label: I.value.alignRight,
133
161
  action: () => u.chain().focus().setTextAlign("right").run(),
134
162
  active: () => !!u.isActive({ textAlign: "right" })
135
163
  }
136
164
  ],
137
165
  [{
138
166
  icon: "undo",
139
- label: "Deshacer",
167
+ label: I.value.undo,
140
168
  action: () => u.chain().focus().undo().run()
141
169
  }, {
142
170
  icon: "redo",
143
- label: "Rehacer",
171
+ label: I.value.redo,
144
172
  action: () => u.chain().focus().redo().run()
145
173
  }]
146
- ], _(() => u.destroy()), w(() => j.modelValue, (e) => {
174
+ ], v(() => u.destroy()), T(() => F.modelValue, (e) => {
147
175
  u.getHTML() !== e && u.commands.setContent(e);
148
- }), w(() => j.disabled, (e) => u.setEditable(!e)), N.value = !0;
176
+ }), T(() => F.disabled, (e) => u.setEditable(!e)), R.value = !0;
149
177
  });
150
- let L = b(!1), R = b(""), z = b(!1), B = b(""), V = c(() => {
151
- let e = P.value;
152
- return e ? e.isActive("heading", { level: 1 }) ? "Título 1" : e.isActive("heading", { level: 2 }) ? "Título 2" : e.isActive("heading", { level: 3 }) ? "Título 3" : "Párrafo" : "Párrafo";
178
+ let H = x(!1), U = x(""), W = x(!1), G = x(""), K = l(() => {
179
+ let e = z.value;
180
+ return e ? e.isActive("heading", { level: 1 }) ? I.value.heading1 : e.isActive("heading", { level: 2 }) ? I.value.heading2 : e.isActive("heading", { level: 3 }) ? I.value.heading3 : I.value.paragraph : I.value.paragraph;
153
181
  });
154
- function H(e) {
155
- e === 0 ? P.value?.chain().focus().setParagraph().run() : P.value?.chain().focus().toggleHeading({ level: e }).run();
182
+ function q(e) {
183
+ e === 0 ? z.value?.chain().focus().setParagraph().run() : z.value?.chain().focus().toggleHeading({ level: e }).run();
156
184
  }
157
- function U() {
158
- R.value = "", L.value = !0;
185
+ function J() {
186
+ U.value = "", H.value = !0;
159
187
  }
160
- function W() {
161
- R.value && P.value?.chain().focus().setLink({ href: R.value }).run(), L.value = !1;
188
+ function Y() {
189
+ U.value && z.value?.chain().focus().setLink({ href: U.value }).run(), H.value = !1;
162
190
  }
163
- function G() {
164
- B.value = "", z.value = !0;
191
+ function X() {
192
+ G.value = "", W.value = !0;
165
193
  }
166
- function K() {
167
- B.value && P.value?.chain().focus().setImage({ src: B.value }).run(), z.value = !1;
194
+ function Z() {
195
+ G.value && z.value?.chain().focus().setImage({ src: G.value }).run(), W.value = !1;
168
196
  }
169
- return (c, m) => (y(), u("div", { class: h(["overflow-hidden rounded-lg border transition-colors duration-150", o.disabled ? "border-outline-variant/50 opacity-60" : "border-outline-variant focus-within:border-primary"]) }, [
170
- N.value ? (y(), u("div", D, [
171
- p(t, { align: "left" }, {
172
- trigger: T(() => [d("button", O, [f(C(V.value) + " ", 1), p(a, {
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"]) }, [
198
+ R.value ? (b(), d("div", O, [
199
+ m(n, { align: "left" }, {
200
+ trigger: E(() => [f("button", k, [p(w(K.value) + " ", 1), m(o, {
173
201
  name: "arrow_drop_down",
174
202
  size: 20
175
203
  })])]),
176
- default: T(() => [
177
- p(i, { onClick: m[0] ||= (e) => H(0) }, {
178
- default: T(() => [...m[10] ||= [f("Párrafo", -1)]]),
204
+ default: E(() => [
205
+ m(a, { onClick: l[0] ||= (e) => q(0) }, {
206
+ default: E(() => [p(w(I.value.paragraph), 1)]),
179
207
  _: 1
180
208
  }),
181
- p(i, { onClick: m[1] ||= (e) => H(1) }, {
182
- default: T(() => [...m[11] ||= [f("Título 1", -1)]]),
209
+ m(a, { onClick: l[1] ||= (e) => q(1) }, {
210
+ default: E(() => [p(w(I.value.heading1), 1)]),
183
211
  _: 1
184
212
  }),
185
- p(i, { onClick: m[2] ||= (e) => H(2) }, {
186
- default: T(() => [...m[12] ||= [f("Título 2", -1)]]),
213
+ m(a, { onClick: l[2] ||= (e) => q(2) }, {
214
+ default: E(() => [p(w(I.value.heading2), 1)]),
187
215
  _: 1
188
216
  }),
189
- p(i, { onClick: m[3] ||= (e) => H(3) }, {
190
- default: T(() => [...m[13] ||= [f("Título 3", -1)]]),
217
+ m(a, { onClick: l[3] ||= (e) => q(3) }, {
218
+ default: E(() => [p(w(I.value.heading3), 1)]),
191
219
  _: 1
192
220
  })
193
221
  ]),
194
222
  _: 1
195
223
  }),
196
- m[14] ||= d("div", { class: "mx-1 h-6 w-px bg-outline-variant" }, null, -1),
197
- (y(!0), u(s, null, x(I.value, (e, t) => (y(), u(s, { key: t }, [(y(!0), u(s, null, x(e, (e) => (y(), u("button", {
224
+ l[10] ||= f("div", { class: "mx-1 h-6 w-px bg-outline-variant" }, null, -1),
225
+ (b(!0), d(c, null, S(V.value, (e, t) => (b(), d(c, { key: t }, [(b(!0), d(c, null, S(e, (e) => (b(), d("button", {
198
226
  key: e.icon,
199
227
  type: "button",
200
228
  title: e.label,
201
- class: h(["flex h-8 w-8 cursor-pointer items-center justify-center rounded transition-colors duration-100", e.active?.() ? "bg-secondary-container text-on-secondary-container" : "text-on-surface-variant hover:bg-on-surface/8"]),
229
+ class: g(["flex h-8 w-8 cursor-pointer items-center justify-center rounded transition-colors duration-100", e.active?.() ? "bg-secondary-container text-on-secondary-container" : "text-on-surface-variant hover:bg-on-surface/8"]),
202
230
  onClick: e.action
203
- }, [p(a, {
231
+ }, [m(o, {
204
232
  name: e.icon,
205
233
  size: 20
206
- }, null, 8, ["name"])], 10, k))), 128)), t < I.value.length - 1 ? (y(), u("div", A)) : l("", !0)], 64))), 128)),
207
- m[15] ||= d("div", { class: "mx-1 h-6 w-px bg-outline-variant" }, null, -1),
208
- d("button", {
234
+ }, null, 8, ["name"])], 10, A))), 128)), t < V.value.length - 1 ? (b(), d("div", j)) : u("", !0)], 64))), 128)),
235
+ l[11] ||= f("div", { class: "mx-1 h-6 w-px bg-outline-variant" }, null, -1),
236
+ f("button", {
209
237
  type: "button",
210
- title: "Enlace",
238
+ title: I.value.link,
211
239
  class: "flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8",
212
- onClick: U
213
- }, [p(a, {
240
+ onClick: J
241
+ }, [m(o, {
214
242
  name: "link",
215
243
  size: 20
216
- })]),
217
- d("button", {
244
+ })], 8, M),
245
+ f("button", {
218
246
  type: "button",
219
- title: "Imagen",
247
+ title: I.value.image,
220
248
  class: "flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8",
221
- onClick: G
222
- }, [p(a, {
249
+ onClick: X
250
+ }, [m(o, {
223
251
  name: "image",
224
252
  size: 20
225
- })])
226
- ])) : l("", !0),
227
- d("div", {
253
+ })], 8, N)
254
+ ])) : u("", !0),
255
+ f("div", {
228
256
  ref_key: "editorContainer",
229
- ref: F,
257
+ ref: B,
230
258
  class: "rte-content bg-surface px-4 py-3 text-body-large text-on-surface",
231
- style: g({ minHeight: o.minHeight })
259
+ style: _({ minHeight: s.minHeight })
232
260
  }, null, 4),
233
- p(e, {
234
- modelValue: L.value,
235
- "onUpdate:modelValue": m[6] ||= (e) => L.value = e,
236
- title: "Insertar enlace"
261
+ m(t, {
262
+ modelValue: H.value,
263
+ "onUpdate:modelValue": l[6] ||= (e) => H.value = e,
264
+ title: I.value.insertLink
237
265
  }, {
238
- actions: T(() => [p(n, {
266
+ actions: E(() => [m(r, {
239
267
  variant: "text",
240
- onClick: m[5] ||= (e) => L.value = !1
268
+ onClick: l[5] ||= (e) => H.value = !1
241
269
  }, {
242
- default: T(() => [...m[16] ||= [f("Cancelar", -1)]]),
270
+ default: E(() => [p(w(I.value.cancel), 1)]),
243
271
  _: 1
244
- }), p(n, { onClick: W }, {
245
- default: T(() => [...m[17] ||= [f("Insertar", -1)]]),
272
+ }), m(r, { onClick: Y }, {
273
+ default: E(() => [p(w(I.value.insert), 1)]),
246
274
  _: 1
247
275
  })]),
248
- default: T(() => [p(r, {
249
- modelValue: R.value,
250
- "onUpdate:modelValue": m[4] ||= (e) => R.value = e,
276
+ default: E(() => [m(i, {
277
+ modelValue: U.value,
278
+ "onUpdate:modelValue": l[4] ||= (e) => U.value = e,
251
279
  label: "URL",
252
280
  placeholder: " ",
253
- onKeydown: E(W, ["enter"])
281
+ onKeydown: D(Y, ["enter"])
254
282
  }, null, 8, ["modelValue"])]),
255
283
  _: 1
256
- }, 8, ["modelValue"]),
257
- p(e, {
258
- modelValue: z.value,
259
- "onUpdate:modelValue": m[9] ||= (e) => z.value = e,
260
- title: "Insertar imagen"
284
+ }, 8, ["modelValue", "title"]),
285
+ m(t, {
286
+ modelValue: W.value,
287
+ "onUpdate:modelValue": l[9] ||= (e) => W.value = e,
288
+ title: I.value.insertImage
261
289
  }, {
262
- actions: T(() => [p(n, {
290
+ actions: E(() => [m(r, {
263
291
  variant: "text",
264
- onClick: m[8] ||= (e) => z.value = !1
292
+ onClick: l[8] ||= (e) => W.value = !1
265
293
  }, {
266
- default: T(() => [...m[18] ||= [f("Cancelar", -1)]]),
294
+ default: E(() => [p(w(I.value.cancel), 1)]),
267
295
  _: 1
268
- }), p(n, { onClick: K }, {
269
- default: T(() => [...m[19] ||= [f("Insertar", -1)]]),
296
+ }), m(r, { onClick: Z }, {
297
+ default: E(() => [p(w(I.value.insert), 1)]),
270
298
  _: 1
271
299
  })]),
272
- default: T(() => [p(r, {
273
- modelValue: B.value,
274
- "onUpdate:modelValue": m[7] ||= (e) => B.value = e,
275
- label: "URL de la imagen",
300
+ default: E(() => [m(i, {
301
+ modelValue: G.value,
302
+ "onUpdate:modelValue": l[7] ||= (e) => G.value = e,
303
+ label: I.value.imageUrlLabel,
276
304
  placeholder: " ",
277
- onKeydown: E(K, ["enter"])
278
- }, null, 8, ["modelValue"])]),
305
+ onKeydown: D(Z, ["enter"])
306
+ }, null, 8, ["modelValue", "label"])]),
279
307
  _: 1
280
- }, 8, ["modelValue"])
308
+ }, 8, ["modelValue", "title"])
281
309
  ], 2));
282
310
  }
283
- }), [["__scopeId", "data-v-c59a60e3"]]);
311
+ }), [["__scopeId", "data-v-e6829e5c"]]);
284
312
  //#endregion
285
- export { j as MRichTextEditor };
313
+ export { P as MRichTextEditor };
286
314
 
287
315
  //# sourceMappingURL=rich-text-editor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rich-text-editor.js","names":[],"sources":["../src/components/MRichTextEditor.vue","../src/components/MRichTextEditor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount, shallowRef, computed } from 'vue'\nimport MIcon from './MIcon.vue'\nimport MMenu from './MMenu.vue'\nimport MMenuItem from './MMenuItem.vue'\nimport MDialog from './MDialog.vue'\nimport MTextField from './MTextField.vue'\nimport MButton from './MButton.vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue: string\n placeholder?: string\n disabled?: boolean\n minHeight?: string\n }>(),\n { placeholder: 'Escribe aquí...', disabled: false, minHeight: '200px' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [string] }>()\n\nconst ready = ref(false)\nconst editorRef = shallowRef<any>(null)\nconst editorContainer = ref<HTMLElement | null>(null)\n\ninterface ToolBtn {\n icon: string\n label: string\n action: () => void\n active?: () => boolean\n}\n\nconst toolGroups = ref<ToolBtn[][]>([])\n\nonMounted(async () => {\n const [\n { Editor },\n { default: StarterKit },\n { default: Underline },\n { default: TextAlign },\n { default: Link },\n { default: Image },\n { default: Highlight },\n { default: Placeholder },\n { TextStyle },\n { default: Color },\n ] = await Promise.all([\n import('@tiptap/vue-3'),\n import('@tiptap/starter-kit'),\n import('@tiptap/extension-underline'),\n import('@tiptap/extension-text-align'),\n import('@tiptap/extension-link'),\n import('@tiptap/extension-image'),\n import('@tiptap/extension-highlight'),\n import('@tiptap/extension-placeholder'),\n import('@tiptap/extension-text-style'),\n import('@tiptap/extension-color'),\n ])\n\n const editor = new Editor({\n element: editorContainer.value!,\n content: props.modelValue,\n editable: !props.disabled,\n extensions: [\n StarterKit,\n Underline,\n TextAlign.configure({ types: ['heading', 'paragraph'] }),\n Link.configure({ openOnClick: false }),\n Image,\n Highlight.configure({ multicolor: true }),\n Placeholder.configure({ placeholder: props.placeholder }),\n TextStyle,\n Color,\n ],\n onUpdate: ({ editor: e }) => emit('update:modelValue', e.getHTML()),\n })\n\n editorRef.value = editor\n\n toolGroups.value = [\n [\n { icon: 'format_bold', label: 'Negrita', action: () => editor.chain().focus().toggleBold().run(), active: () => !!editor.isActive('bold') },\n { icon: 'format_italic', label: 'Cursiva', action: () => editor.chain().focus().toggleItalic().run(), active: () => !!editor.isActive('italic') },\n { icon: 'format_underlined', label: 'Subrayado', action: () => editor.chain().focus().toggleUnderline().run(), active: () => !!editor.isActive('underline') },\n { icon: 'format_strikethrough', label: 'Tachado', action: () => editor.chain().focus().toggleStrike().run(), active: () => !!editor.isActive('strike') },\n { icon: 'ink_highlighter', label: 'Resaltar', action: () => editor.chain().focus().toggleHighlight().run(), active: () => !!editor.isActive('highlight') },\n ],\n [\n { icon: 'format_list_bulleted', label: 'Lista', action: () => editor.chain().focus().toggleBulletList().run(), active: () => !!editor.isActive('bulletList') },\n { icon: 'format_list_numbered', label: 'Lista numerada', action: () => editor.chain().focus().toggleOrderedList().run(), active: () => !!editor.isActive('orderedList') },\n { icon: 'format_quote', label: 'Cita', action: () => editor.chain().focus().toggleBlockquote().run(), active: () => !!editor.isActive('blockquote') },\n { icon: 'code', label: 'Código', action: () => editor.chain().focus().toggleCode().run(), active: () => !!editor.isActive('code') },\n ],\n [\n { icon: 'format_align_left', label: 'Izquierda', action: () => editor.chain().focus().setTextAlign('left').run(), active: () => !!editor.isActive({ textAlign: 'left' }) },\n { icon: 'format_align_center', label: 'Centro', action: () => editor.chain().focus().setTextAlign('center').run(), active: () => !!editor.isActive({ textAlign: 'center' }) },\n { icon: 'format_align_right', label: 'Derecha', action: () => editor.chain().focus().setTextAlign('right').run(), active: () => !!editor.isActive({ textAlign: 'right' }) },\n ],\n [\n { icon: 'undo', label: 'Deshacer', action: () => editor.chain().focus().undo().run() },\n { icon: 'redo', label: 'Rehacer', action: () => editor.chain().focus().redo().run() },\n ],\n ]\n\n onBeforeUnmount(() => editor.destroy())\n\n watch(() => props.modelValue, (val) => {\n if (editor.getHTML() !== val) editor.commands.setContent(val)\n })\n\n watch(() => props.disabled, (v) => editor.setEditable(!v))\n\n ready.value = true\n})\n\nconst linkDialogOpen = ref(false)\nconst linkUrl = ref('')\nconst imageDialogOpen = ref(false)\nconst imageUrl = ref('')\n\nconst headingLabel = computed(() => {\n const e = editorRef.value\n if (!e) return 'Párrafo'\n if (e.isActive('heading', { level: 1 })) return 'Título 1'\n if (e.isActive('heading', { level: 2 })) return 'Título 2'\n if (e.isActive('heading', { level: 3 })) return 'Título 3'\n return 'Párrafo'\n})\n\nfunction setHeading(level: 0 | 1 | 2 | 3) {\n if (level === 0) editorRef.value?.chain().focus().setParagraph().run()\n else editorRef.value?.chain().focus().toggleHeading({ level }).run()\n}\n\nfunction openLinkDialog() {\n linkUrl.value = ''\n linkDialogOpen.value = true\n}\n\nfunction confirmLink() {\n if (linkUrl.value) editorRef.value?.chain().focus().setLink({ href: linkUrl.value }).run()\n linkDialogOpen.value = false\n}\n\nfunction openImageDialog() {\n imageUrl.value = ''\n imageDialogOpen.value = true\n}\n\nfunction confirmImage() {\n if (imageUrl.value) editorRef.value?.chain().focus().setImage({ src: imageUrl.value }).run()\n imageDialogOpen.value = false\n}\n</script>\n\n<template>\n <div\n class=\"overflow-hidden rounded-lg border transition-colors duration-150\"\n :class=\"disabled ? 'border-outline-variant/50 opacity-60' : 'border-outline-variant focus-within:border-primary'\"\n >\n <!-- Toolbar -->\n <div v-if=\"ready\" class=\"flex flex-wrap items-center gap-0.5 border-b border-outline-variant bg-surface-container px-2 py-1.5\">\n <!-- Heading menu -->\n <MMenu align=\"left\">\n <template #trigger>\n <button\n type=\"button\"\n class=\"flex h-8 cursor-pointer items-center gap-1 rounded px-2 text-label-large text-on-surface-variant hover:bg-on-surface/8\"\n >\n {{ headingLabel }}\n <MIcon name=\"arrow_drop_down\" :size=\"20\" />\n </button>\n </template>\n <MMenuItem @click=\"setHeading(0)\">Párrafo</MMenuItem>\n <MMenuItem @click=\"setHeading(1)\">Título 1</MMenuItem>\n <MMenuItem @click=\"setHeading(2)\">Título 2</MMenuItem>\n <MMenuItem @click=\"setHeading(3)\">Título 3</MMenuItem>\n </MMenu>\n\n <div class=\"mx-1 h-6 w-px bg-outline-variant\" />\n\n <template v-for=\"(group, gi) in toolGroups\" :key=\"gi\">\n <button\n v-for=\"btn in group\"\n :key=\"btn.icon\"\n type=\"button\"\n :title=\"btn.label\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded transition-colors duration-100\"\n :class=\"btn.active?.() ? 'bg-secondary-container text-on-secondary-container' : 'text-on-surface-variant hover:bg-on-surface/8'\"\n @click=\"btn.action\"\n >\n <MIcon :name=\"btn.icon\" :size=\"20\" />\n </button>\n <div v-if=\"gi < toolGroups.length - 1\" class=\"mx-1 h-6 w-px bg-outline-variant\" />\n </template>\n\n <div class=\"mx-1 h-6 w-px bg-outline-variant\" />\n\n <button\n type=\"button\"\n title=\"Enlace\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8\"\n @click=\"openLinkDialog\"\n >\n <MIcon name=\"link\" :size=\"20\" />\n </button>\n <button\n type=\"button\"\n title=\"Imagen\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8\"\n @click=\"openImageDialog\"\n >\n <MIcon name=\"image\" :size=\"20\" />\n </button>\n </div>\n\n <!-- Editor content -->\n <div\n ref=\"editorContainer\"\n class=\"rte-content bg-surface px-4 py-3 text-body-large text-on-surface\"\n :style=\"{ minHeight: minHeight }\"\n />\n\n <!-- Link dialog -->\n <MDialog v-model=\"linkDialogOpen\" title=\"Insertar enlace\">\n <MTextField v-model=\"linkUrl\" label=\"URL\" placeholder=\" \" @keydown.enter=\"confirmLink\" />\n <template #actions>\n <MButton variant=\"text\" @click=\"linkDialogOpen = false\">Cancelar</MButton>\n <MButton @click=\"confirmLink\">Insertar</MButton>\n </template>\n </MDialog>\n\n <!-- Image dialog -->\n <MDialog v-model=\"imageDialogOpen\" title=\"Insertar imagen\">\n <MTextField v-model=\"imageUrl\" label=\"URL de la imagen\" placeholder=\" \" @keydown.enter=\"confirmImage\" />\n <template #actions>\n <MButton variant=\"text\" @click=\"imageDialogOpen = false\">Cancelar</MButton>\n <MButton @click=\"confirmImage\">Insertar</MButton>\n </template>\n </MDialog>\n </div>\n</template>\n\n<style scoped>\n.rte-content :deep(.tiptap) {\n outline: none;\n min-height: inherit;\n}\n\n.rte-content :deep(.tiptap p.is-editor-empty:first-child::before) {\n content: attr(data-placeholder);\n float: left;\n color: var(--color-on-surface-variant);\n opacity: 0.5;\n pointer-events: none;\n height: 0;\n}\n\n.rte-content :deep(h1) { font-size: var(--text-headline-large); line-height: var(--text-headline-large--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(h2) { font-size: var(--text-headline-medium); line-height: var(--text-headline-medium--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(h3) { font-size: var(--text-headline-small); line-height: var(--text-headline-small--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(p) { margin: 0.5em 0; }\n.rte-content :deep(ul) { list-style-type: disc; padding-left: 1.5em; margin: 0.5em 0; }\n.rte-content :deep(ol) { list-style-type: decimal; padding-left: 1.5em; margin: 0.5em 0; }\n.rte-content :deep(blockquote) { border-left: 3px solid var(--color-primary); padding-left: 1em; margin: 0.5em 0; color: var(--color-on-surface-variant); }\n.rte-content :deep(code) { background: var(--color-surface-container-highest); padding: 0.15em 0.4em; border-radius: 4px; font-size: 0.875em; }\n.rte-content :deep(pre) { background: var(--color-surface-container-highest); padding: 1em; border-radius: 8px; overflow-x: auto; margin: 0.5em 0; }\n.rte-content :deep(pre code) { background: none; padding: 0; }\n.rte-content :deep(a) { color: var(--color-primary); text-decoration: underline; }\n.rte-content :deep(mark) { background: var(--color-tertiary-container); color: var(--color-on-tertiary-container); padding: 0.1em 0.2em; border-radius: 2px; }\n.rte-content :deep(img) { max-width: 100%; height: auto; border-radius: 8px; margin: 0.5em 0; }\n</style>\n","<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount, shallowRef, computed } from 'vue'\nimport MIcon from './MIcon.vue'\nimport MMenu from './MMenu.vue'\nimport MMenuItem from './MMenuItem.vue'\nimport MDialog from './MDialog.vue'\nimport MTextField from './MTextField.vue'\nimport MButton from './MButton.vue'\n\nconst props = withDefaults(\n defineProps<{\n modelValue: string\n placeholder?: string\n disabled?: boolean\n minHeight?: string\n }>(),\n { placeholder: 'Escribe aquí...', disabled: false, minHeight: '200px' },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [string] }>()\n\nconst ready = ref(false)\nconst editorRef = shallowRef<any>(null)\nconst editorContainer = ref<HTMLElement | null>(null)\n\ninterface ToolBtn {\n icon: string\n label: string\n action: () => void\n active?: () => boolean\n}\n\nconst toolGroups = ref<ToolBtn[][]>([])\n\nonMounted(async () => {\n const [\n { Editor },\n { default: StarterKit },\n { default: Underline },\n { default: TextAlign },\n { default: Link },\n { default: Image },\n { default: Highlight },\n { default: Placeholder },\n { TextStyle },\n { default: Color },\n ] = await Promise.all([\n import('@tiptap/vue-3'),\n import('@tiptap/starter-kit'),\n import('@tiptap/extension-underline'),\n import('@tiptap/extension-text-align'),\n import('@tiptap/extension-link'),\n import('@tiptap/extension-image'),\n import('@tiptap/extension-highlight'),\n import('@tiptap/extension-placeholder'),\n import('@tiptap/extension-text-style'),\n import('@tiptap/extension-color'),\n ])\n\n const editor = new Editor({\n element: editorContainer.value!,\n content: props.modelValue,\n editable: !props.disabled,\n extensions: [\n StarterKit,\n Underline,\n TextAlign.configure({ types: ['heading', 'paragraph'] }),\n Link.configure({ openOnClick: false }),\n Image,\n Highlight.configure({ multicolor: true }),\n Placeholder.configure({ placeholder: props.placeholder }),\n TextStyle,\n Color,\n ],\n onUpdate: ({ editor: e }) => emit('update:modelValue', e.getHTML()),\n })\n\n editorRef.value = editor\n\n toolGroups.value = [\n [\n { icon: 'format_bold', label: 'Negrita', action: () => editor.chain().focus().toggleBold().run(), active: () => !!editor.isActive('bold') },\n { icon: 'format_italic', label: 'Cursiva', action: () => editor.chain().focus().toggleItalic().run(), active: () => !!editor.isActive('italic') },\n { icon: 'format_underlined', label: 'Subrayado', action: () => editor.chain().focus().toggleUnderline().run(), active: () => !!editor.isActive('underline') },\n { icon: 'format_strikethrough', label: 'Tachado', action: () => editor.chain().focus().toggleStrike().run(), active: () => !!editor.isActive('strike') },\n { icon: 'ink_highlighter', label: 'Resaltar', action: () => editor.chain().focus().toggleHighlight().run(), active: () => !!editor.isActive('highlight') },\n ],\n [\n { icon: 'format_list_bulleted', label: 'Lista', action: () => editor.chain().focus().toggleBulletList().run(), active: () => !!editor.isActive('bulletList') },\n { icon: 'format_list_numbered', label: 'Lista numerada', action: () => editor.chain().focus().toggleOrderedList().run(), active: () => !!editor.isActive('orderedList') },\n { icon: 'format_quote', label: 'Cita', action: () => editor.chain().focus().toggleBlockquote().run(), active: () => !!editor.isActive('blockquote') },\n { icon: 'code', label: 'Código', action: () => editor.chain().focus().toggleCode().run(), active: () => !!editor.isActive('code') },\n ],\n [\n { icon: 'format_align_left', label: 'Izquierda', action: () => editor.chain().focus().setTextAlign('left').run(), active: () => !!editor.isActive({ textAlign: 'left' }) },\n { icon: 'format_align_center', label: 'Centro', action: () => editor.chain().focus().setTextAlign('center').run(), active: () => !!editor.isActive({ textAlign: 'center' }) },\n { icon: 'format_align_right', label: 'Derecha', action: () => editor.chain().focus().setTextAlign('right').run(), active: () => !!editor.isActive({ textAlign: 'right' }) },\n ],\n [\n { icon: 'undo', label: 'Deshacer', action: () => editor.chain().focus().undo().run() },\n { icon: 'redo', label: 'Rehacer', action: () => editor.chain().focus().redo().run() },\n ],\n ]\n\n onBeforeUnmount(() => editor.destroy())\n\n watch(() => props.modelValue, (val) => {\n if (editor.getHTML() !== val) editor.commands.setContent(val)\n })\n\n watch(() => props.disabled, (v) => editor.setEditable(!v))\n\n ready.value = true\n})\n\nconst linkDialogOpen = ref(false)\nconst linkUrl = ref('')\nconst imageDialogOpen = ref(false)\nconst imageUrl = ref('')\n\nconst headingLabel = computed(() => {\n const e = editorRef.value\n if (!e) return 'Párrafo'\n if (e.isActive('heading', { level: 1 })) return 'Título 1'\n if (e.isActive('heading', { level: 2 })) return 'Título 2'\n if (e.isActive('heading', { level: 3 })) return 'Título 3'\n return 'Párrafo'\n})\n\nfunction setHeading(level: 0 | 1 | 2 | 3) {\n if (level === 0) editorRef.value?.chain().focus().setParagraph().run()\n else editorRef.value?.chain().focus().toggleHeading({ level }).run()\n}\n\nfunction openLinkDialog() {\n linkUrl.value = ''\n linkDialogOpen.value = true\n}\n\nfunction confirmLink() {\n if (linkUrl.value) editorRef.value?.chain().focus().setLink({ href: linkUrl.value }).run()\n linkDialogOpen.value = false\n}\n\nfunction openImageDialog() {\n imageUrl.value = ''\n imageDialogOpen.value = true\n}\n\nfunction confirmImage() {\n if (imageUrl.value) editorRef.value?.chain().focus().setImage({ src: imageUrl.value }).run()\n imageDialogOpen.value = false\n}\n</script>\n\n<template>\n <div\n class=\"overflow-hidden rounded-lg border transition-colors duration-150\"\n :class=\"disabled ? 'border-outline-variant/50 opacity-60' : 'border-outline-variant focus-within:border-primary'\"\n >\n <!-- Toolbar -->\n <div v-if=\"ready\" class=\"flex flex-wrap items-center gap-0.5 border-b border-outline-variant bg-surface-container px-2 py-1.5\">\n <!-- Heading menu -->\n <MMenu align=\"left\">\n <template #trigger>\n <button\n type=\"button\"\n class=\"flex h-8 cursor-pointer items-center gap-1 rounded px-2 text-label-large text-on-surface-variant hover:bg-on-surface/8\"\n >\n {{ headingLabel }}\n <MIcon name=\"arrow_drop_down\" :size=\"20\" />\n </button>\n </template>\n <MMenuItem @click=\"setHeading(0)\">Párrafo</MMenuItem>\n <MMenuItem @click=\"setHeading(1)\">Título 1</MMenuItem>\n <MMenuItem @click=\"setHeading(2)\">Título 2</MMenuItem>\n <MMenuItem @click=\"setHeading(3)\">Título 3</MMenuItem>\n </MMenu>\n\n <div class=\"mx-1 h-6 w-px bg-outline-variant\" />\n\n <template v-for=\"(group, gi) in toolGroups\" :key=\"gi\">\n <button\n v-for=\"btn in group\"\n :key=\"btn.icon\"\n type=\"button\"\n :title=\"btn.label\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded transition-colors duration-100\"\n :class=\"btn.active?.() ? 'bg-secondary-container text-on-secondary-container' : 'text-on-surface-variant hover:bg-on-surface/8'\"\n @click=\"btn.action\"\n >\n <MIcon :name=\"btn.icon\" :size=\"20\" />\n </button>\n <div v-if=\"gi < toolGroups.length - 1\" class=\"mx-1 h-6 w-px bg-outline-variant\" />\n </template>\n\n <div class=\"mx-1 h-6 w-px bg-outline-variant\" />\n\n <button\n type=\"button\"\n title=\"Enlace\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8\"\n @click=\"openLinkDialog\"\n >\n <MIcon name=\"link\" :size=\"20\" />\n </button>\n <button\n type=\"button\"\n title=\"Imagen\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8\"\n @click=\"openImageDialog\"\n >\n <MIcon name=\"image\" :size=\"20\" />\n </button>\n </div>\n\n <!-- Editor content -->\n <div\n ref=\"editorContainer\"\n class=\"rte-content bg-surface px-4 py-3 text-body-large text-on-surface\"\n :style=\"{ minHeight: minHeight }\"\n />\n\n <!-- Link dialog -->\n <MDialog v-model=\"linkDialogOpen\" title=\"Insertar enlace\">\n <MTextField v-model=\"linkUrl\" label=\"URL\" placeholder=\" \" @keydown.enter=\"confirmLink\" />\n <template #actions>\n <MButton variant=\"text\" @click=\"linkDialogOpen = false\">Cancelar</MButton>\n <MButton @click=\"confirmLink\">Insertar</MButton>\n </template>\n </MDialog>\n\n <!-- Image dialog -->\n <MDialog v-model=\"imageDialogOpen\" title=\"Insertar imagen\">\n <MTextField v-model=\"imageUrl\" label=\"URL de la imagen\" placeholder=\" \" @keydown.enter=\"confirmImage\" />\n <template #actions>\n <MButton variant=\"text\" @click=\"imageDialogOpen = false\">Cancelar</MButton>\n <MButton @click=\"confirmImage\">Insertar</MButton>\n </template>\n </MDialog>\n </div>\n</template>\n\n<style scoped>\n.rte-content :deep(.tiptap) {\n outline: none;\n min-height: inherit;\n}\n\n.rte-content :deep(.tiptap p.is-editor-empty:first-child::before) {\n content: attr(data-placeholder);\n float: left;\n color: var(--color-on-surface-variant);\n opacity: 0.5;\n pointer-events: none;\n height: 0;\n}\n\n.rte-content :deep(h1) { font-size: var(--text-headline-large); line-height: var(--text-headline-large--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(h2) { font-size: var(--text-headline-medium); line-height: var(--text-headline-medium--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(h3) { font-size: var(--text-headline-small); line-height: var(--text-headline-small--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(p) { margin: 0.5em 0; }\n.rte-content :deep(ul) { list-style-type: disc; padding-left: 1.5em; margin: 0.5em 0; }\n.rte-content :deep(ol) { list-style-type: decimal; padding-left: 1.5em; margin: 0.5em 0; }\n.rte-content :deep(blockquote) { border-left: 3px solid var(--color-primary); padding-left: 1em; margin: 0.5em 0; color: var(--color-on-surface-variant); }\n.rte-content :deep(code) { background: var(--color-surface-container-highest); padding: 0.15em 0.4em; border-radius: 4px; font-size: 0.875em; }\n.rte-content :deep(pre) { background: var(--color-surface-container-highest); padding: 1em; border-radius: 8px; overflow-x: auto; margin: 0.5em 0; }\n.rte-content :deep(pre code) { background: none; padding: 0; }\n.rte-content :deep(a) { color: var(--color-primary); text-decoration: underline; }\n.rte-content :deep(mark) { background: var(--color-tertiary-container); color: var(--color-on-tertiary-container); padding: 0.1em 0.2em; border-radius: 2px; }\n.rte-content :deep(img) { max-width: 100%; height: auto; border-radius: 8px; margin: 0.5em 0; }\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"rich-text-editor.js","names":[],"sources":["../src/components/MRichTextEditor.vue","../src/components/MRichTextEditor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount, shallowRef, computed } from 'vue'\nimport MIcon from './MIcon.vue'\nimport MMenu from './MMenu.vue'\nimport MMenuItem from './MMenuItem.vue'\nimport MDialog from './MDialog.vue'\nimport MTextField from './MTextField.vue'\nimport MButton from './MButton.vue'\nimport { useLocale } from '../composables/useLocale'\n\nexport interface RichTextEditorLabels {\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 cancel?: string\n insert?: string\n}\n\nconst locale = useLocale()\n\nconst props = withDefaults(\n defineProps<{\n modelValue: string\n placeholder?: string\n disabled?: boolean\n minHeight?: string\n labels?: RichTextEditorLabels\n }>(),\n { disabled: false, minHeight: '200px' },\n)\n\nconst l = computed<Required<RichTextEditorLabels>>(() => ({\n bold: locale.bold,\n italic: locale.italic,\n underline: locale.underline,\n strikethrough: locale.strikethrough,\n highlight: locale.highlight,\n bulletList: locale.bulletList,\n orderedList: locale.orderedList,\n blockquote: locale.blockquote,\n code: locale.code,\n alignLeft: locale.alignLeft,\n alignCenter: locale.alignCenter,\n alignRight: locale.alignRight,\n undo: locale.undo,\n redo: locale.redo,\n link: locale.link,\n image: locale.image,\n paragraph: locale.paragraph,\n heading1: locale.heading1,\n heading2: locale.heading2,\n heading3: locale.heading3,\n insertLink: locale.insertLink,\n insertImage: locale.insertImage,\n imageUrlLabel: locale.imageUrlLabel,\n cancel: locale.cancel,\n insert: locale.insert,\n ...props.labels,\n}))\n\nconst emit = defineEmits<{ 'update:modelValue': [string] }>()\n\nconst ready = ref(false)\nconst editorRef = shallowRef<any>(null)\nconst editorContainer = ref<HTMLElement | null>(null)\n\ninterface ToolBtn {\n icon: string\n label: string\n action: () => void\n active?: () => boolean\n}\n\nconst toolGroups = ref<ToolBtn[][]>([])\n\nonMounted(async () => {\n const [\n { Editor },\n { default: StarterKit },\n { default: Underline },\n { default: TextAlign },\n { default: Link },\n { default: Image },\n { default: Highlight },\n { default: Placeholder },\n { TextStyle },\n { default: Color },\n ] = await Promise.all([\n import('@tiptap/vue-3'),\n import('@tiptap/starter-kit'),\n import('@tiptap/extension-underline'),\n import('@tiptap/extension-text-align'),\n import('@tiptap/extension-link'),\n import('@tiptap/extension-image'),\n import('@tiptap/extension-highlight'),\n import('@tiptap/extension-placeholder'),\n import('@tiptap/extension-text-style'),\n import('@tiptap/extension-color'),\n ])\n\n const editor = new Editor({\n element: editorContainer.value!,\n content: props.modelValue,\n editable: !props.disabled,\n extensions: [\n StarterKit,\n Underline,\n TextAlign.configure({ types: ['heading', 'paragraph'] }),\n Link.configure({ openOnClick: false }),\n Image,\n Highlight.configure({ multicolor: true }),\n Placeholder.configure({ placeholder: props.placeholder ?? 'Start writing...' }),\n TextStyle,\n Color,\n ],\n onUpdate: ({ editor: e }) => emit('update:modelValue', e.getHTML()),\n })\n\n editorRef.value = editor\n\n toolGroups.value = [\n [\n { icon: 'format_bold', label: l.value.bold, action: () => editor.chain().focus().toggleBold().run(), active: () => !!editor.isActive('bold') },\n { icon: 'format_italic', label: l.value.italic, action: () => editor.chain().focus().toggleItalic().run(), active: () => !!editor.isActive('italic') },\n { icon: 'format_underlined', label: l.value.underline, action: () => editor.chain().focus().toggleUnderline().run(), active: () => !!editor.isActive('underline') },\n { icon: 'format_strikethrough', label: l.value.strikethrough, action: () => editor.chain().focus().toggleStrike().run(), active: () => !!editor.isActive('strike') },\n { icon: 'ink_highlighter', label: l.value.highlight, action: () => editor.chain().focus().toggleHighlight().run(), active: () => !!editor.isActive('highlight') },\n ],\n [\n { icon: 'format_list_bulleted', label: l.value.bulletList, action: () => editor.chain().focus().toggleBulletList().run(), active: () => !!editor.isActive('bulletList') },\n { icon: 'format_list_numbered', label: l.value.orderedList, action: () => editor.chain().focus().toggleOrderedList().run(), active: () => !!editor.isActive('orderedList') },\n { icon: 'format_quote', label: l.value.blockquote, action: () => editor.chain().focus().toggleBlockquote().run(), active: () => !!editor.isActive('blockquote') },\n { icon: 'code', label: l.value.code, action: () => editor.chain().focus().toggleCode().run(), active: () => !!editor.isActive('code') },\n ],\n [\n { icon: 'format_align_left', label: l.value.alignLeft, action: () => editor.chain().focus().setTextAlign('left').run(), active: () => !!editor.isActive({ textAlign: 'left' }) },\n { icon: 'format_align_center', label: l.value.alignCenter, action: () => editor.chain().focus().setTextAlign('center').run(), active: () => !!editor.isActive({ textAlign: 'center' }) },\n { icon: 'format_align_right', label: l.value.alignRight, action: () => editor.chain().focus().setTextAlign('right').run(), active: () => !!editor.isActive({ textAlign: 'right' }) },\n ],\n [\n { icon: 'undo', label: l.value.undo, action: () => editor.chain().focus().undo().run() },\n { icon: 'redo', label: l.value.redo, action: () => editor.chain().focus().redo().run() },\n ],\n ]\n\n onBeforeUnmount(() => editor.destroy())\n\n watch(() => props.modelValue, (val) => {\n if (editor.getHTML() !== val) editor.commands.setContent(val)\n })\n\n watch(() => props.disabled, (v) => editor.setEditable(!v))\n\n ready.value = true\n})\n\nconst linkDialogOpen = ref(false)\nconst linkUrl = ref('')\nconst imageDialogOpen = ref(false)\nconst imageUrl = ref('')\n\nconst headingLabel = computed(() => {\n const e = editorRef.value\n if (!e) return l.value.paragraph\n if (e.isActive('heading', { level: 1 })) return l.value.heading1\n if (e.isActive('heading', { level: 2 })) return l.value.heading2\n if (e.isActive('heading', { level: 3 })) return l.value.heading3\n return l.value.paragraph\n})\n\nfunction setHeading(level: 0 | 1 | 2 | 3) {\n if (level === 0) editorRef.value?.chain().focus().setParagraph().run()\n else editorRef.value?.chain().focus().toggleHeading({ level }).run()\n}\n\nfunction openLinkDialog() {\n linkUrl.value = ''\n linkDialogOpen.value = true\n}\n\nfunction confirmLink() {\n if (linkUrl.value) editorRef.value?.chain().focus().setLink({ href: linkUrl.value }).run()\n linkDialogOpen.value = false\n}\n\nfunction openImageDialog() {\n imageUrl.value = ''\n imageDialogOpen.value = true\n}\n\nfunction confirmImage() {\n if (imageUrl.value) editorRef.value?.chain().focus().setImage({ src: imageUrl.value }).run()\n imageDialogOpen.value = false\n}\n</script>\n\n<template>\n <div\n class=\"overflow-hidden rounded-lg border transition-colors duration-150\"\n :class=\"disabled ? 'border-outline-variant/50 opacity-60' : 'border-outline-variant focus-within:border-primary'\"\n >\n <!-- Toolbar -->\n <div v-if=\"ready\" class=\"flex flex-wrap items-center gap-0.5 border-b border-outline-variant bg-surface-container px-2 py-1.5\">\n <!-- Heading menu -->\n <MMenu align=\"left\">\n <template #trigger>\n <button\n type=\"button\"\n class=\"flex h-8 cursor-pointer items-center gap-1 rounded px-2 text-label-large text-on-surface-variant hover:bg-on-surface/8\"\n >\n {{ headingLabel }}\n <MIcon name=\"arrow_drop_down\" :size=\"20\" />\n </button>\n </template>\n <MMenuItem @click=\"setHeading(0)\">{{ l.paragraph }}</MMenuItem>\n <MMenuItem @click=\"setHeading(1)\">{{ l.heading1 }}</MMenuItem>\n <MMenuItem @click=\"setHeading(2)\">{{ l.heading2 }}</MMenuItem>\n <MMenuItem @click=\"setHeading(3)\">{{ l.heading3 }}</MMenuItem>\n </MMenu>\n\n <div class=\"mx-1 h-6 w-px bg-outline-variant\" />\n\n <template v-for=\"(group, gi) in toolGroups\" :key=\"gi\">\n <button\n v-for=\"btn in group\"\n :key=\"btn.icon\"\n type=\"button\"\n :title=\"btn.label\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded transition-colors duration-100\"\n :class=\"btn.active?.() ? 'bg-secondary-container text-on-secondary-container' : 'text-on-surface-variant hover:bg-on-surface/8'\"\n @click=\"btn.action\"\n >\n <MIcon :name=\"btn.icon\" :size=\"20\" />\n </button>\n <div v-if=\"gi < toolGroups.length - 1\" class=\"mx-1 h-6 w-px bg-outline-variant\" />\n </template>\n\n <div class=\"mx-1 h-6 w-px bg-outline-variant\" />\n\n <button\n type=\"button\"\n :title=\"l.link\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8\"\n @click=\"openLinkDialog\"\n >\n <MIcon name=\"link\" :size=\"20\" />\n </button>\n <button\n type=\"button\"\n :title=\"l.image\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8\"\n @click=\"openImageDialog\"\n >\n <MIcon name=\"image\" :size=\"20\" />\n </button>\n </div>\n\n <!-- Editor content -->\n <div\n ref=\"editorContainer\"\n class=\"rte-content bg-surface px-4 py-3 text-body-large text-on-surface\"\n :style=\"{ minHeight: minHeight }\"\n />\n\n <!-- Link dialog -->\n <MDialog v-model=\"linkDialogOpen\" :title=\"l.insertLink\">\n <MTextField v-model=\"linkUrl\" label=\"URL\" placeholder=\" \" @keydown.enter=\"confirmLink\" />\n <template #actions>\n <MButton variant=\"text\" @click=\"linkDialogOpen = false\">{{ l.cancel }}</MButton>\n <MButton @click=\"confirmLink\">{{ l.insert }}</MButton>\n </template>\n </MDialog>\n\n <!-- Image dialog -->\n <MDialog v-model=\"imageDialogOpen\" :title=\"l.insertImage\">\n <MTextField v-model=\"imageUrl\" :label=\"l.imageUrlLabel\" placeholder=\" \" @keydown.enter=\"confirmImage\" />\n <template #actions>\n <MButton variant=\"text\" @click=\"imageDialogOpen = false\">{{ l.cancel }}</MButton>\n <MButton @click=\"confirmImage\">{{ l.insert }}</MButton>\n </template>\n </MDialog>\n </div>\n</template>\n\n<style scoped>\n.rte-content :deep(.tiptap) {\n outline: none;\n min-height: inherit;\n}\n\n.rte-content :deep(.tiptap p.is-editor-empty:first-child::before) {\n content: attr(data-placeholder);\n float: left;\n color: var(--color-on-surface-variant);\n opacity: 0.5;\n pointer-events: none;\n height: 0;\n}\n\n.rte-content :deep(h1) { font-size: var(--text-headline-large); line-height: var(--text-headline-large--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(h2) { font-size: var(--text-headline-medium); line-height: var(--text-headline-medium--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(h3) { font-size: var(--text-headline-small); line-height: var(--text-headline-small--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(p) { margin: 0.5em 0; }\n.rte-content :deep(ul) { list-style-type: disc; padding-left: 1.5em; margin: 0.5em 0; }\n.rte-content :deep(ol) { list-style-type: decimal; padding-left: 1.5em; margin: 0.5em 0; }\n.rte-content :deep(blockquote) { border-left: 3px solid var(--color-primary); padding-left: 1em; margin: 0.5em 0; color: var(--color-on-surface-variant); }\n.rte-content :deep(code) { background: var(--color-surface-container-highest); padding: 0.15em 0.4em; border-radius: 4px; font-size: 0.875em; }\n.rte-content :deep(pre) { background: var(--color-surface-container-highest); padding: 1em; border-radius: 8px; overflow-x: auto; margin: 0.5em 0; }\n.rte-content :deep(pre code) { background: none; padding: 0; }\n.rte-content :deep(a) { color: var(--color-primary); text-decoration: underline; }\n.rte-content :deep(mark) { background: var(--color-tertiary-container); color: var(--color-on-tertiary-container); padding: 0.1em 0.2em; border-radius: 2px; }\n.rte-content :deep(img) { max-width: 100%; height: auto; border-radius: 8px; margin: 0.5em 0; }\n</style>\n","<script setup lang=\"ts\">\nimport { ref, watch, onMounted, onBeforeUnmount, shallowRef, computed } from 'vue'\nimport MIcon from './MIcon.vue'\nimport MMenu from './MMenu.vue'\nimport MMenuItem from './MMenuItem.vue'\nimport MDialog from './MDialog.vue'\nimport MTextField from './MTextField.vue'\nimport MButton from './MButton.vue'\nimport { useLocale } from '../composables/useLocale'\n\nexport interface RichTextEditorLabels {\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 cancel?: string\n insert?: string\n}\n\nconst locale = useLocale()\n\nconst props = withDefaults(\n defineProps<{\n modelValue: string\n placeholder?: string\n disabled?: boolean\n minHeight?: string\n labels?: RichTextEditorLabels\n }>(),\n { disabled: false, minHeight: '200px' },\n)\n\nconst l = computed<Required<RichTextEditorLabels>>(() => ({\n bold: locale.bold,\n italic: locale.italic,\n underline: locale.underline,\n strikethrough: locale.strikethrough,\n highlight: locale.highlight,\n bulletList: locale.bulletList,\n orderedList: locale.orderedList,\n blockquote: locale.blockquote,\n code: locale.code,\n alignLeft: locale.alignLeft,\n alignCenter: locale.alignCenter,\n alignRight: locale.alignRight,\n undo: locale.undo,\n redo: locale.redo,\n link: locale.link,\n image: locale.image,\n paragraph: locale.paragraph,\n heading1: locale.heading1,\n heading2: locale.heading2,\n heading3: locale.heading3,\n insertLink: locale.insertLink,\n insertImage: locale.insertImage,\n imageUrlLabel: locale.imageUrlLabel,\n cancel: locale.cancel,\n insert: locale.insert,\n ...props.labels,\n}))\n\nconst emit = defineEmits<{ 'update:modelValue': [string] }>()\n\nconst ready = ref(false)\nconst editorRef = shallowRef<any>(null)\nconst editorContainer = ref<HTMLElement | null>(null)\n\ninterface ToolBtn {\n icon: string\n label: string\n action: () => void\n active?: () => boolean\n}\n\nconst toolGroups = ref<ToolBtn[][]>([])\n\nonMounted(async () => {\n const [\n { Editor },\n { default: StarterKit },\n { default: Underline },\n { default: TextAlign },\n { default: Link },\n { default: Image },\n { default: Highlight },\n { default: Placeholder },\n { TextStyle },\n { default: Color },\n ] = await Promise.all([\n import('@tiptap/vue-3'),\n import('@tiptap/starter-kit'),\n import('@tiptap/extension-underline'),\n import('@tiptap/extension-text-align'),\n import('@tiptap/extension-link'),\n import('@tiptap/extension-image'),\n import('@tiptap/extension-highlight'),\n import('@tiptap/extension-placeholder'),\n import('@tiptap/extension-text-style'),\n import('@tiptap/extension-color'),\n ])\n\n const editor = new Editor({\n element: editorContainer.value!,\n content: props.modelValue,\n editable: !props.disabled,\n extensions: [\n StarterKit,\n Underline,\n TextAlign.configure({ types: ['heading', 'paragraph'] }),\n Link.configure({ openOnClick: false }),\n Image,\n Highlight.configure({ multicolor: true }),\n Placeholder.configure({ placeholder: props.placeholder ?? 'Start writing...' }),\n TextStyle,\n Color,\n ],\n onUpdate: ({ editor: e }) => emit('update:modelValue', e.getHTML()),\n })\n\n editorRef.value = editor\n\n toolGroups.value = [\n [\n { icon: 'format_bold', label: l.value.bold, action: () => editor.chain().focus().toggleBold().run(), active: () => !!editor.isActive('bold') },\n { icon: 'format_italic', label: l.value.italic, action: () => editor.chain().focus().toggleItalic().run(), active: () => !!editor.isActive('italic') },\n { icon: 'format_underlined', label: l.value.underline, action: () => editor.chain().focus().toggleUnderline().run(), active: () => !!editor.isActive('underline') },\n { icon: 'format_strikethrough', label: l.value.strikethrough, action: () => editor.chain().focus().toggleStrike().run(), active: () => !!editor.isActive('strike') },\n { icon: 'ink_highlighter', label: l.value.highlight, action: () => editor.chain().focus().toggleHighlight().run(), active: () => !!editor.isActive('highlight') },\n ],\n [\n { icon: 'format_list_bulleted', label: l.value.bulletList, action: () => editor.chain().focus().toggleBulletList().run(), active: () => !!editor.isActive('bulletList') },\n { icon: 'format_list_numbered', label: l.value.orderedList, action: () => editor.chain().focus().toggleOrderedList().run(), active: () => !!editor.isActive('orderedList') },\n { icon: 'format_quote', label: l.value.blockquote, action: () => editor.chain().focus().toggleBlockquote().run(), active: () => !!editor.isActive('blockquote') },\n { icon: 'code', label: l.value.code, action: () => editor.chain().focus().toggleCode().run(), active: () => !!editor.isActive('code') },\n ],\n [\n { icon: 'format_align_left', label: l.value.alignLeft, action: () => editor.chain().focus().setTextAlign('left').run(), active: () => !!editor.isActive({ textAlign: 'left' }) },\n { icon: 'format_align_center', label: l.value.alignCenter, action: () => editor.chain().focus().setTextAlign('center').run(), active: () => !!editor.isActive({ textAlign: 'center' }) },\n { icon: 'format_align_right', label: l.value.alignRight, action: () => editor.chain().focus().setTextAlign('right').run(), active: () => !!editor.isActive({ textAlign: 'right' }) },\n ],\n [\n { icon: 'undo', label: l.value.undo, action: () => editor.chain().focus().undo().run() },\n { icon: 'redo', label: l.value.redo, action: () => editor.chain().focus().redo().run() },\n ],\n ]\n\n onBeforeUnmount(() => editor.destroy())\n\n watch(() => props.modelValue, (val) => {\n if (editor.getHTML() !== val) editor.commands.setContent(val)\n })\n\n watch(() => props.disabled, (v) => editor.setEditable(!v))\n\n ready.value = true\n})\n\nconst linkDialogOpen = ref(false)\nconst linkUrl = ref('')\nconst imageDialogOpen = ref(false)\nconst imageUrl = ref('')\n\nconst headingLabel = computed(() => {\n const e = editorRef.value\n if (!e) return l.value.paragraph\n if (e.isActive('heading', { level: 1 })) return l.value.heading1\n if (e.isActive('heading', { level: 2 })) return l.value.heading2\n if (e.isActive('heading', { level: 3 })) return l.value.heading3\n return l.value.paragraph\n})\n\nfunction setHeading(level: 0 | 1 | 2 | 3) {\n if (level === 0) editorRef.value?.chain().focus().setParagraph().run()\n else editorRef.value?.chain().focus().toggleHeading({ level }).run()\n}\n\nfunction openLinkDialog() {\n linkUrl.value = ''\n linkDialogOpen.value = true\n}\n\nfunction confirmLink() {\n if (linkUrl.value) editorRef.value?.chain().focus().setLink({ href: linkUrl.value }).run()\n linkDialogOpen.value = false\n}\n\nfunction openImageDialog() {\n imageUrl.value = ''\n imageDialogOpen.value = true\n}\n\nfunction confirmImage() {\n if (imageUrl.value) editorRef.value?.chain().focus().setImage({ src: imageUrl.value }).run()\n imageDialogOpen.value = false\n}\n</script>\n\n<template>\n <div\n class=\"overflow-hidden rounded-lg border transition-colors duration-150\"\n :class=\"disabled ? 'border-outline-variant/50 opacity-60' : 'border-outline-variant focus-within:border-primary'\"\n >\n <!-- Toolbar -->\n <div v-if=\"ready\" class=\"flex flex-wrap items-center gap-0.5 border-b border-outline-variant bg-surface-container px-2 py-1.5\">\n <!-- Heading menu -->\n <MMenu align=\"left\">\n <template #trigger>\n <button\n type=\"button\"\n class=\"flex h-8 cursor-pointer items-center gap-1 rounded px-2 text-label-large text-on-surface-variant hover:bg-on-surface/8\"\n >\n {{ headingLabel }}\n <MIcon name=\"arrow_drop_down\" :size=\"20\" />\n </button>\n </template>\n <MMenuItem @click=\"setHeading(0)\">{{ l.paragraph }}</MMenuItem>\n <MMenuItem @click=\"setHeading(1)\">{{ l.heading1 }}</MMenuItem>\n <MMenuItem @click=\"setHeading(2)\">{{ l.heading2 }}</MMenuItem>\n <MMenuItem @click=\"setHeading(3)\">{{ l.heading3 }}</MMenuItem>\n </MMenu>\n\n <div class=\"mx-1 h-6 w-px bg-outline-variant\" />\n\n <template v-for=\"(group, gi) in toolGroups\" :key=\"gi\">\n <button\n v-for=\"btn in group\"\n :key=\"btn.icon\"\n type=\"button\"\n :title=\"btn.label\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded transition-colors duration-100\"\n :class=\"btn.active?.() ? 'bg-secondary-container text-on-secondary-container' : 'text-on-surface-variant hover:bg-on-surface/8'\"\n @click=\"btn.action\"\n >\n <MIcon :name=\"btn.icon\" :size=\"20\" />\n </button>\n <div v-if=\"gi < toolGroups.length - 1\" class=\"mx-1 h-6 w-px bg-outline-variant\" />\n </template>\n\n <div class=\"mx-1 h-6 w-px bg-outline-variant\" />\n\n <button\n type=\"button\"\n :title=\"l.link\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8\"\n @click=\"openLinkDialog\"\n >\n <MIcon name=\"link\" :size=\"20\" />\n </button>\n <button\n type=\"button\"\n :title=\"l.image\"\n class=\"flex h-8 w-8 cursor-pointer items-center justify-center rounded text-on-surface-variant transition-colors hover:bg-on-surface/8\"\n @click=\"openImageDialog\"\n >\n <MIcon name=\"image\" :size=\"20\" />\n </button>\n </div>\n\n <!-- Editor content -->\n <div\n ref=\"editorContainer\"\n class=\"rte-content bg-surface px-4 py-3 text-body-large text-on-surface\"\n :style=\"{ minHeight: minHeight }\"\n />\n\n <!-- Link dialog -->\n <MDialog v-model=\"linkDialogOpen\" :title=\"l.insertLink\">\n <MTextField v-model=\"linkUrl\" label=\"URL\" placeholder=\" \" @keydown.enter=\"confirmLink\" />\n <template #actions>\n <MButton variant=\"text\" @click=\"linkDialogOpen = false\">{{ l.cancel }}</MButton>\n <MButton @click=\"confirmLink\">{{ l.insert }}</MButton>\n </template>\n </MDialog>\n\n <!-- Image dialog -->\n <MDialog v-model=\"imageDialogOpen\" :title=\"l.insertImage\">\n <MTextField v-model=\"imageUrl\" :label=\"l.imageUrlLabel\" placeholder=\" \" @keydown.enter=\"confirmImage\" />\n <template #actions>\n <MButton variant=\"text\" @click=\"imageDialogOpen = false\">{{ l.cancel }}</MButton>\n <MButton @click=\"confirmImage\">{{ l.insert }}</MButton>\n </template>\n </MDialog>\n </div>\n</template>\n\n<style scoped>\n.rte-content :deep(.tiptap) {\n outline: none;\n min-height: inherit;\n}\n\n.rte-content :deep(.tiptap p.is-editor-empty:first-child::before) {\n content: attr(data-placeholder);\n float: left;\n color: var(--color-on-surface-variant);\n opacity: 0.5;\n pointer-events: none;\n height: 0;\n}\n\n.rte-content :deep(h1) { font-size: var(--text-headline-large); line-height: var(--text-headline-large--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(h2) { font-size: var(--text-headline-medium); line-height: var(--text-headline-medium--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(h3) { font-size: var(--text-headline-small); line-height: var(--text-headline-small--line-height); font-weight: 600; margin: 0.75em 0 0.25em; }\n.rte-content :deep(p) { margin: 0.5em 0; }\n.rte-content :deep(ul) { list-style-type: disc; padding-left: 1.5em; margin: 0.5em 0; }\n.rte-content :deep(ol) { list-style-type: decimal; padding-left: 1.5em; margin: 0.5em 0; }\n.rte-content :deep(blockquote) { border-left: 3px solid var(--color-primary); padding-left: 1em; margin: 0.5em 0; color: var(--color-on-surface-variant); }\n.rte-content :deep(code) { background: var(--color-surface-container-highest); padding: 0.15em 0.4em; border-radius: 4px; font-size: 0.875em; }\n.rte-content :deep(pre) { background: var(--color-surface-container-highest); padding: 1em; border-radius: 8px; overflow-x: auto; margin: 0.5em 0; }\n.rte-content :deep(pre code) { background: none; padding: 0; }\n.rte-content :deep(a) { color: var(--color-primary); text-decoration: underline; }\n.rte-content :deep(mark) { background: var(--color-tertiary-container); color: var(--color-on-tertiary-container); padding: 0.1em 0.2em; border-radius: 2px; }\n.rte-content :deep(img) { max-width: 100%; height: auto; border-radius: 8px; margin: 0.5em 0; }\n</style>\n"],"mappings":"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"}