@templatical/editor 0.16.1 → 0.16.2

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 (74) hide show
  1. package/dist/{AiFeatureMenu-Rb8G3EBo.js → AiFeatureMenu-DfTYyExg.js} +1 -1
  2. package/dist/{CloudEditor-D88gLBXp.js → CloudEditor-BQyZ_nFg.js} +5 -5
  3. package/dist/{CollaboratorBar-dxCD8jSi.js → CollaboratorBar-DeP7K-zk.js} +1 -1
  4. package/dist/{ColorPicker-CAgMCX3A.js → ColorPicker-CXAbjTaG.js} +7 -3
  5. package/dist/{CountdownToolbar-8XVTOuGX.js → CountdownToolbar-nY9H0BKd.js} +2 -2
  6. package/dist/{ModuleBrowserModal-l4_RCC8m.js → ModuleBrowserModal-CkeYw1e3.js} +4 -4
  7. package/dist/{ModulePreviewCanvas-BqYAr4fz.js → ModulePreviewCanvas-BIMFyYaa.js} +1 -1
  8. package/dist/{NumberWithSuffix-Di-cDy_m.js → NumberWithSuffix-BoZyUoNz.js} +1 -1
  9. package/dist/{ParagraphEditor-DIQ1jmSP.js → ParagraphEditor-DGsTFMxg.js} +76 -86
  10. package/dist/{RichTextEditorContent-DkTJ6KK8.js → RichTextEditorContent-BB_n8vgB.js} +1 -1
  11. package/dist/{SaveModuleDialog-DPo3Raon.js → SaveModuleDialog-Cypt_qOB.js} +2 -2
  12. package/dist/{SnapshotHistory-m7brKV7C.js → SnapshotHistory-DQTH8TCS.js} +1 -1
  13. package/dist/{TestEmailModal-BE9sFEIl.js → TestEmailModal-DqxrL-U9.js} +2 -2
  14. package/dist/{TitleEditor-BATN-k-Q.js → TitleEditor-DoGgnrcb.js} +2 -2
  15. package/dist/{TplModal-DHBcZ1gq.js → TplModal-Ca-29YDD.js} +1 -1
  16. package/dist/{blockTypeIcons-wRchKKx0.js → blockTypeIcons-DVJXg5si.js} +1 -1
  17. package/dist/bundle-stats.json +6 -6
  18. package/dist/cdn/chunks/{AiFeatureMenu-W7VQFAwq.js → AiFeatureMenu-roPglhox.js} +2 -2
  19. package/dist/cdn/chunks/{AiFeatureMenu-W7VQFAwq.js.map → AiFeatureMenu-roPglhox.js.map} +1 -1
  20. package/dist/cdn/chunks/{BlockIssueBadge-ww2vNIfJ.js → BlockIssueBadge-DW_Tt7Wg.js} +2 -2
  21. package/dist/cdn/chunks/{BlockIssueBadge-ww2vNIfJ.js.map → BlockIssueBadge-DW_Tt7Wg.js.map} +1 -1
  22. package/dist/cdn/chunks/{CloudEditor-BVSJ1kvB.js → CloudEditor-CX6y1k3C.js} +9 -9
  23. package/dist/cdn/chunks/{CloudEditor-BVSJ1kvB.js.map → CloudEditor-CX6y1k3C.js.map} +1 -1
  24. package/dist/cdn/chunks/{CollaboratorBar-BFrAua9a.js → CollaboratorBar-Dyrab63H.js} +3 -3
  25. package/dist/cdn/chunks/{CollaboratorBar-BFrAua9a.js.map → CollaboratorBar-Dyrab63H.js.map} +1 -1
  26. package/dist/cdn/chunks/{ColorPicker-DmxMDn-t.js → ColorPicker-BggAWrc9.js} +9 -5
  27. package/dist/cdn/chunks/{ColorPicker-DmxMDn-t.js.map → ColorPicker-BggAWrc9.js.map} +1 -1
  28. package/dist/cdn/chunks/{CountdownBlock-MC-mhtQD.js → CountdownBlock-Bul4tczj.js} +2 -2
  29. package/dist/cdn/chunks/{CountdownBlock-MC-mhtQD.js.map → CountdownBlock-Bul4tczj.js.map} +1 -1
  30. package/dist/cdn/chunks/{CountdownToolbar-dXyr7tz-.js → CountdownToolbar-DYvATR0J.js} +4 -4
  31. package/dist/cdn/chunks/{CountdownToolbar-dXyr7tz-.js.map → CountdownToolbar-DYvATR0J.js.map} +1 -1
  32. package/dist/cdn/chunks/{IssuesPanel-CTxSgViL.js → IssuesPanel-BhHU-hq3.js} +3 -3
  33. package/dist/cdn/chunks/{IssuesPanel-CTxSgViL.js.map → IssuesPanel-BhHU-hq3.js.map} +1 -1
  34. package/dist/cdn/chunks/{ModuleBrowserModal-B5sCsrud.js → ModuleBrowserModal-BGd5Ryyx.js} +5 -5
  35. package/dist/cdn/chunks/{ModuleBrowserModal-B5sCsrud.js.map → ModuleBrowserModal-BGd5Ryyx.js.map} +1 -1
  36. package/dist/cdn/chunks/{ModulePreviewCanvas-DGTGo8kg.js → ModulePreviewCanvas-Hx6SCCjB.js} +2 -2
  37. package/dist/cdn/chunks/{ModulePreviewCanvas-DGTGo8kg.js.map → ModulePreviewCanvas-Hx6SCCjB.js.map} +1 -1
  38. package/dist/cdn/chunks/{NumberWithSuffix-tAHfui6k.js → NumberWithSuffix-BImuhc9K.js} +2 -2
  39. package/dist/cdn/chunks/{NumberWithSuffix-tAHfui6k.js.map → NumberWithSuffix-BImuhc9K.js.map} +1 -1
  40. package/dist/cdn/chunks/{ParagraphEditor-CB5FGRs3.js → ParagraphEditor-K2vENidm.js} +100 -109
  41. package/dist/cdn/chunks/ParagraphEditor-K2vENidm.js.map +1 -0
  42. package/dist/cdn/chunks/{RichTextEditorContent-CPelbtck.js → RichTextEditorContent-B_w3u5lN.js} +3 -3
  43. package/dist/cdn/chunks/{RichTextEditorContent-CPelbtck.js.map → RichTextEditorContent-B_w3u5lN.js.map} +1 -1
  44. package/dist/cdn/chunks/{SaveModuleDialog-7f9uUUEC.js → SaveModuleDialog-Cw-182CB.js} +2 -2
  45. package/dist/cdn/chunks/{SaveModuleDialog-7f9uUUEC.js.map → SaveModuleDialog-Cw-182CB.js.map} +1 -1
  46. package/dist/cdn/chunks/{TitleEditor-C0mYpgs4.js → TitleEditor-CUKlo_Zj.js} +5 -5
  47. package/dist/cdn/chunks/{TitleEditor-C0mYpgs4.js.map → TitleEditor-CUKlo_Zj.js.map} +1 -1
  48. package/dist/cdn/chunks/{blockTypeIcons-BtxaUtlx.js → blockTypeIcons-Cx1FAqL6.js} +3 -3
  49. package/dist/cdn/chunks/{blockTypeIcons-BtxaUtlx.js.map → blockTypeIcons-Cx1FAqL6.js.map} +1 -1
  50. package/dist/cdn/chunks/{extensions-BJ7vaBol.js → extensions-DSxG2wYf.js} +2 -2
  51. package/dist/cdn/chunks/{extensions-BJ7vaBol.js.map → extensions-DSxG2wYf.js.map} +1 -1
  52. package/dist/cdn/chunks/{features-CgbSSCgv.js → features-C-cjT_8L.js} +6 -6
  53. package/dist/cdn/chunks/{features-CgbSSCgv.js.map → features-C-cjT_8L.js.map} +1 -1
  54. package/dist/cdn/chunks/{icons-Dlx5MT1V.js → icons-ay0_fN-T.js} +2 -2
  55. package/dist/cdn/chunks/{icons-Dlx5MT1V.js.map → icons-ay0_fN-T.js.map} +1 -1
  56. package/dist/cdn/chunks/{media-library-BMlykZGq.js → media-library-CkmqPdO4.js} +3 -3
  57. package/dist/cdn/chunks/{media-library-BMlykZGq.js.map → media-library-CkmqPdO4.js.map} +1 -1
  58. package/dist/cdn/chunks/{quality-DsVgXk_j.js → quality-CDNrMw2A.js} +2 -2
  59. package/dist/cdn/chunks/{quality-DsVgXk_j.js.map → quality-CDNrMw2A.js.map} +1 -1
  60. package/dist/cdn/chunks/{renderer-DPvEtVGO.js → renderer-JQ91A09w.js} +4 -4
  61. package/dist/cdn/chunks/renderer-JQ91A09w.js.map +1 -0
  62. package/dist/cdn/chunks/{src-CAdirukY.js → src-Cehu7Hqx.js} +4 -4
  63. package/dist/cdn/chunks/{src-CAdirukY.js.map → src-Cehu7Hqx.js.map} +1 -1
  64. package/dist/cdn/chunks/{styles-D7u4vCpH.js → styles-DBjy3lz9.js} +9 -9
  65. package/dist/cdn/chunks/{styles-D7u4vCpH.js.map → styles-DBjy3lz9.js.map} +1 -1
  66. package/dist/cdn/editor.css +1 -1
  67. package/dist/cdn/editor.js +6 -6
  68. package/dist/style.css +1 -1
  69. package/dist/{styles-B-yhoJnH.js → styles-mvx3k1hf.js} +6 -6
  70. package/dist/templatical-editor.js +4 -4
  71. package/dist/{useEditorCore-CV1ct_17.js → useEditorCore-DtZkR7Vk.js} +2 -2
  72. package/package.json +8 -8
  73. package/dist/cdn/chunks/ParagraphEditor-CB5FGRs3.js.map +0 -1
  74. package/dist/cdn/chunks/renderer-DPvEtVGO.js.map +0 -1
@@ -1,19 +1,19 @@
1
1
  import { K as e, L as t, M as n, P as r, T as i, Z as a, c as o, ct as s, d as c, f as l, g as u, h as d, it as f, l as p, m, ot as h, p as g, st as _, u as v, v as y, x as b, y as x } from "./draggable-D840DIZB.js";
2
- import { $t as S, Qt as C, Rt as w, X as T, Z as E, Zt as D, at as O, ct as k, dn as A, en as ee, k as j, ln as te, ot as M, sn as ne, tt as N, un as re, xt as ie } from "./features-CgbSSCgv.js";
3
- import { B as ae, C as oe, H as se, L as ce, R as le, X as ue, Z as de, b as fe, c as pe, d as me, f as he, g as P, i as ge, l as _e, o as ve, s as F } from "./icons-Dlx5MT1V.js";
4
- import { c as ye, o as be, s as xe } from "./ColorPicker-DmxMDn-t.js";
5
- import { n as I, t as L } from "./RichTextEditorContent-CPelbtck.js";
2
+ import { $t as S, Qt as C, Rt as w, X as T, Z as E, Zt as D, at as O, dn as k, en as ee, k as A, ln as te, ot as j, sn as ne, tt as M, un as re, xt as ie } from "./features-C-cjT_8L.js";
3
+ import { B as ae, C as oe, H as se, L as ce, R as le, X as ue, Z as de, b as fe, c as pe, d as me, f as he, g as N, i as ge, l as _e, o as ve, s as ye } from "./icons-ay0_fN-T.js";
4
+ import { c as P, o as be, r as xe, s as Se, t as F } from "./ColorPicker-BggAWrc9.js";
5
+ import { n as I, t as L } from "./RichTextEditorContent-B_w3u5lN.js";
6
6
  //#region src/components/blocks/EmojiPickerDropdown.vue?vue&type=script&setup=true&lang.ts
7
7
  var R = [
8
8
  "aria-label",
9
9
  "title",
10
10
  "aria-expanded"
11
- ], z = ["aria-label"], B = { class: "tpl:mb-1.5 tpl:text-[10px] tpl:font-medium tpl:tracking-wide tpl:text-[var(--tpl-text-muted)] tpl:uppercase" }, V = { class: "tpl:grid tpl:grid-cols-10 tpl:gap-0.5" }, H = ["aria-label", "onClick"], Se = /* @__PURE__ */ b({
11
+ ], z = ["aria-label"], B = { class: "tpl:mb-1.5 tpl:text-[10px] tpl:font-medium tpl:tracking-wide tpl:text-[var(--tpl-text-muted)] tpl:uppercase" }, V = { class: "tpl:grid tpl:grid-cols-10 tpl:gap-0.5" }, H = ["aria-label", "onClick"], Ce = /* @__PURE__ */ b({
12
12
  __name: "EmojiPickerDropdown",
13
13
  emits: ["insert"],
14
14
  setup(e, { emit: t }) {
15
- let i = t, { categories: c, isOpen: m, toggle: _, close: y } = N(), { t: b, format: S } = w(), C = a(null), T = a(null);
16
- O(C, l(() => m.value)), A(T, () => {
15
+ let i = t, { categories: c, isOpen: m, toggle: _, close: y } = M(), { t: b, format: S } = w(), C = a(null), T = a(null);
16
+ O(C, l(() => m.value)), k(T, () => {
17
17
  m.value && y();
18
18
  });
19
19
  function E(e) {
@@ -32,7 +32,7 @@ var R = [
32
32
  "aria-haspopup": "dialog",
33
33
  "aria-controls": "tpl-emoji-picker",
34
34
  onClick: t[0] ||= (...e) => f(_) && f(_)(...e)
35
- }, [x(f(P), {
35
+ }, [x(f(N), {
36
36
  size: 16,
37
37
  "stroke-width": 2
38
38
  })], 10, R), f(m) ? (n(), u("div", {
@@ -89,11 +89,11 @@ var R = [
89
89
  function q(e, t) {
90
90
  return n(), u("span", K);
91
91
  }
92
- var J = /*#__PURE__*/ M(G, [["render", q]]), Y = [
92
+ var J = /*#__PURE__*/ j(G, [["render", q]]), Y = [
93
93
  "value",
94
94
  "aria-label",
95
95
  "title"
96
- ], X = { value: "" }, Ce = ["value"], Z = /* @__PURE__ */ b({
96
+ ], X = { value: "" }, we = ["value"], Z = /* @__PURE__ */ b({
97
97
  __name: "ToolbarSelect",
98
98
  props: {
99
99
  modelValue: {},
@@ -123,7 +123,7 @@ var J = /*#__PURE__*/ M(G, [["render", q]]), Y = [
123
123
  }, [g("option", X, s(e.placeholder ?? ""), 1), (n(!0), u(v, null, r(e.options, (e) => (n(), u("option", {
124
124
  key: o(e),
125
125
  value: o(e)
126
- }, s(c(e)), 9, Ce))), 128))], 42, Y));
126
+ }, s(c(e)), 9, we))), 128))], 42, Y));
127
127
  }
128
128
  });
129
129
  //#endregion
@@ -133,18 +133,10 @@ function Q(e, t) {
133
133
  }
134
134
  //#endregion
135
135
  //#region src/components/blocks/ParagraphToolbar.vue?vue&type=script&setup=true&lang.ts
136
- var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-center tpl:gap-1" }, Ee = { class: "tpl:relative" }, De = [
137
- "value",
138
- "aria-label",
139
- "title"
140
- ], $ = ["aria-label", "title"], Oe = { class: "tpl:relative" }, ke = [
141
- "value",
142
- "aria-label",
143
- "title"
144
- ], Ae = { class: "tpl:flex tpl:items-center tpl:gap-1" }, je = ["aria-label", "title"], Me = ["aria-label", "title"], Ne = {
136
+ var Te = ["data-tpl-theme", "aria-label"], $ = { class: "tpl:flex tpl:items-center tpl:gap-1" }, Ee = { class: "tpl:flex tpl:items-center tpl:gap-1" }, De = ["aria-label", "title"], Oe = ["aria-label", "title"], ke = {
145
137
  key: 1,
146
138
  class: "tpl:flex tpl:items-center tpl:gap-2 tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]"
147
- }, Pe = /* @__PURE__ */ b({
139
+ }, Ae = /* @__PURE__ */ b({
148
140
  __name: "ParagraphToolbar",
149
141
  props: {
150
142
  editor: {},
@@ -159,8 +151,8 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
159
151
  "add-logic-tag"
160
152
  ],
161
153
  setup(e, { emit: t }) {
162
- let r = e, a = t, o = i(ne, null), p = i(te, null), h = re(C, "ParagraphToolbar"), b = j(), T = i(ee, null), E = i(S, null), O = i(D, null), A = l(() => (T?.isOpen.value ?? !1) || (E?.isOpen.value ?? !1)), { t: M } = w(), N = h.fonts;
163
- function P(e) {
154
+ let r = e, a = t, o = i(ne, null), p = i(te, null), h = re(C, "ParagraphToolbar"), b = A(), T = i(ee, null), E = i(S, null), O = i(D, null), k = l(() => (T?.isOpen.value ?? !1) || (E?.isOpen.value ?? !1)), { t: j } = w(), M = h.fonts;
155
+ function N(e) {
164
156
  r.editor?.chain().focus().insertContent(e).run();
165
157
  }
166
158
  function I(e) {
@@ -189,7 +181,7 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
189
181
  return z() ? Q(B(), e?.linkColor || e?.textColor) : Q(I("color"), e?.textColor);
190
182
  }
191
183
  function U() {
192
- return z() ? B() !== "" : I("color") !== "";
184
+ return z() ? B() : I("color");
193
185
  }
194
186
  function G() {
195
187
  return r.editor?.getAttributes("paragraph").lineHeight || "";
@@ -209,13 +201,13 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
209
201
  let t = r.editor?.chain().focus();
210
202
  e ? t?.setHighlight({ color: e }).run() : t?.unsetHighlight().run();
211
203
  }
212
- return (t, r) => f(b) && !A.value ? (n(), m(c, {
204
+ return (t, r) => f(b) && !k.value ? (n(), m(c, {
213
205
  key: 0,
214
206
  to: f(b)
215
207
  }, [g("div", {
216
208
  "data-tpl-theme": f(p),
217
209
  role: "toolbar",
218
- "aria-label": f(M).paragraphEditor.toolbar,
210
+ "aria-label": f(j).paragraphEditor.toolbar,
219
211
  class: "tpl tpl-text-toolbar tpl:fixed tpl:z-popover tpl:flex tpl:gap-1 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2 tpl:shadow-lg",
220
212
  style: _({
221
213
  ...f(o),
@@ -224,12 +216,12 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
224
216
  transform: "translateY(-100%)",
225
217
  flexDirection: "column"
226
218
  })
227
- }, [!e.isLoading && e.editor ? (n(), u(v, { key: 0 }, [g("div", Te, [
219
+ }, [!e.isLoading && e.editor ? (n(), u(v, { key: 0 }, [g("div", $, [
228
220
  x(Z, {
229
221
  "model-value": I("fontFamily"),
230
- options: f(N),
231
- label: f(M).paragraphEditor.fontFamily,
232
- placeholder: f(M).paragraphEditor.defaultFont,
222
+ options: f(M),
223
+ label: f(j).paragraphEditor.fontFamily,
224
+ placeholder: f(j).paragraphEditor.defaultFont,
233
225
  "width-class": "tpl:w-32",
234
226
  "onUpdate:modelValue": L
235
227
  }, null, 8, [
@@ -241,8 +233,8 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
241
233
  x(Z, {
242
234
  "model-value": I("fontSize"),
243
235
  options: f(be),
244
- label: f(M).paragraphEditor.fontSize,
245
- placeholder: f(M).paragraphEditor.defaultSize,
236
+ label: f(j).paragraphEditor.fontSize,
237
+ placeholder: f(j).paragraphEditor.defaultSize,
246
238
  "width-class": "tpl:w-20",
247
239
  "onUpdate:modelValue": R
248
240
  }, null, 8, [
@@ -252,40 +244,39 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
252
244
  "placeholder"
253
245
  ]),
254
246
  x(J),
255
- g("div", Ee, [g("input", {
256
- type: "color",
257
- class: "tpl:size-8 tpl:cursor-pointer tpl:rounded tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-1",
258
- value: H(),
259
- "aria-label": f(M).paragraphEditor.textColor,
260
- title: f(M).paragraphEditor.textColor,
261
- onInput: r[0] ||= (e) => V(e.target.value)
262
- }, null, 40, De), U() ? (n(), u("button", {
263
- key: 0,
264
- type: "button",
265
- class: "tpl:absolute tpl:-right-1 tpl:-top-1 tpl:flex tpl:size-4 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded-full tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:text-[var(--tpl-text-dim)] tpl:shadow-sm tpl:transition-colors tpl:duration-150 hover:tpl:text-[var(--tpl-text)]",
266
- "aria-label": f(M).colorPicker.clear,
267
- title: f(M).colorPicker.clear,
268
- onClick: r[1] ||= (e) => V("")
269
- }, [x(f(k), {
270
- size: 10,
271
- "stroke-width": 2.5
272
- })], 8, $)) : d("", !0)]),
273
- g("div", Oe, [g("input", {
274
- type: "color",
275
- class: "tpl:size-8 tpl:cursor-pointer tpl:rounded tpl:border tpl:border-[var(--tpl-border)] tpl:p-1",
276
- style: _({ backgroundColor: Y() || "var(--tpl-bg)" }),
277
- value: Y() || f("#ffff00"),
278
- "aria-label": f(M).paragraphEditor.highlightColor,
279
- title: f(M).paragraphEditor.highlightColor,
280
- onInput: r[2] ||= (e) => X(e.target.value)
281
- }, null, 44, ke)]),
247
+ x(F, {
248
+ "swatch-only": "",
249
+ size: "sm",
250
+ "data-testid": "text-color-picker",
251
+ "model-value": U(),
252
+ "seed-color": H(),
253
+ "aria-label": f(j).paragraphEditor.textColor,
254
+ "onUpdate:modelValue": V
255
+ }, null, 8, [
256
+ "model-value",
257
+ "seed-color",
258
+ "aria-label"
259
+ ]),
260
+ x(F, {
261
+ "swatch-only": "",
262
+ size: "sm",
263
+ "data-testid": "highlight-color-picker",
264
+ "model-value": Y(),
265
+ "seed-color": f(xe),
266
+ "aria-label": f(j).paragraphEditor.highlightColor,
267
+ "onUpdate:modelValue": X
268
+ }, null, 8, [
269
+ "model-value",
270
+ "seed-color",
271
+ "aria-label"
272
+ ]),
282
273
  x(J),
283
274
  x(W, {
284
275
  icon: f(de),
285
- label: f(M).paragraphEditor.bold,
276
+ label: f(j).paragraphEditor.bold,
286
277
  active: e.editor.isActive("bold"),
287
278
  "stroke-width": 2.5,
288
- onClick: r[3] ||= (t) => e.editor.chain().focus().toggleBold().run()
279
+ onClick: r[0] ||= (t) => e.editor.chain().focus().toggleBold().run()
289
280
  }, null, 8, [
290
281
  "icon",
291
282
  "label",
@@ -293,9 +284,9 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
293
284
  ]),
294
285
  x(W, {
295
286
  icon: f(se),
296
- label: f(M).paragraphEditor.italic,
287
+ label: f(j).paragraphEditor.italic,
297
288
  active: e.editor.isActive("italic"),
298
- onClick: r[4] ||= (t) => e.editor.chain().focus().toggleItalic().run()
289
+ onClick: r[1] ||= (t) => e.editor.chain().focus().toggleItalic().run()
299
290
  }, null, 8, [
300
291
  "icon",
301
292
  "label",
@@ -303,9 +294,9 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
303
294
  ]),
304
295
  x(W, {
305
296
  icon: f(ge),
306
- label: f(M).paragraphEditor.underline,
297
+ label: f(j).paragraphEditor.underline,
307
298
  active: e.editor.isActive("underline"),
308
- onClick: r[5] ||= (t) => e.editor.chain().focus().toggleUnderline().run()
299
+ onClick: r[2] ||= (t) => e.editor.chain().focus().toggleUnderline().run()
309
300
  }, null, 8, [
310
301
  "icon",
311
302
  "label",
@@ -313,9 +304,9 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
313
304
  ]),
314
305
  x(W, {
315
306
  icon: f(me),
316
- label: f(M).paragraphEditor.strikethrough,
307
+ label: f(j).paragraphEditor.strikethrough,
317
308
  active: e.editor.isActive("strike"),
318
- onClick: r[6] ||= (t) => e.editor.chain().focus().toggleStrike().run()
309
+ onClick: r[3] ||= (t) => e.editor.chain().focus().toggleStrike().run()
319
310
  }, null, 8, [
320
311
  "icon",
321
312
  "label",
@@ -324,9 +315,9 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
324
315
  x(J),
325
316
  x(W, {
326
317
  icon: f(he),
327
- label: f(M).paragraphEditor.subscript,
318
+ label: f(j).paragraphEditor.subscript,
328
319
  active: e.editor.isActive("subscript"),
329
- onClick: r[7] ||= (t) => e.editor.chain().focus().toggleSubscript().run()
320
+ onClick: r[4] ||= (t) => e.editor.chain().focus().toggleSubscript().run()
330
321
  }, null, 8, [
331
322
  "icon",
332
323
  "label",
@@ -334,9 +325,9 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
334
325
  ]),
335
326
  x(W, {
336
327
  icon: f(_e),
337
- label: f(M).paragraphEditor.superscript,
328
+ label: f(j).paragraphEditor.superscript,
338
329
  active: e.editor.isActive("superscript"),
339
- onClick: r[8] ||= (t) => e.editor.chain().focus().toggleSuperscript().run()
330
+ onClick: r[5] ||= (t) => e.editor.chain().focus().toggleSuperscript().run()
340
331
  }, null, 8, [
341
332
  "icon",
342
333
  "label",
@@ -345,20 +336,20 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
345
336
  x(J),
346
337
  x(W, {
347
338
  icon: f(ae),
348
- label: f(M).paragraphEditor.addLink,
339
+ label: f(j).paragraphEditor.addLink,
349
340
  active: e.editor.isActive("link"),
350
- onClick: r[9] ||= (e) => a("open-link-dialog")
341
+ onClick: r[6] ||= (e) => a("open-link-dialog")
351
342
  }, null, 8, [
352
343
  "icon",
353
344
  "label",
354
345
  "active"
355
346
  ])
356
- ]), g("div", Ae, [
347
+ ]), g("div", Ee, [
357
348
  x(W, {
358
349
  icon: f(ce),
359
- label: f(M).paragraphEditor.bulletList,
350
+ label: f(j).paragraphEditor.bulletList,
360
351
  active: e.editor.isActive("bulletList"),
361
- onClick: r[10] ||= (t) => e.editor.chain().focus().toggleBulletList().run()
352
+ onClick: r[7] ||= (t) => e.editor.chain().focus().toggleBulletList().run()
362
353
  }, null, 8, [
363
354
  "icon",
364
355
  "label",
@@ -366,9 +357,9 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
366
357
  ]),
367
358
  x(W, {
368
359
  icon: f(le),
369
- label: f(M).paragraphEditor.numberedList,
360
+ label: f(j).paragraphEditor.numberedList,
370
361
  active: e.editor.isActive("orderedList"),
371
- onClick: r[11] ||= (t) => e.editor.chain().focus().toggleOrderedList().run()
362
+ onClick: r[8] ||= (t) => e.editor.chain().focus().toggleOrderedList().run()
372
363
  }, null, 8, [
373
364
  "icon",
374
365
  "label",
@@ -377,19 +368,19 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
377
368
  x(J),
378
369
  x(W, {
379
370
  icon: f(ve),
380
- label: f(M).paragraphEditor.alignLeft,
371
+ label: f(j).paragraphEditor.alignLeft,
381
372
  active: e.editor.isActive({ textAlign: "left" }),
382
- onClick: r[12] ||= (t) => e.editor.chain().focus().setTextAlign("left").run()
373
+ onClick: r[9] ||= (t) => e.editor.chain().focus().setTextAlign("left").run()
383
374
  }, null, 8, [
384
375
  "icon",
385
376
  "label",
386
377
  "active"
387
378
  ]),
388
379
  x(W, {
389
- icon: f(F),
390
- label: f(M).paragraphEditor.alignCenter,
380
+ icon: f(ye),
381
+ label: f(j).paragraphEditor.alignCenter,
391
382
  active: e.editor.isActive({ textAlign: "center" }),
392
- onClick: r[13] ||= (t) => e.editor.chain().focus().setTextAlign("center").run()
383
+ onClick: r[10] ||= (t) => e.editor.chain().focus().setTextAlign("center").run()
393
384
  }, null, 8, [
394
385
  "icon",
395
386
  "label",
@@ -397,9 +388,9 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
397
388
  ]),
398
389
  x(W, {
399
390
  icon: f(pe),
400
- label: f(M).paragraphEditor.alignRight,
391
+ label: f(j).paragraphEditor.alignRight,
401
392
  active: e.editor.isActive({ textAlign: "right" }),
402
- onClick: r[14] ||= (t) => e.editor.chain().focus().setTextAlign("right").run()
393
+ onClick: r[11] ||= (t) => e.editor.chain().focus().setTextAlign("right").run()
403
394
  }, null, 8, [
404
395
  "icon",
405
396
  "label",
@@ -408,8 +399,8 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
408
399
  x(J),
409
400
  x(Z, {
410
401
  "model-value": G(),
411
- options: f(ye),
412
- label: f(M).paragraphEditor.lineHeight,
402
+ options: f(P),
403
+ label: f(j).paragraphEditor.lineHeight,
413
404
  placeholder: "LH",
414
405
  "width-class": "tpl:w-16",
415
406
  "onUpdate:modelValue": K
@@ -420,8 +411,8 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
420
411
  ]),
421
412
  x(Z, {
422
413
  "model-value": I("letterSpacing"),
423
- options: f(xe),
424
- label: f(M).paragraphEditor.letterSpacing,
414
+ options: f(Se),
415
+ label: f(j).paragraphEditor.letterSpacing,
425
416
  placeholder: "LS",
426
417
  "width-class": "tpl:w-20",
427
418
  "onUpdate:modelValue": q
@@ -433,39 +424,39 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
433
424
  x(J),
434
425
  x(W, {
435
426
  icon: f(oe),
436
- label: f(M).paragraphEditor.clearFormatting,
437
- onClick: r[15] ||= (t) => e.editor.chain().focus().clearNodes().unsetAllMarks().run()
427
+ label: f(j).paragraphEditor.clearFormatting,
428
+ onClick: r[12] ||= (t) => e.editor.chain().focus().clearNodes().unsetAllMarks().run()
438
429
  }, null, 8, ["icon", "label"]),
439
430
  x(J),
440
- x(Se, { onInsert: P }),
431
+ x(Ce, { onInsert: N }),
441
432
  e.canRequestMergeTag ? (n(), u(v, { key: 0 }, [x(J), g("button", {
442
433
  type: "button",
443
434
  class: "tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:duration-150 tpl:hover:bg-[var(--tpl-bg-active)]",
444
- "aria-label": f(M).mergeTag.insert,
445
- title: f(M).mergeTag.insert,
446
- onClick: r[16] ||= (e) => a("add-merge-tag")
435
+ "aria-label": f(j).mergeTag.insert,
436
+ title: f(j).mergeTag.insert,
437
+ onClick: r[13] ||= (e) => a("add-merge-tag")
447
438
  }, [x(f(fe), {
448
439
  size: 16,
449
440
  "stroke-width": 2
450
- }), y(" " + s(f(M).mergeTag.insertShort), 1)], 8, je)], 64)) : d("", !0),
441
+ }), y(" " + s(f(j).mergeTag.insertShort), 1)], 8, De)], 64)) : d("", !0),
451
442
  e.canInsertLogicTag ? (n(), u(v, { key: 1 }, [x(J), g("button", {
452
443
  type: "button",
453
444
  class: "tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:duration-150 tpl:hover:bg-[var(--tpl-bg-active)]",
454
- "aria-label": f(M).logicTag.insert,
455
- title: f(M).logicTag.insert,
445
+ "aria-label": f(j).logicTag.insert,
446
+ title: f(j).logicTag.insert,
456
447
  "data-testid": "insert-logic-button",
457
- onClick: r[17] ||= (e) => a("add-logic-tag")
448
+ onClick: r[14] ||= (e) => a("add-logic-tag")
458
449
  }, [x(f(ue), {
459
450
  size: 16,
460
451
  "stroke-width": 2
461
- }), y(" " + s(f(M).logicTag.insertShort), 1)], 8, Me)], 64)) : d("", !0)
462
- ])], 64)) : (n(), u("div", Ne, [x(f(ie), {
452
+ }), y(" " + s(f(j).logicTag.insertShort), 1)], 8, Oe)], 64)) : d("", !0)
453
+ ])], 64)) : (n(), u("div", ke, [x(f(ie), {
463
454
  class: "tpl-spinner",
464
455
  size: 14,
465
456
  "stroke-width": 2
466
- }), y(" " + s(f(M).errors.editorLoading), 1)]))], 12, we)], 8, ["to"])) : d("", !0);
457
+ }), y(" " + s(f(j).errors.editorLoading), 1)]))], 12, Te)], 8, ["to"])) : d("", !0);
467
458
  }
468
- }), Fe = { class: "tpl-text-editor-wrapper tpl:relative" }, Ie = /* @__PURE__ */ b({
459
+ }), je = { class: "tpl-text-editor-wrapper tpl:relative" }, Me = /* @__PURE__ */ b({
469
460
  __name: "ParagraphEditor",
470
461
  props: {
471
462
  block: {},
@@ -473,7 +464,7 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
473
464
  },
474
465
  emits: ["done"],
475
466
  setup(t, { emit: r }) {
476
- let i = t, a = r, o = j(), { editor: s, EditorContent: c, isLoading: l, initError: d, retry: p, showLinkDialog: m, linkUrl: h, linkColor: g, linkDialogRef: _, canRequestMergeTag: v, canInsertLogicTag: y, openLinkDialog: b, insertLink: S, removeLink: C, closeLinkDialog: w, handleLinkKeydown: D, handleAddMergeTag: O, handleAddLogicTag: k } = T({
467
+ let i = t, a = r, o = A(), { editor: s, EditorContent: c, isLoading: l, initError: d, retry: p, showLinkDialog: m, linkUrl: h, linkColor: g, linkDialogRef: _, canRequestMergeTag: v, canInsertLogicTag: y, openLinkDialog: b, insertLink: S, removeLink: C, closeLinkDialog: w, handleLinkKeydown: D, handleAddMergeTag: O, handleAddLogicTag: k } = T({
477
468
  blockId: () => i.block.id,
478
469
  blockContent: () => i.block.content,
479
470
  onDone: () => a("done"),
@@ -491,7 +482,7 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
491
482
  import("./tiptap-zpXk5mN4.js").then((e) => e.f),
492
483
  import("./tiptap-zpXk5mN4.js").then((e) => e.d),
493
484
  import("./tiptap-zpXk5mN4.js").then((e) => e.u),
494
- import("./extensions-BJ7vaBol.js")
485
+ import("./extensions-DSxG2wYf.js")
495
486
  ]);
496
487
  return {
497
488
  TiptapEditor: a,
@@ -538,8 +529,8 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
538
529
  };
539
530
  }
540
531
  });
541
- return (r, i) => (n(), u("div", Fe, [
542
- x(Pe, {
532
+ return (r, i) => (n(), u("div", je, [
533
+ x(Ae, {
543
534
  editor: f(s),
544
535
  "toolbar-position": t.toolbarPosition,
545
536
  "is-loading": f(l),
@@ -599,6 +590,6 @@ var we = ["data-tpl-theme", "aria-label"], Te = { class: "tpl:flex tpl:items-cen
599
590
  }
600
591
  });
601
592
  //#endregion
602
- export { Ie as default };
593
+ export { Me as default };
603
594
 
604
- //# sourceMappingURL=ParagraphEditor-CB5FGRs3.js.map
595
+ //# sourceMappingURL=ParagraphEditor-K2vENidm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParagraphEditor-K2vENidm.js","names":[],"sources":["../../../src/components/blocks/EmojiPickerDropdown.vue","../../../src/components/blocks/EmojiPickerDropdown.vue","../../../src/components/toolbar/ToolbarIconButton.vue","../../../src/components/toolbar/ToolbarIconButton.vue","../../../src/components/toolbar/ToolbarSeparator.vue","../../../src/components/toolbar/ToolbarSelect.vue","../../../src/components/toolbar/ToolbarSelect.vue","../../../src/utils/richTextColor.ts","../../../src/components/blocks/ParagraphToolbar.vue","../../../src/components/blocks/ParagraphToolbar.vue","../../../src/components/blocks/ParagraphEditor.vue","../../../src/components/blocks/ParagraphEditor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useEmoji, useI18n } from \"../../composables\";\nimport { useFocusTrap } from \"../../composables/useFocusTrap\";\nimport { onClickOutside } from \"@vueuse/core\";\nimport { Smile } from \"@lucide/vue\";\nimport { computed, ref } from \"vue\";\n\nconst emit = defineEmits<{\n (e: \"insert\", emoji: string): void;\n}>();\n\nconst {\n categories: emojiCategories,\n isOpen: showEmojiPicker,\n toggle: toggleEmojiPicker,\n close: closeEmojiPicker,\n} = useEmoji();\n\nconst { t, format } = useI18n();\n\nconst pickerRef = ref<HTMLElement | null>(null);\nconst rootRef = ref<HTMLElement | null>(null);\n\nconst isOpenRef = computed(() => showEmojiPicker.value);\nuseFocusTrap(pickerRef, isOpenRef);\n\nonClickOutside(rootRef, () => {\n if (showEmojiPicker.value) {\n closeEmojiPicker();\n }\n});\n\nfunction handleInsert(emoji: string): void {\n emit(\"insert\", emoji);\n closeEmojiPicker();\n}\n</script>\n\n<template>\n <div ref=\"rootRef\" class=\"tpl:relative\">\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': showEmojiPicker,\n }\"\n :aria-label=\"t.paragraphEditor.insertEmoji\"\n :title=\"t.paragraphEditor.insertEmoji\"\n :aria-expanded=\"showEmojiPicker\"\n aria-haspopup=\"dialog\"\n aria-controls=\"tpl-emoji-picker\"\n @click=\"toggleEmojiPicker\"\n >\n <Smile :size=\"16\" :stroke-width=\"2\" />\n </button>\n <div\n v-if=\"showEmojiPicker\"\n id=\"tpl-emoji-picker\"\n ref=\"pickerRef\"\n role=\"dialog\"\n aria-modal=\"false\"\n :aria-label=\"t.paragraphEditor.insertEmoji\"\n tabindex=\"-1\"\n class=\"tpl-emoji-picker tpl:absolute tpl:top-full tpl:left-0 tpl:z-10 tpl:mt-2 tpl:w-72 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-2 tpl:shadow-lg\"\n @keydown.esc.stop.prevent=\"closeEmojiPicker\"\n >\n <div\n v-for=\"category in emojiCategories\"\n :key=\"category.key\"\n class=\"tpl:mb-2 tpl:last:mb-0\"\n >\n <div\n class=\"tpl:mb-1.5 tpl:text-[10px] tpl:font-medium tpl:tracking-wide tpl:text-[var(--tpl-text-muted)] tpl:uppercase\"\n >\n {{ t.emoji[category.key] }}\n </div>\n <div class=\"tpl:grid tpl:grid-cols-10 tpl:gap-0.5\">\n <button\n v-for=\"emoji in category.emojis\"\n :key=\"emoji\"\n type=\"button\"\n :aria-label=\"format(t.paragraphEditor.emojiItemLabel, { emoji })\"\n class=\"tpl:flex tpl:size-6 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:border-none tpl:bg-transparent tpl:text-base tpl:transition-all tpl:duration-100 tpl:hover:scale-125 tpl:hover:bg-[var(--tpl-bg-active)]\"\n @click=\"handleInsert(emoji)\"\n >\n {{ emoji }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { useEmoji, useI18n } from \"../../composables\";\nimport { useFocusTrap } from \"../../composables/useFocusTrap\";\nimport { onClickOutside } from \"@vueuse/core\";\nimport { Smile } from \"@lucide/vue\";\nimport { computed, ref } from \"vue\";\n\nconst emit = defineEmits<{\n (e: \"insert\", emoji: string): void;\n}>();\n\nconst {\n categories: emojiCategories,\n isOpen: showEmojiPicker,\n toggle: toggleEmojiPicker,\n close: closeEmojiPicker,\n} = useEmoji();\n\nconst { t, format } = useI18n();\n\nconst pickerRef = ref<HTMLElement | null>(null);\nconst rootRef = ref<HTMLElement | null>(null);\n\nconst isOpenRef = computed(() => showEmojiPicker.value);\nuseFocusTrap(pickerRef, isOpenRef);\n\nonClickOutside(rootRef, () => {\n if (showEmojiPicker.value) {\n closeEmojiPicker();\n }\n});\n\nfunction handleInsert(emoji: string): void {\n emit(\"insert\", emoji);\n closeEmojiPicker();\n}\n</script>\n\n<template>\n <div ref=\"rootRef\" class=\"tpl:relative\">\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{\n 'tpl-text-toolbar-btn--active': showEmojiPicker,\n }\"\n :aria-label=\"t.paragraphEditor.insertEmoji\"\n :title=\"t.paragraphEditor.insertEmoji\"\n :aria-expanded=\"showEmojiPicker\"\n aria-haspopup=\"dialog\"\n aria-controls=\"tpl-emoji-picker\"\n @click=\"toggleEmojiPicker\"\n >\n <Smile :size=\"16\" :stroke-width=\"2\" />\n </button>\n <div\n v-if=\"showEmojiPicker\"\n id=\"tpl-emoji-picker\"\n ref=\"pickerRef\"\n role=\"dialog\"\n aria-modal=\"false\"\n :aria-label=\"t.paragraphEditor.insertEmoji\"\n tabindex=\"-1\"\n class=\"tpl-emoji-picker tpl:absolute tpl:top-full tpl:left-0 tpl:z-10 tpl:mt-2 tpl:w-72 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:p-2 tpl:shadow-lg\"\n @keydown.esc.stop.prevent=\"closeEmojiPicker\"\n >\n <div\n v-for=\"category in emojiCategories\"\n :key=\"category.key\"\n class=\"tpl:mb-2 tpl:last:mb-0\"\n >\n <div\n class=\"tpl:mb-1.5 tpl:text-[10px] tpl:font-medium tpl:tracking-wide tpl:text-[var(--tpl-text-muted)] tpl:uppercase\"\n >\n {{ t.emoji[category.key] }}\n </div>\n <div class=\"tpl:grid tpl:grid-cols-10 tpl:gap-0.5\">\n <button\n v-for=\"emoji in category.emojis\"\n :key=\"emoji\"\n type=\"button\"\n :aria-label=\"format(t.paragraphEditor.emojiItemLabel, { emoji })\"\n class=\"tpl:flex tpl:size-6 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:rounded tpl:border-none tpl:bg-transparent tpl:text-base tpl:transition-all tpl:duration-100 tpl:hover:scale-125 tpl:hover:bg-[var(--tpl-bg-active)]\"\n @click=\"handleInsert(emoji)\"\n >\n {{ emoji }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport type { Component } from \"vue\";\n\ndefineProps<{\n icon: Component;\n label: string;\n active?: boolean;\n strokeWidth?: number;\n size?: number;\n}>();\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{ 'tpl-text-toolbar-btn--active': active }\"\n :aria-label=\"label\"\n :title=\"label\"\n :aria-pressed=\"active ? 'true' : 'false'\"\n >\n <component :is=\"icon\" :size=\"size ?? 16\" :stroke-width=\"strokeWidth ?? 2\" />\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport type { Component } from \"vue\";\n\ndefineProps<{\n icon: Component;\n label: string;\n active?: boolean;\n strokeWidth?: number;\n size?: number;\n}>();\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"tpl-text-toolbar-btn\"\n :class=\"{ 'tpl-text-toolbar-btn--active': active }\"\n :aria-label=\"label\"\n :title=\"label\"\n :aria-pressed=\"active ? 'true' : 'false'\"\n >\n <component :is=\"icon\" :size=\"size ?? 16\" :stroke-width=\"strokeWidth ?? 2\" />\n </button>\n</template>\n","<template>\n <span\n class=\"tpl:mx-1 tpl:h-6 tpl:w-px tpl:bg-[var(--tpl-border)]\"\n aria-hidden=\"true\"\n ></span>\n</template>\n","<script setup lang=\"ts\">\ninterface OptionItem {\n value: string;\n label: string;\n}\n\ndefineProps<{\n modelValue: string;\n options: readonly (string | OptionItem)[];\n label: string;\n placeholder?: string;\n widthClass?: string;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: string): void;\n}>();\n\nfunction onChange(e: Event): void {\n emit(\"update:modelValue\", (e.target as HTMLSelectElement).value);\n}\n\nfunction optionValue(opt: string | OptionItem): string {\n return typeof opt === \"string\" ? opt : opt.value;\n}\n\nfunction optionLabel(opt: string | OptionItem): string {\n return typeof opt === \"string\" ? opt : opt.label;\n}\n</script>\n\n<template>\n <select\n :class=\"[\n 'tpl:h-8 tpl:cursor-pointer tpl:rounded tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text)] tpl:outline-none',\n widthClass ?? 'tpl:w-20',\n ]\"\n :value=\"modelValue\"\n :aria-label=\"label\"\n :title=\"label\"\n @change=\"onChange\"\n >\n <option value=\"\">{{ placeholder ?? \"\" }}</option>\n <option\n v-for=\"opt in options\"\n :key=\"optionValue(opt)\"\n :value=\"optionValue(opt)\"\n >\n {{ optionLabel(opt) }}\n </option>\n </select>\n</template>\n","<script setup lang=\"ts\">\ninterface OptionItem {\n value: string;\n label: string;\n}\n\ndefineProps<{\n modelValue: string;\n options: readonly (string | OptionItem)[];\n label: string;\n placeholder?: string;\n widthClass?: string;\n}>();\n\nconst emit = defineEmits<{\n (e: \"update:modelValue\", value: string): void;\n}>();\n\nfunction onChange(e: Event): void {\n emit(\"update:modelValue\", (e.target as HTMLSelectElement).value);\n}\n\nfunction optionValue(opt: string | OptionItem): string {\n return typeof opt === \"string\" ? opt : opt.value;\n}\n\nfunction optionLabel(opt: string | OptionItem): string {\n return typeof opt === \"string\" ? opt : opt.label;\n}\n</script>\n\n<template>\n <select\n :class=\"[\n 'tpl:h-8 tpl:cursor-pointer tpl:rounded tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text)] tpl:outline-none',\n widthClass ?? 'tpl:w-20',\n ]\"\n :value=\"modelValue\"\n :aria-label=\"label\"\n :title=\"label\"\n @change=\"onChange\"\n >\n <option value=\"\">{{ placeholder ?? \"\" }}</option>\n <option\n v-for=\"opt in options\"\n :key=\"optionValue(opt)\"\n :value=\"optionValue(opt)\"\n >\n {{ optionLabel(opt) }}\n </option>\n </select>\n</template>\n","import { DEFAULT_TEXT_COLOR } from \"../constants/styleConstants\";\n\n/**\n * The color a rich-text selection actually renders as, for display in the\n * text-color control (issue #373).\n *\n * Priority: an explicit inline text-color mark on the selection wins; otherwise\n * the text inherits the document-level `textColor`; if that too is unset (older\n * content predating document text color), fall back to the built-in default.\n *\n * A native `<input type=\"color\">` can't represent \"no color\", so before this it\n * always painted a hard-coded `#000000` when no inline mark existed — which both\n * looked like an explicit choice and didn't even match the real inherited color\n * (`#1a1a1a`). Resolving the effective color keeps the swatch truthful: it shows\n * the color the text is actually rendered in, whatever level it comes from.\n */\nexport function resolveEffectiveTextColor(\n explicitColor: string,\n documentTextColor: string | undefined,\n): string {\n return explicitColor || documentTextColor || DEFAULT_TEXT_COLOR;\n}\n","<script setup lang=\"ts\">\nimport ColorPicker from \"../ColorPicker.vue\";\nimport EmojiPickerDropdown from \"./EmojiPickerDropdown.vue\";\nimport ToolbarIconButton from \"../toolbar/ToolbarIconButton.vue\";\nimport ToolbarSeparator from \"../toolbar/ToolbarSeparator.vue\";\nimport ToolbarSelect from \"../toolbar/ToolbarSelect.vue\";\nimport { useI18n } from \"../../composables\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n AlignCenter,\n AlignLeft,\n AlignRight,\n Bold,\n Italic,\n Braces,\n Link,\n List,\n ListOrdered,\n LoaderCircle,\n RemoveFormatting,\n ScanLine,\n Strikethrough,\n Subscript,\n Superscript,\n Underline,\n} from \"@lucide/vue\";\nimport { computed, inject } from \"vue\";\nimport {\n EDITOR_KEY,\n THEME_STYLES_KEY,\n UI_THEME_KEY,\n FONTS_MANAGER_KEY,\n MERGE_TAG_PICKER_KEY,\n LOGIC_TAG_PICKER_KEY,\n requireInject,\n} from \"../../keys\";\nimport {\n DEFAULT_HIGHLIGHT_COLOR,\n FONT_SIZE_OPTIONS,\n LINE_HEIGHT_OPTIONS,\n LETTER_SPACING_OPTIONS,\n} from \"../../constants/styleConstants\";\nimport { resolveEffectiveTextColor } from \"../../utils/richTextColor\";\n\nconst props = defineProps<{\n editor: Editor | null;\n toolbarPosition: { top: number; left: number };\n isLoading: boolean;\n canRequestMergeTag: boolean;\n canInsertLogicTag: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"open-link-dialog\"): void;\n (e: \"add-merge-tag\"): void;\n (e: \"add-logic-tag\"): void;\n}>();\n\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst tplUiTheme = inject(UI_THEME_KEY, null);\nconst fontsManager = requireInject(FONTS_MANAGER_KEY, \"ParagraphToolbar\");\nconst popoverRoot = usePopoverRoot();\n// Picker may be null in non-editor contexts (e.g. isolated component tests).\n// When it's provided AND open, hide the floating toolbar — leaving it\n// visible behind the modal is visually noisy and the toolbar's Tailwind\n// z-index utility doesn't compile reliably, so it can sometimes paint\n// over the modal backdrop.\nconst picker = inject(MERGE_TAG_PICKER_KEY, null);\nconst logicPicker = inject(LOGIC_TAG_PICKER_KEY, null);\n// Editor may be absent in isolated tests; used only to resolve the inherited\n// document text color for the text-color swatch.\nconst editorReturn = inject(EDITOR_KEY, null);\n// Hide the floating toolbar while either built-in picker modal is open, so it\n// doesn't overlap the dialog.\nconst pickerIsOpen = computed(\n () => (picker?.isOpen.value ?? false) || (logicPicker?.isOpen.value ?? false),\n);\n\nconst { t } = useI18n();\n\nconst fontFamilies = fontsManager.fonts;\n\nfunction insertEmoji(emoji: string): void {\n props.editor?.chain().focus().insertContent(emoji).run();\n}\n\nfunction textStyleAttr(attr: string): string {\n return (props.editor?.getAttributes(\"textStyle\")[attr] as string) || \"\";\n}\n\nfunction setFontFamily(family: string): void {\n const chain = props.editor?.chain().focus();\n if (family) chain?.setFontFamily(family).run();\n else chain?.unsetFontFamily().run();\n}\n\nfunction setFontSize(size: string): void {\n const chain = props.editor?.chain().focus();\n if (size) chain?.setFontSize(size).run();\n else chain?.unsetFontSize().run();\n}\n\n// When the selection is a link, the color control operates on the link itself\n// (its `color` attribute → inline on the `<a>`) so the link's text and underline\n// stay in sync; otherwise it applies a plain inline text-color mark.\nfunction isLinkSelection(): boolean {\n return props.editor?.isActive(\"link\") ?? false;\n}\n\nfunction linkColorAttr(): string {\n return (props.editor?.getAttributes(\"link\").color as string) || \"\";\n}\n\n// Set (or clear, when empty) the color of the current selection. On a link the\n// whole link is recolored (extendMarkRange) so it doesn't split into segments.\nfunction setColor(color: string): void {\n const chain = props.editor?.chain().focus();\n if (!chain) return;\n if (isLinkSelection()) {\n chain.extendMarkRange(\"link\").updateAttributes(\"link\", {\n color: color || null,\n });\n // A per-link color takes absolute priority over any inner text-color: strip\n // the inline text color on the link range so the `<a>` color alone drives\n // the glyphs and the underline (mirrors useRichTextLinkDialog.insertLink).\n // Only when setting a color — clearing leaves the text color untouched.\n if (color) chain.unsetColor();\n chain.run();\n } else if (color) {\n // A text color applied over a selection that includes a link unifies the\n // link with it: update the link's own color so the `<a>` (which paints the\n // underline and is what the dialog/toolbar read) matches the recolored\n // glyphs. A no-op on a selection with no link. Mirror of the link branch\n // above — either way a link never ends up with a text color fighting its\n // own color.\n chain.setColor(color).updateAttributes(\"link\", { color }).run();\n } else {\n chain.unsetColor().run();\n }\n}\n\n// The color the current selection actually renders in — a link's own color (else\n// the effective document link color: link color, then text color), or for plain\n// text the inline mark else the document text color. Keeps the swatch truthful\n// rather than showing a hard-coded default (issue #373 / per-link color).\nfunction effectiveTextColor(): string {\n const settings = editorReturn?.content.value.settings;\n if (isLinkSelection()) {\n return resolveEffectiveTextColor(\n linkColorAttr(),\n settings?.linkColor || settings?.textColor,\n );\n }\n return resolveEffectiveTextColor(textStyleAttr(\"color\"), settings?.textColor);\n}\n\n// The selection's own explicit color: a link's color when on a link, else the\n// inline text-color mark. May be \"\" when the selection only inherits its color\n// — that drives the swatch's set/unset state, while `effectiveTextColor()`\n// seeds the wheel so it still opens on the real rendered color.\nfunction explicitTextColor(): string {\n return isLinkSelection() ? linkColorAttr() : textStyleAttr(\"color\");\n}\n\nfunction getCurrentLineHeight(): string {\n return (props.editor?.getAttributes(\"paragraph\").lineHeight as string) || \"\";\n}\n\nfunction setLineHeight(value: string): void {\n const chain = props.editor?.chain().focus();\n if (value) chain?.setLineHeight(value).run();\n else chain?.unsetLineHeight().run();\n}\n\nfunction setLetterSpacing(value: string): void {\n const chain = props.editor?.chain().focus();\n if (value && value !== \"normal\") chain?.setLetterSpacing(value).run();\n else chain?.unsetLetterSpacing().run();\n}\n\nfunction getCurrentHighlight(): string {\n return (props.editor?.getAttributes(\"highlight\").color as string) || \"\";\n}\n\nfunction setHighlight(color: string): void {\n const chain = props.editor?.chain().focus();\n if (color) chain?.setHighlight({ color }).run();\n else chain?.unsetHighlight().run();\n}\n</script>\n\n<template>\n <Teleport v-if=\"popoverRoot && !pickerIsOpen\" :to=\"popoverRoot\">\n <div\n :data-tpl-theme=\"tplUiTheme\"\n role=\"toolbar\"\n :aria-label=\"t.paragraphEditor.toolbar\"\n class=\"tpl tpl-text-toolbar tpl:fixed tpl:z-popover tpl:flex tpl:gap-1 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2 tpl:shadow-lg\"\n :style=\"{\n ...themeStyles,\n top: `${toolbarPosition.top}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateY(-100%)',\n flexDirection: 'column',\n }\"\n >\n <template v-if=\"!isLoading && editor\">\n <!-- Row 1: Font family, Font size, Text color, Bold/Italic/Underline/Strikethrough -->\n <div class=\"tpl:flex tpl:items-center tpl:gap-1\">\n <ToolbarSelect\n :model-value=\"textStyleAttr('fontFamily')\"\n :options=\"fontFamilies\"\n :label=\"t.paragraphEditor.fontFamily\"\n :placeholder=\"t.paragraphEditor.defaultFont\"\n width-class=\"tpl:w-32\"\n @update:model-value=\"setFontFamily\"\n />\n <ToolbarSelect\n :model-value=\"textStyleAttr('fontSize')\"\n :options=\"FONT_SIZE_OPTIONS\"\n :label=\"t.paragraphEditor.fontSize\"\n :placeholder=\"t.paragraphEditor.defaultSize\"\n width-class=\"tpl:w-20\"\n @update:model-value=\"setFontSize\"\n />\n <ToolbarSeparator />\n <ColorPicker\n swatch-only\n size=\"sm\"\n data-testid=\"text-color-picker\"\n :model-value=\"explicitTextColor()\"\n :seed-color=\"effectiveTextColor()\"\n :aria-label=\"t.paragraphEditor.textColor\"\n @update:model-value=\"setColor\"\n />\n <ColorPicker\n swatch-only\n size=\"sm\"\n data-testid=\"highlight-color-picker\"\n :model-value=\"getCurrentHighlight()\"\n :seed-color=\"DEFAULT_HIGHLIGHT_COLOR\"\n :aria-label=\"t.paragraphEditor.highlightColor\"\n @update:model-value=\"setHighlight\"\n />\n <ToolbarSeparator />\n <ToolbarIconButton\n :icon=\"Bold\"\n :label=\"t.paragraphEditor.bold\"\n :active=\"editor.isActive('bold')\"\n :stroke-width=\"2.5\"\n @click=\"editor.chain().focus().toggleBold().run()\"\n />\n <ToolbarIconButton\n :icon=\"Italic\"\n :label=\"t.paragraphEditor.italic\"\n :active=\"editor.isActive('italic')\"\n @click=\"editor.chain().focus().toggleItalic().run()\"\n />\n <ToolbarIconButton\n :icon=\"Underline\"\n :label=\"t.paragraphEditor.underline\"\n :active=\"editor.isActive('underline')\"\n @click=\"editor.chain().focus().toggleUnderline().run()\"\n />\n <ToolbarIconButton\n :icon=\"Strikethrough\"\n :label=\"t.paragraphEditor.strikethrough\"\n :active=\"editor.isActive('strike')\"\n @click=\"editor.chain().focus().toggleStrike().run()\"\n />\n <ToolbarSeparator />\n <ToolbarIconButton\n :icon=\"Subscript\"\n :label=\"t.paragraphEditor.subscript\"\n :active=\"editor.isActive('subscript')\"\n @click=\"editor.chain().focus().toggleSubscript().run()\"\n />\n <ToolbarIconButton\n :icon=\"Superscript\"\n :label=\"t.paragraphEditor.superscript\"\n :active=\"editor.isActive('superscript')\"\n @click=\"editor.chain().focus().toggleSuperscript().run()\"\n />\n <ToolbarSeparator />\n <ToolbarIconButton\n :icon=\"Link\"\n :label=\"t.paragraphEditor.addLink\"\n :active=\"editor.isActive('link')\"\n @click=\"emit('open-link-dialog')\"\n />\n </div>\n <!-- Row 2: Lists, Alignment, LH, LS, Clear, Emoji, Merge tags -->\n <div class=\"tpl:flex tpl:items-center tpl:gap-1\">\n <ToolbarIconButton\n :icon=\"List\"\n :label=\"t.paragraphEditor.bulletList\"\n :active=\"editor.isActive('bulletList')\"\n @click=\"editor.chain().focus().toggleBulletList().run()\"\n />\n <ToolbarIconButton\n :icon=\"ListOrdered\"\n :label=\"t.paragraphEditor.numberedList\"\n :active=\"editor.isActive('orderedList')\"\n @click=\"editor.chain().focus().toggleOrderedList().run()\"\n />\n <ToolbarSeparator />\n <ToolbarIconButton\n :icon=\"AlignLeft\"\n :label=\"t.paragraphEditor.alignLeft\"\n :active=\"editor.isActive({ textAlign: 'left' })\"\n @click=\"editor.chain().focus().setTextAlign('left').run()\"\n />\n <ToolbarIconButton\n :icon=\"AlignCenter\"\n :label=\"t.paragraphEditor.alignCenter\"\n :active=\"editor.isActive({ textAlign: 'center' })\"\n @click=\"editor.chain().focus().setTextAlign('center').run()\"\n />\n <ToolbarIconButton\n :icon=\"AlignRight\"\n :label=\"t.paragraphEditor.alignRight\"\n :active=\"editor.isActive({ textAlign: 'right' })\"\n @click=\"editor.chain().focus().setTextAlign('right').run()\"\n />\n <ToolbarSeparator />\n <ToolbarSelect\n :model-value=\"getCurrentLineHeight()\"\n :options=\"LINE_HEIGHT_OPTIONS\"\n :label=\"t.paragraphEditor.lineHeight\"\n placeholder=\"LH\"\n width-class=\"tpl:w-16\"\n @update:model-value=\"setLineHeight\"\n />\n <ToolbarSelect\n :model-value=\"textStyleAttr('letterSpacing')\"\n :options=\"LETTER_SPACING_OPTIONS\"\n :label=\"t.paragraphEditor.letterSpacing\"\n placeholder=\"LS\"\n width-class=\"tpl:w-20\"\n @update:model-value=\"setLetterSpacing\"\n />\n <ToolbarSeparator />\n <ToolbarIconButton\n :icon=\"RemoveFormatting\"\n :label=\"t.paragraphEditor.clearFormatting\"\n @click=\"editor.chain().focus().clearNodes().unsetAllMarks().run()\"\n />\n <ToolbarSeparator />\n <EmojiPickerDropdown @insert=\"insertEmoji\" />\n <template v-if=\"canRequestMergeTag\">\n <ToolbarSeparator />\n <button\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:duration-150 tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.mergeTag.insert\"\n :title=\"t.mergeTag.insert\"\n @click=\"emit('add-merge-tag')\"\n >\n <ScanLine :size=\"16\" :stroke-width=\"2\" />\n {{ t.mergeTag.insertShort }}\n </button>\n </template>\n <template v-if=\"canInsertLogicTag\">\n <ToolbarSeparator />\n <button\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:duration-150 tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.logicTag.insert\"\n :title=\"t.logicTag.insert\"\n data-testid=\"insert-logic-button\"\n @click=\"emit('add-logic-tag')\"\n >\n <Braces :size=\"16\" :stroke-width=\"2\" />\n {{ t.logicTag.insertShort }}\n </button>\n </template>\n </div>\n </template>\n <template v-else>\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n <LoaderCircle class=\"tpl-spinner\" :size=\"14\" :stroke-width=\"2\" />\n {{ t.errors.editorLoading }}\n </div>\n </template>\n </div>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport ColorPicker from \"../ColorPicker.vue\";\nimport EmojiPickerDropdown from \"./EmojiPickerDropdown.vue\";\nimport ToolbarIconButton from \"../toolbar/ToolbarIconButton.vue\";\nimport ToolbarSeparator from \"../toolbar/ToolbarSeparator.vue\";\nimport ToolbarSelect from \"../toolbar/ToolbarSelect.vue\";\nimport { useI18n } from \"../../composables\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n AlignCenter,\n AlignLeft,\n AlignRight,\n Bold,\n Italic,\n Braces,\n Link,\n List,\n ListOrdered,\n LoaderCircle,\n RemoveFormatting,\n ScanLine,\n Strikethrough,\n Subscript,\n Superscript,\n Underline,\n} from \"@lucide/vue\";\nimport { computed, inject } from \"vue\";\nimport {\n EDITOR_KEY,\n THEME_STYLES_KEY,\n UI_THEME_KEY,\n FONTS_MANAGER_KEY,\n MERGE_TAG_PICKER_KEY,\n LOGIC_TAG_PICKER_KEY,\n requireInject,\n} from \"../../keys\";\nimport {\n DEFAULT_HIGHLIGHT_COLOR,\n FONT_SIZE_OPTIONS,\n LINE_HEIGHT_OPTIONS,\n LETTER_SPACING_OPTIONS,\n} from \"../../constants/styleConstants\";\nimport { resolveEffectiveTextColor } from \"../../utils/richTextColor\";\n\nconst props = defineProps<{\n editor: Editor | null;\n toolbarPosition: { top: number; left: number };\n isLoading: boolean;\n canRequestMergeTag: boolean;\n canInsertLogicTag: boolean;\n}>();\n\nconst emit = defineEmits<{\n (e: \"open-link-dialog\"): void;\n (e: \"add-merge-tag\"): void;\n (e: \"add-logic-tag\"): void;\n}>();\n\nconst themeStyles = inject(THEME_STYLES_KEY, null);\nconst tplUiTheme = inject(UI_THEME_KEY, null);\nconst fontsManager = requireInject(FONTS_MANAGER_KEY, \"ParagraphToolbar\");\nconst popoverRoot = usePopoverRoot();\n// Picker may be null in non-editor contexts (e.g. isolated component tests).\n// When it's provided AND open, hide the floating toolbar — leaving it\n// visible behind the modal is visually noisy and the toolbar's Tailwind\n// z-index utility doesn't compile reliably, so it can sometimes paint\n// over the modal backdrop.\nconst picker = inject(MERGE_TAG_PICKER_KEY, null);\nconst logicPicker = inject(LOGIC_TAG_PICKER_KEY, null);\n// Editor may be absent in isolated tests; used only to resolve the inherited\n// document text color for the text-color swatch.\nconst editorReturn = inject(EDITOR_KEY, null);\n// Hide the floating toolbar while either built-in picker modal is open, so it\n// doesn't overlap the dialog.\nconst pickerIsOpen = computed(\n () => (picker?.isOpen.value ?? false) || (logicPicker?.isOpen.value ?? false),\n);\n\nconst { t } = useI18n();\n\nconst fontFamilies = fontsManager.fonts;\n\nfunction insertEmoji(emoji: string): void {\n props.editor?.chain().focus().insertContent(emoji).run();\n}\n\nfunction textStyleAttr(attr: string): string {\n return (props.editor?.getAttributes(\"textStyle\")[attr] as string) || \"\";\n}\n\nfunction setFontFamily(family: string): void {\n const chain = props.editor?.chain().focus();\n if (family) chain?.setFontFamily(family).run();\n else chain?.unsetFontFamily().run();\n}\n\nfunction setFontSize(size: string): void {\n const chain = props.editor?.chain().focus();\n if (size) chain?.setFontSize(size).run();\n else chain?.unsetFontSize().run();\n}\n\n// When the selection is a link, the color control operates on the link itself\n// (its `color` attribute → inline on the `<a>`) so the link's text and underline\n// stay in sync; otherwise it applies a plain inline text-color mark.\nfunction isLinkSelection(): boolean {\n return props.editor?.isActive(\"link\") ?? false;\n}\n\nfunction linkColorAttr(): string {\n return (props.editor?.getAttributes(\"link\").color as string) || \"\";\n}\n\n// Set (or clear, when empty) the color of the current selection. On a link the\n// whole link is recolored (extendMarkRange) so it doesn't split into segments.\nfunction setColor(color: string): void {\n const chain = props.editor?.chain().focus();\n if (!chain) return;\n if (isLinkSelection()) {\n chain.extendMarkRange(\"link\").updateAttributes(\"link\", {\n color: color || null,\n });\n // A per-link color takes absolute priority over any inner text-color: strip\n // the inline text color on the link range so the `<a>` color alone drives\n // the glyphs and the underline (mirrors useRichTextLinkDialog.insertLink).\n // Only when setting a color — clearing leaves the text color untouched.\n if (color) chain.unsetColor();\n chain.run();\n } else if (color) {\n // A text color applied over a selection that includes a link unifies the\n // link with it: update the link's own color so the `<a>` (which paints the\n // underline and is what the dialog/toolbar read) matches the recolored\n // glyphs. A no-op on a selection with no link. Mirror of the link branch\n // above — either way a link never ends up with a text color fighting its\n // own color.\n chain.setColor(color).updateAttributes(\"link\", { color }).run();\n } else {\n chain.unsetColor().run();\n }\n}\n\n// The color the current selection actually renders in — a link's own color (else\n// the effective document link color: link color, then text color), or for plain\n// text the inline mark else the document text color. Keeps the swatch truthful\n// rather than showing a hard-coded default (issue #373 / per-link color).\nfunction effectiveTextColor(): string {\n const settings = editorReturn?.content.value.settings;\n if (isLinkSelection()) {\n return resolveEffectiveTextColor(\n linkColorAttr(),\n settings?.linkColor || settings?.textColor,\n );\n }\n return resolveEffectiveTextColor(textStyleAttr(\"color\"), settings?.textColor);\n}\n\n// The selection's own explicit color: a link's color when on a link, else the\n// inline text-color mark. May be \"\" when the selection only inherits its color\n// — that drives the swatch's set/unset state, while `effectiveTextColor()`\n// seeds the wheel so it still opens on the real rendered color.\nfunction explicitTextColor(): string {\n return isLinkSelection() ? linkColorAttr() : textStyleAttr(\"color\");\n}\n\nfunction getCurrentLineHeight(): string {\n return (props.editor?.getAttributes(\"paragraph\").lineHeight as string) || \"\";\n}\n\nfunction setLineHeight(value: string): void {\n const chain = props.editor?.chain().focus();\n if (value) chain?.setLineHeight(value).run();\n else chain?.unsetLineHeight().run();\n}\n\nfunction setLetterSpacing(value: string): void {\n const chain = props.editor?.chain().focus();\n if (value && value !== \"normal\") chain?.setLetterSpacing(value).run();\n else chain?.unsetLetterSpacing().run();\n}\n\nfunction getCurrentHighlight(): string {\n return (props.editor?.getAttributes(\"highlight\").color as string) || \"\";\n}\n\nfunction setHighlight(color: string): void {\n const chain = props.editor?.chain().focus();\n if (color) chain?.setHighlight({ color }).run();\n else chain?.unsetHighlight().run();\n}\n</script>\n\n<template>\n <Teleport v-if=\"popoverRoot && !pickerIsOpen\" :to=\"popoverRoot\">\n <div\n :data-tpl-theme=\"tplUiTheme\"\n role=\"toolbar\"\n :aria-label=\"t.paragraphEditor.toolbar\"\n class=\"tpl tpl-text-toolbar tpl:fixed tpl:z-popover tpl:flex tpl:gap-1 tpl:rounded-lg tpl:border tpl:border-[var(--tpl-border)] tpl:bg-[var(--tpl-bg)] tpl:px-3 tpl:py-2 tpl:shadow-lg\"\n :style=\"{\n ...themeStyles,\n top: `${toolbarPosition.top}px`,\n left: `${toolbarPosition.left}px`,\n transform: 'translateY(-100%)',\n flexDirection: 'column',\n }\"\n >\n <template v-if=\"!isLoading && editor\">\n <!-- Row 1: Font family, Font size, Text color, Bold/Italic/Underline/Strikethrough -->\n <div class=\"tpl:flex tpl:items-center tpl:gap-1\">\n <ToolbarSelect\n :model-value=\"textStyleAttr('fontFamily')\"\n :options=\"fontFamilies\"\n :label=\"t.paragraphEditor.fontFamily\"\n :placeholder=\"t.paragraphEditor.defaultFont\"\n width-class=\"tpl:w-32\"\n @update:model-value=\"setFontFamily\"\n />\n <ToolbarSelect\n :model-value=\"textStyleAttr('fontSize')\"\n :options=\"FONT_SIZE_OPTIONS\"\n :label=\"t.paragraphEditor.fontSize\"\n :placeholder=\"t.paragraphEditor.defaultSize\"\n width-class=\"tpl:w-20\"\n @update:model-value=\"setFontSize\"\n />\n <ToolbarSeparator />\n <ColorPicker\n swatch-only\n size=\"sm\"\n data-testid=\"text-color-picker\"\n :model-value=\"explicitTextColor()\"\n :seed-color=\"effectiveTextColor()\"\n :aria-label=\"t.paragraphEditor.textColor\"\n @update:model-value=\"setColor\"\n />\n <ColorPicker\n swatch-only\n size=\"sm\"\n data-testid=\"highlight-color-picker\"\n :model-value=\"getCurrentHighlight()\"\n :seed-color=\"DEFAULT_HIGHLIGHT_COLOR\"\n :aria-label=\"t.paragraphEditor.highlightColor\"\n @update:model-value=\"setHighlight\"\n />\n <ToolbarSeparator />\n <ToolbarIconButton\n :icon=\"Bold\"\n :label=\"t.paragraphEditor.bold\"\n :active=\"editor.isActive('bold')\"\n :stroke-width=\"2.5\"\n @click=\"editor.chain().focus().toggleBold().run()\"\n />\n <ToolbarIconButton\n :icon=\"Italic\"\n :label=\"t.paragraphEditor.italic\"\n :active=\"editor.isActive('italic')\"\n @click=\"editor.chain().focus().toggleItalic().run()\"\n />\n <ToolbarIconButton\n :icon=\"Underline\"\n :label=\"t.paragraphEditor.underline\"\n :active=\"editor.isActive('underline')\"\n @click=\"editor.chain().focus().toggleUnderline().run()\"\n />\n <ToolbarIconButton\n :icon=\"Strikethrough\"\n :label=\"t.paragraphEditor.strikethrough\"\n :active=\"editor.isActive('strike')\"\n @click=\"editor.chain().focus().toggleStrike().run()\"\n />\n <ToolbarSeparator />\n <ToolbarIconButton\n :icon=\"Subscript\"\n :label=\"t.paragraphEditor.subscript\"\n :active=\"editor.isActive('subscript')\"\n @click=\"editor.chain().focus().toggleSubscript().run()\"\n />\n <ToolbarIconButton\n :icon=\"Superscript\"\n :label=\"t.paragraphEditor.superscript\"\n :active=\"editor.isActive('superscript')\"\n @click=\"editor.chain().focus().toggleSuperscript().run()\"\n />\n <ToolbarSeparator />\n <ToolbarIconButton\n :icon=\"Link\"\n :label=\"t.paragraphEditor.addLink\"\n :active=\"editor.isActive('link')\"\n @click=\"emit('open-link-dialog')\"\n />\n </div>\n <!-- Row 2: Lists, Alignment, LH, LS, Clear, Emoji, Merge tags -->\n <div class=\"tpl:flex tpl:items-center tpl:gap-1\">\n <ToolbarIconButton\n :icon=\"List\"\n :label=\"t.paragraphEditor.bulletList\"\n :active=\"editor.isActive('bulletList')\"\n @click=\"editor.chain().focus().toggleBulletList().run()\"\n />\n <ToolbarIconButton\n :icon=\"ListOrdered\"\n :label=\"t.paragraphEditor.numberedList\"\n :active=\"editor.isActive('orderedList')\"\n @click=\"editor.chain().focus().toggleOrderedList().run()\"\n />\n <ToolbarSeparator />\n <ToolbarIconButton\n :icon=\"AlignLeft\"\n :label=\"t.paragraphEditor.alignLeft\"\n :active=\"editor.isActive({ textAlign: 'left' })\"\n @click=\"editor.chain().focus().setTextAlign('left').run()\"\n />\n <ToolbarIconButton\n :icon=\"AlignCenter\"\n :label=\"t.paragraphEditor.alignCenter\"\n :active=\"editor.isActive({ textAlign: 'center' })\"\n @click=\"editor.chain().focus().setTextAlign('center').run()\"\n />\n <ToolbarIconButton\n :icon=\"AlignRight\"\n :label=\"t.paragraphEditor.alignRight\"\n :active=\"editor.isActive({ textAlign: 'right' })\"\n @click=\"editor.chain().focus().setTextAlign('right').run()\"\n />\n <ToolbarSeparator />\n <ToolbarSelect\n :model-value=\"getCurrentLineHeight()\"\n :options=\"LINE_HEIGHT_OPTIONS\"\n :label=\"t.paragraphEditor.lineHeight\"\n placeholder=\"LH\"\n width-class=\"tpl:w-16\"\n @update:model-value=\"setLineHeight\"\n />\n <ToolbarSelect\n :model-value=\"textStyleAttr('letterSpacing')\"\n :options=\"LETTER_SPACING_OPTIONS\"\n :label=\"t.paragraphEditor.letterSpacing\"\n placeholder=\"LS\"\n width-class=\"tpl:w-20\"\n @update:model-value=\"setLetterSpacing\"\n />\n <ToolbarSeparator />\n <ToolbarIconButton\n :icon=\"RemoveFormatting\"\n :label=\"t.paragraphEditor.clearFormatting\"\n @click=\"editor.chain().focus().clearNodes().unsetAllMarks().run()\"\n />\n <ToolbarSeparator />\n <EmojiPickerDropdown @insert=\"insertEmoji\" />\n <template v-if=\"canRequestMergeTag\">\n <ToolbarSeparator />\n <button\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:duration-150 tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.mergeTag.insert\"\n :title=\"t.mergeTag.insert\"\n @click=\"emit('add-merge-tag')\"\n >\n <ScanLine :size=\"16\" :stroke-width=\"2\" />\n {{ t.mergeTag.insertShort }}\n </button>\n </template>\n <template v-if=\"canInsertLogicTag\">\n <ToolbarSeparator />\n <button\n type=\"button\"\n class=\"tpl:flex tpl:h-8 tpl:cursor-pointer tpl:items-center tpl:justify-center tpl:gap-1.5 tpl:rounded tpl:border-none tpl:bg-transparent tpl:px-2.5 tpl:text-xs tpl:font-medium tpl:text-[var(--tpl-text)] tpl:transition-all tpl:duration-150 tpl:hover:bg-[var(--tpl-bg-active)]\"\n :aria-label=\"t.logicTag.insert\"\n :title=\"t.logicTag.insert\"\n data-testid=\"insert-logic-button\"\n @click=\"emit('add-logic-tag')\"\n >\n <Braces :size=\"16\" :stroke-width=\"2\" />\n {{ t.logicTag.insertShort }}\n </button>\n </template>\n </div>\n </template>\n <template v-else>\n <div\n class=\"tpl:flex tpl:items-center tpl:gap-2 tpl:px-2 tpl:text-xs tpl:text-[var(--tpl-text-dim)]\"\n >\n <LoaderCircle class=\"tpl-spinner\" :size=\"14\" :stroke-width=\"2\" />\n {{ t.errors.editorLoading }}\n </div>\n </template>\n </div>\n </Teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { useRichTextEditor } from \"../../composables/useRichTextEditor\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport type { ParagraphBlock as ParagraphBlockType } from \"@templatical/types\";\nimport ParagraphToolbar from \"./ParagraphToolbar.vue\";\nimport RichTextLinkDialog from \"./RichTextLinkDialog.vue\";\nimport RichTextEditorContent from \"./RichTextEditorContent.vue\";\nimport { withLinkColor } from \"../../utils/linkColorExtension\";\n\nconst props = defineProps<{\n block: ParagraphBlockType;\n toolbarPosition: { top: number; left: number };\n}>();\n\nconst emit = defineEmits<{\n (e: \"done\"): void;\n}>();\n\nconst popoverRoot = usePopoverRoot();\n\nconst {\n editor,\n EditorContent,\n isLoading,\n initError,\n retry,\n showLinkDialog,\n linkUrl,\n linkColor,\n linkDialogRef,\n canRequestMergeTag,\n canInsertLogicTag,\n openLinkDialog,\n insertLink,\n removeLink,\n closeLinkDialog,\n handleLinkKeydown,\n handleAddMergeTag,\n handleAddLogicTag,\n} = useRichTextEditor({\n blockId: () => props.block.id,\n blockContent: () => props.block.content,\n onDone: () => emit(\"done\"),\n editorName: \"ParagraphEditor\",\n async loadExtensions({\n mergeTags,\n syntax,\n triggerChar,\n autocompleteEnabled,\n suggestionEmptyText,\n }) {\n const [\n { Editor: TiptapEditor, EditorContent: EC },\n { default: StarterKit },\n { default: LinkExt },\n { default: UnderlineExt },\n { default: SubscriptExt },\n { default: SuperscriptExt },\n { default: TextAlign },\n { TextStyle },\n { default: Color },\n { default: FontFamily },\n { default: Highlight },\n {\n MergeTagNode,\n MergeTagSuggestion,\n LogicMergeTagNode,\n FontSize,\n LineHeight,\n LetterSpacing,\n },\n ] = await Promise.all([\n import(\"@tiptap/vue-3\"),\n import(\"@tiptap/starter-kit\"),\n import(\"@tiptap/extension-link\"),\n import(\"@tiptap/extension-underline\"),\n import(\"@tiptap/extension-subscript\"),\n import(\"@tiptap/extension-superscript\"),\n import(\"@tiptap/extension-text-align\"),\n import(\"@tiptap/extension-text-style\"),\n import(\"@tiptap/extension-color\"),\n import(\"@tiptap/extension-font-family\"),\n import(\"@tiptap/extension-highlight\"),\n import(\"../../extensions\"),\n ]);\n\n return {\n TiptapEditor,\n EC,\n extensions: [\n StarterKit.configure({\n heading: false,\n codeBlock: false,\n blockquote: false,\n horizontalRule: false,\n // StarterKit bundles @tiptap/extension-link (openOnClick: true).\n // Disable it so the LinkExt below (openOnClick: false) is the only\n // link extension — otherwise clicking a link while editing opens it.\n link: false,\n // StarterKit also bundles @tiptap/extension-underline; the editor\n // registers its own UnderlineExt below, so disable StarterKit's copy\n // to avoid a duplicate `underline` extension (and its console warning).\n underline: false,\n }),\n UnderlineExt,\n SubscriptExt,\n SuperscriptExt,\n withLinkColor(LinkExt).configure({\n openOnClick: false,\n HTMLAttributes: {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n }),\n TextAlign.configure({ types: [\"paragraph\"] }),\n TextStyle,\n Color,\n FontFamily,\n Highlight.configure({ multicolor: true }),\n FontSize,\n LineHeight,\n LetterSpacing,\n MergeTagNode.configure({ mergeTags, syntax }),\n LogicMergeTagNode.configure({ syntax }),\n ...(autocompleteEnabled && triggerChar && mergeTags.length > 0\n ? [\n MergeTagSuggestion.configure({\n mergeTags,\n char: triggerChar,\n emptyText: suggestionEmptyText,\n popoverRoot,\n }),\n ]\n : []),\n ],\n };\n },\n});\n</script>\n\n<template>\n <div class=\"tpl-text-editor-wrapper tpl:relative\">\n <ParagraphToolbar\n :editor=\"editor\"\n :toolbar-position=\"toolbarPosition\"\n :is-loading=\"isLoading\"\n :can-request-merge-tag=\"canRequestMergeTag\"\n :can-insert-logic-tag=\"canInsertLogicTag\"\n @open-link-dialog=\"openLinkDialog\"\n @add-merge-tag=\"handleAddMergeTag\"\n @add-logic-tag=\"handleAddLogicTag\"\n />\n\n <RichTextEditorContent\n :editor=\"editor\"\n :editor-content=\"EditorContent\"\n :is-loading=\"isLoading\"\n :init-error=\"initError\"\n @retry=\"retry\"\n />\n\n <RichTextLinkDialog\n :visible=\"showLinkDialog\"\n :is-editing-link=\"editor?.isActive('link') ?? false\"\n v-model:dialog-ref=\"linkDialogRef\"\n v-model:link-url=\"linkUrl\"\n v-model:link-color=\"linkColor\"\n @close=\"closeLinkDialog\"\n @insert=\"insertLink\"\n @remove=\"removeLink\"\n @keydown=\"handleLinkKeydown\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { useRichTextEditor } from \"../../composables/useRichTextEditor\";\nimport { usePopoverRoot } from \"../../composables/usePopoverRoot\";\nimport type { ParagraphBlock as ParagraphBlockType } from \"@templatical/types\";\nimport ParagraphToolbar from \"./ParagraphToolbar.vue\";\nimport RichTextLinkDialog from \"./RichTextLinkDialog.vue\";\nimport RichTextEditorContent from \"./RichTextEditorContent.vue\";\nimport { withLinkColor } from \"../../utils/linkColorExtension\";\n\nconst props = defineProps<{\n block: ParagraphBlockType;\n toolbarPosition: { top: number; left: number };\n}>();\n\nconst emit = defineEmits<{\n (e: \"done\"): void;\n}>();\n\nconst popoverRoot = usePopoverRoot();\n\nconst {\n editor,\n EditorContent,\n isLoading,\n initError,\n retry,\n showLinkDialog,\n linkUrl,\n linkColor,\n linkDialogRef,\n canRequestMergeTag,\n canInsertLogicTag,\n openLinkDialog,\n insertLink,\n removeLink,\n closeLinkDialog,\n handleLinkKeydown,\n handleAddMergeTag,\n handleAddLogicTag,\n} = useRichTextEditor({\n blockId: () => props.block.id,\n blockContent: () => props.block.content,\n onDone: () => emit(\"done\"),\n editorName: \"ParagraphEditor\",\n async loadExtensions({\n mergeTags,\n syntax,\n triggerChar,\n autocompleteEnabled,\n suggestionEmptyText,\n }) {\n const [\n { Editor: TiptapEditor, EditorContent: EC },\n { default: StarterKit },\n { default: LinkExt },\n { default: UnderlineExt },\n { default: SubscriptExt },\n { default: SuperscriptExt },\n { default: TextAlign },\n { TextStyle },\n { default: Color },\n { default: FontFamily },\n { default: Highlight },\n {\n MergeTagNode,\n MergeTagSuggestion,\n LogicMergeTagNode,\n FontSize,\n LineHeight,\n LetterSpacing,\n },\n ] = await Promise.all([\n import(\"@tiptap/vue-3\"),\n import(\"@tiptap/starter-kit\"),\n import(\"@tiptap/extension-link\"),\n import(\"@tiptap/extension-underline\"),\n import(\"@tiptap/extension-subscript\"),\n import(\"@tiptap/extension-superscript\"),\n import(\"@tiptap/extension-text-align\"),\n import(\"@tiptap/extension-text-style\"),\n import(\"@tiptap/extension-color\"),\n import(\"@tiptap/extension-font-family\"),\n import(\"@tiptap/extension-highlight\"),\n import(\"../../extensions\"),\n ]);\n\n return {\n TiptapEditor,\n EC,\n extensions: [\n StarterKit.configure({\n heading: false,\n codeBlock: false,\n blockquote: false,\n horizontalRule: false,\n // StarterKit bundles @tiptap/extension-link (openOnClick: true).\n // Disable it so the LinkExt below (openOnClick: false) is the only\n // link extension — otherwise clicking a link while editing opens it.\n link: false,\n // StarterKit also bundles @tiptap/extension-underline; the editor\n // registers its own UnderlineExt below, so disable StarterKit's copy\n // to avoid a duplicate `underline` extension (and its console warning).\n underline: false,\n }),\n UnderlineExt,\n SubscriptExt,\n SuperscriptExt,\n withLinkColor(LinkExt).configure({\n openOnClick: false,\n HTMLAttributes: {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n }),\n TextAlign.configure({ types: [\"paragraph\"] }),\n TextStyle,\n Color,\n FontFamily,\n Highlight.configure({ multicolor: true }),\n FontSize,\n LineHeight,\n LetterSpacing,\n MergeTagNode.configure({ mergeTags, syntax }),\n LogicMergeTagNode.configure({ syntax }),\n ...(autocompleteEnabled && triggerChar && mergeTags.length > 0\n ? [\n MergeTagSuggestion.configure({\n mergeTags,\n char: triggerChar,\n emptyText: suggestionEmptyText,\n popoverRoot,\n }),\n ]\n : []),\n ],\n };\n },\n});\n</script>\n\n<template>\n <div class=\"tpl-text-editor-wrapper tpl:relative\">\n <ParagraphToolbar\n :editor=\"editor\"\n :toolbar-position=\"toolbarPosition\"\n :is-loading=\"isLoading\"\n :can-request-merge-tag=\"canRequestMergeTag\"\n :can-insert-logic-tag=\"canInsertLogicTag\"\n @open-link-dialog=\"openLinkDialog\"\n @add-merge-tag=\"handleAddMergeTag\"\n @add-logic-tag=\"handleAddLogicTag\"\n />\n\n <RichTextEditorContent\n :editor=\"editor\"\n :editor-content=\"EditorContent\"\n :is-loading=\"isLoading\"\n :init-error=\"initError\"\n @retry=\"retry\"\n />\n\n <RichTextLinkDialog\n :visible=\"showLinkDialog\"\n :is-editing-link=\"editor?.isActive('link') ?? false\"\n v-model:dialog-ref=\"linkDialogRef\"\n v-model:link-url=\"linkUrl\"\n v-model:link-color=\"linkColor\"\n @close=\"closeLinkDialog\"\n @insert=\"insertLink\"\n @remove=\"removeLink\"\n @keydown=\"handleLinkKeydown\"\n />\n </div>\n</template>\n"],"mappings":"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"}