@mono-lit/helper 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/dist/accordion-core-DaNyPWRr.js +277 -0
  2. package/dist/alert-core-DWtHbX_-.js +134 -0
  3. package/dist/breadcrumb-list-core-Dh68T8Cf.js +747 -0
  4. package/dist/{mono-button-CLkHg3WW.js → button-core-DerXg84Q.js} +3 -276
  5. package/dist/button-dropdown-core-DKYEOyjy.js +654 -0
  6. package/dist/button-utils-D5-66M02.js +63 -0
  7. package/dist/card-utils-l80qAmrN.js +312 -0
  8. package/dist/chart-core-DV7hD3ZY.js +801 -0
  9. package/dist/checkbox-utils-DKdrhAzF.js +337 -0
  10. package/dist/chip-utils-DpRrd7Zj.js +403 -0
  11. package/dist/{data-source-controller-C6C4ej_M.js → data-source-controller-DS_JLrmS.js} +1 -1
  12. package/dist/{data-source-options-fxT5QIX4.js → data-source-options-DJUNU26C.js} +6 -6
  13. package/dist/{data-source-read-BL266IW0.js → data-source-read-uKJpRAzx.js} +2 -2
  14. package/dist/date-core-CyuSyvvG.js +734 -0
  15. package/dist/drawer-core-DbFWvNln.js +759 -0
  16. package/dist/dropdown-core-BCH1pK14.js +511 -0
  17. package/dist/dropdown-table-core-SfHUJVFq.js +1342 -0
  18. package/dist/export.js +1 -1
  19. package/dist/{field-path-BabiMrrA.js → field-path-DK2VBWHl.js} +1 -1
  20. package/dist/field-tooltip.css_raw-DVblekCl.js +5 -0
  21. package/dist/{field-validation.css_raw-Cx6SGrfP.js → field-validation.css_raw-BU7C6173.js} +1 -170
  22. package/dist/file-upload-core-Cz_dBQMx.js +624 -0
  23. package/dist/filter-builder-core-DyWjbBP7.js +381 -0
  24. package/dist/{filter-builder-B6Y2mmbM.js → filter-builder-vbqIuPhX.js} +1 -1
  25. package/dist/{filter-eval-ChDSaAUH.js → filter-eval-CqeBnMYh.js} +1 -1
  26. package/dist/{filter-odata-Bi27XUpQ.js → filter-odata-GsczYKNC.js} +1 -1
  27. package/dist/{hydration-flush-BaE9gN3C.js → hydration-flush-Volt9X7Q.js} +2 -1071
  28. package/dist/index.js +11 -11
  29. package/dist/{index.node-DTqDBca7.js → index.node-Csy9zrr1.js} +4 -4
  30. package/dist/index.node.js +11 -11
  31. package/dist/input-utils-BglY-k0H.js +1145 -0
  32. package/dist/menu-core-DkAYuCZ2.js +831 -0
  33. package/dist/modal-core-CSBSPN_m.js +844 -0
  34. package/dist/mono-button-DVvZ03P-.js +280 -0
  35. package/dist/{mono-button.shadow-DqZMpcqY.js → mono-button.shadow-BANxMGln.js} +6 -594
  36. package/dist/{mono-data-chart-NKPdAgVq.js → mono-data-chart-ChF4J9RT.js} +6 -6
  37. package/dist/{mono-data-dropdown-B2iRpJuI.js → mono-data-dropdown-Bgj2PDfm.js} +1 -1
  38. package/dist/{mono-data-grid-llJCX9MC.js → mono-data-grid-DJkp96N-.js} +144 -46
  39. package/dist/{mono-event-BPku9HpS.js → mono-event-CAZf0F_k.js} +14 -9
  40. package/dist/{mono-form-controller-BrA10erm.js → mono-form-controller-DxZLvyg6.js} +2 -1
  41. package/dist/mono-table-checkbox-core-BKOMx8R5.js +5288 -0
  42. package/dist/nav-core-B5qU2dzn.js +225 -0
  43. package/dist/{normalize-error-D93O4q8g.js → normalize-error-BEcd1tmS.js} +2 -2
  44. package/dist/otp-core-DXg3vFLh.js +758 -0
  45. package/dist/radio-utils-Dk9Tl1jz.js +319 -0
  46. package/dist/rich-text-editor-core-Ddd_QaLn.js +1280 -0
  47. package/dist/select-utils-BgArYHk8.js +2140 -0
  48. package/dist/sidebar-core-CD6txDo3.js +583 -0
  49. package/dist/slider-core-vcWr321-.js +1014 -0
  50. package/dist/src/components/dropdown-table/dropdown-table-core.d.ts +2 -2
  51. package/dist/src/components/dropdown-table/dropdown-table-types.d.ts +1 -1
  52. package/dist/src/components/dropdown-table/index.d.ts +1 -1
  53. package/dist/src/components/dropdown-table/index.shadow.d.ts +1 -1
  54. package/dist/src/components/dropdown-table/mono-data-dropdown.d.ts +1 -1
  55. package/dist/src/components/form/form-types.d.ts +9 -3
  56. package/dist/src/components/input/input-core.d.ts +1 -1
  57. package/dist/src/components/input/input-types.d.ts +1 -1
  58. package/dist/src/components/otp/otp-core.d.ts +1 -1
  59. package/dist/src/components/select/select-core.d.ts +1 -1
  60. package/dist/src/components/select/select-types.d.ts +1 -1
  61. package/dist/src/components/slider/slider-core.d.ts +1 -1
  62. package/dist/src/components/slider/slider-types.d.ts +1 -1
  63. package/dist/src/components/table/filter-suggestion.d.ts +171 -0
  64. package/dist/src/components/table/index.d.ts +5 -4
  65. package/dist/src/components/table/index.shadow.d.ts +5 -4
  66. package/dist/src/components/table/mono-data-grid.d.ts +22 -3
  67. package/dist/src/components/table/mono-table-empty-core.d.ts +37 -0
  68. package/dist/src/components/table/mono-table-search-core.d.ts +22 -3
  69. package/dist/src/components/table/table-types.d.ts +74 -4
  70. package/dist/src/components/tag-input/tag-input-core.d.ts +1 -1
  71. package/dist/src/components/tag-input/tag-input-types.d.ts +1 -1
  72. package/dist/src/components/textarea/textarea-core.d.ts +1 -1
  73. package/dist/src/composables/mono-event.d.ts +7 -1
  74. package/dist/src/entries/index.d.ts +8 -6
  75. package/dist/src/entries/index.node.d.ts +8 -6
  76. package/dist/src/search/index.d.ts +1 -1
  77. package/dist/src/utils/group-count.d.ts +36 -0
  78. package/dist/switch-utils-CTZ4id2V.js +338 -0
  79. package/dist/tabs-core-r5-B8k_N.js +317 -0
  80. package/dist/tag-input-utils-D2JA90DQ.js +3060 -0
  81. package/dist/textarea-utils-VU1KeXm8.js +821 -0
  82. package/dist/ui/accordion.js +2 -274
  83. package/dist/ui/alert.js +2 -131
  84. package/dist/ui/breadcrumb.js +4 -745
  85. package/dist/ui/button-dropdown.js +4 -652
  86. package/dist/ui/button.js +2 -63
  87. package/dist/ui/card.js +2 -310
  88. package/dist/ui/chart.js +4 -800
  89. package/dist/ui/checkbox.js +4 -335
  90. package/dist/ui/chip.js +4 -402
  91. package/dist/ui/date.js +3 -732
  92. package/dist/ui/drawer.js +3 -757
  93. package/dist/ui/dropdown-table.js +5 -1341
  94. package/dist/ui/dropdown.js +4 -509
  95. package/dist/ui/file-upload.js +3 -622
  96. package/dist/ui/filter.js +5 -380
  97. package/dist/ui/form.js +1 -1
  98. package/dist/ui/index.css +118 -1
  99. package/dist/ui/input.js +3 -1141
  100. package/dist/ui/menu.js +4 -828
  101. package/dist/ui/modal.js +4 -843
  102. package/dist/ui/nav.js +4 -223
  103. package/dist/ui/otp.js +4 -756
  104. package/dist/ui/radio.js +4 -317
  105. package/dist/ui/rich-text-editor.js +4 -1278
  106. package/dist/ui/select.js +5 -2138
  107. package/dist/ui/shadow/accordion.js +4 -273
  108. package/dist/ui/shadow/alert.js +4 -130
  109. package/dist/ui/shadow/breadcrumb.js +5 -744
  110. package/dist/ui/shadow/button-dropdown.js +6 -652
  111. package/dist/ui/shadow/button.js +3 -63
  112. package/dist/ui/shadow/card.js +4 -309
  113. package/dist/ui/shadow/chart.js +6 -1576
  114. package/dist/ui/shadow/checkbox.js +4 -334
  115. package/dist/ui/shadow/chip.js +4 -396
  116. package/dist/ui/shadow/date.js +7 -731
  117. package/dist/ui/shadow/drawer.js +4 -756
  118. package/dist/ui/shadow/dropdown-table.js +8 -1762
  119. package/dist/ui/shadow/dropdown.js +4 -508
  120. package/dist/ui/shadow/file-upload.js +4 -620
  121. package/dist/ui/shadow/filter.js +7 -379
  122. package/dist/ui/shadow/input.js +6 -1140
  123. package/dist/ui/shadow/menu.js +5 -828
  124. package/dist/ui/shadow/modal.js +6 -1063
  125. package/dist/ui/shadow/nav.js +5 -223
  126. package/dist/ui/shadow/otp.js +6 -754
  127. package/dist/ui/shadow/radio.js +4 -316
  128. package/dist/ui/shadow/rich-text-editor.js +4 -1276
  129. package/dist/ui/shadow/select.js +6 -2136
  130. package/dist/ui/shadow/sidebar.js +5 -581
  131. package/dist/ui/shadow/slider.js +5 -1010
  132. package/dist/ui/shadow/switch.js +4 -335
  133. package/dist/ui/shadow/table.js +10 -4501
  134. package/dist/ui/shadow/tabs.js +6 -315
  135. package/dist/ui/shadow/tag-input.js +7 -3057
  136. package/dist/ui/shadow/textarea.js +6 -817
  137. package/dist/ui/sidebar.js +3 -581
  138. package/dist/ui/slider.js +4 -1012
  139. package/dist/ui/switch.js +4 -336
  140. package/dist/ui/table.js +9 -4502
  141. package/dist/ui/tabs.js +4 -315
  142. package/dist/ui/tag-input.js +5 -3058
  143. package/dist/ui/textarea.js +4 -819
  144. package/dist/vue.d.ts +3 -2
  145. package/package.json +3 -3
  146. package/dist/chip-strip-bNfLn52Z.js +0 -215
  147. package/dist/data-source-controller-Dx6IQ2CN.js +0 -243
  148. package/dist/data-source-options-BM4r4PRw.js +0 -558
  149. package/dist/data-source-read-HyBCRg1t.js +0 -242
  150. package/dist/excel-BXzr3uI1.js +0 -784
  151. package/dist/export-ixRdCS2y.js +0 -2388
  152. package/dist/field-tooltip-addon-CWCp19mJ.js +0 -702
  153. package/dist/field-tooltip.css_raw-U5UeTa2d.js +0 -269
  154. package/dist/filter-builder-C0T3pMx2.js +0 -208
  155. package/dist/form-control-core-BbiACMtL.js +0 -226
  156. package/dist/icon-ClxnYhBG.js +0 -19
  157. package/dist/import-Dc4eXC02.js +0 -612
  158. package/dist/light-slots-_no0r2Z-.js +0 -246
  159. package/dist/markdown-uGlE_OfJ.js +0 -20191
  160. package/dist/mono-data-grid-e9ZVBlNN.js +0 -4240
  161. package/dist/normalize-error-BmLbgANw.js +0 -1048
@@ -0,0 +1,1280 @@
1
+ import { d as buildSizeStyle, f as toCssSize } from "./mono-ui-kvLVIf1V.js";
2
+ import { a as defineHybridPropAliases, r as booleanStringConverter, s as optionalNumberConverter, t as __decorate } from "./decorate-DbYFpi8R.js";
3
+ import { t as dispatchMonoEvent } from "./mono-event-CAZf0F_k.js";
4
+ import { t as MonoFormControlCore } from "./form-control-core-CRZPZ1ru.js";
5
+ import { html, isServer, nothing } from "lit";
6
+ import { property, state } from "lit/decorators.js";
7
+ import { styleMap } from "lit/directives/style-map.js";
8
+
9
+ //#region src/components/rich-text-editor/rich-text-editor-loader.ts
10
+ const INSTALL_HINT = "[mono-rich-text-editor] needs the optional peer dependency \"suneditor\". Install it in your app: pnpm add suneditor@^3.3.3";
11
+ function withHint(err) {
12
+ const message = err instanceof Error ? err.message : String(err);
13
+ return /* @__PURE__ */ new Error(`${INSTALL_HINT}${message ? ` (original error: ${message})` : ""}`);
14
+ }
15
+ let _corePromise = null;
16
+ /** The `suneditor` default export (`{ create, init }`), cached; a failure resets so a later attempt retries. */
17
+ function loadSunEditor() {
18
+ _corePromise ??= import("suneditor").then((m) => m?.default ?? m).catch((err) => {
19
+ _corePromise = null;
20
+ throw withHint(err);
21
+ });
22
+ return _corePromise;
23
+ }
24
+ let _cssPromise = null;
25
+ /**
26
+ * SunEditor's UI stylesheet (`suneditor/css/editor`), injected ONCE per page by
27
+ * the consumer's bundler as a side-effect import. Failure is not fatal — the
28
+ * editor still works, unstyled — so it is reported once and swallowed.
29
+ */
30
+ function loadSunEditorCss() {
31
+ _cssPromise ??= import("suneditor/css/editor").then(() => void 0).catch((err) => {
32
+ console.warn("[mono-rich-text-editor] could not load \"suneditor/css/editor\" — the editor will render unstyled. Import the stylesheet yourself and set load-css=\"false\" if your bundler cannot import CSS from a dynamic import.", err);
33
+ });
34
+ return _cssPromise;
35
+ }
36
+ let _pluginsPromise = null;
37
+ /** Every built-in plugin, keyed by name (`suneditor/plugins`' default export). */
38
+ function loadSunEditorPlugins() {
39
+ _pluginsPromise ??= import("suneditor/plugins").then((m) => m?.default ?? m).catch((err) => {
40
+ _pluginsPromise = null;
41
+ throw withHint(err);
42
+ });
43
+ return _pluginsPromise;
44
+ }
45
+ /**
46
+ * The language packs SunEditor ships, each behind its own static import so the
47
+ * consumer's bundler can split them. Unknown codes fall back to English (the
48
+ * editor's own default) with a warning rather than failing the build.
49
+ */
50
+ const LANGS = {
51
+ ckb: () => import("suneditor/langs/ckb"),
52
+ cs: () => import("suneditor/langs/cs"),
53
+ da: () => import("suneditor/langs/da"),
54
+ de: () => import("suneditor/langs/de"),
55
+ en: () => import("suneditor/langs/en"),
56
+ es: () => import("suneditor/langs/es"),
57
+ fa: () => import("suneditor/langs/fa"),
58
+ fr: () => import("suneditor/langs/fr"),
59
+ he: () => import("suneditor/langs/he"),
60
+ hu: () => import("suneditor/langs/hu"),
61
+ it: () => import("suneditor/langs/it"),
62
+ ja: () => import("suneditor/langs/ja"),
63
+ km: () => import("suneditor/langs/km"),
64
+ ko: () => import("suneditor/langs/ko"),
65
+ lv: () => import("suneditor/langs/lv"),
66
+ nl: () => import("suneditor/langs/nl"),
67
+ pl: () => import("suneditor/langs/pl"),
68
+ pt_br: () => import("suneditor/langs/pt_br"),
69
+ ro: () => import("suneditor/langs/ro"),
70
+ ru: () => import("suneditor/langs/ru"),
71
+ se: () => import("suneditor/langs/se"),
72
+ tr: () => import("suneditor/langs/tr"),
73
+ uk: () => import("suneditor/langs/uk"),
74
+ ur: () => import("suneditor/langs/ur"),
75
+ zh_cn: () => import("suneditor/langs/zh_cn")
76
+ };
77
+ /** Codes `lang` accepts. */
78
+ const SUNEDITOR_LANG_CODES = Object.keys(LANGS);
79
+ const _langPromises = /* @__PURE__ */ new Map();
80
+ /**
81
+ * A language pack by code (`ko`, `pt-BR` → `pt_br`, `zh-CN` → `zh_cn`, …), or
82
+ * `undefined` for English / an unknown code (SunEditor then uses its default).
83
+ */
84
+ function loadSunEditorLang(code) {
85
+ const key = code.trim().toLowerCase().replace(/-/g, "_");
86
+ if (!key || key === "en") return Promise.resolve(void 0);
87
+ const loader = LANGS[key];
88
+ if (!loader) {
89
+ console.warn(`[mono-rich-text-editor] unknown lang "${code}" — SunEditor ships: ${SUNEDITOR_LANG_CODES.join(", ")}. Using English.`);
90
+ return Promise.resolve(void 0);
91
+ }
92
+ let p = _langPromises.get(key);
93
+ if (!p) {
94
+ p = loader().then((m) => m?.default ?? m).catch((err) => {
95
+ _langPromises.delete(key);
96
+ throw withHint(err);
97
+ });
98
+ _langPromises.set(key, p);
99
+ }
100
+ return p;
101
+ }
102
+
103
+ //#endregion
104
+ //#region src/components/rich-text-editor/rich-text-editor-toolbar.ts
105
+ /**
106
+ * Buttons SunEditor's core provides WITHOUT a plugin (v3 `_defaultButtons`).
107
+ * Anything else in a `buttonList` is the `key` of a plugin that has to be in
108
+ * `plugins`, so a preset is filtered against the plugins actually loaded.
109
+ */
110
+ const SUNEDITOR_CORE_BUTTONS = /* @__PURE__ */ new Set([
111
+ "bold",
112
+ "underline",
113
+ "italic",
114
+ "strike",
115
+ "subscript",
116
+ "superscript",
117
+ "removeFormat",
118
+ "copyFormat",
119
+ "indent",
120
+ "outdent",
121
+ "fullScreen",
122
+ "showBlocks",
123
+ "codeView",
124
+ "markdownView",
125
+ "undo",
126
+ "redo",
127
+ "preview",
128
+ "print",
129
+ "copy",
130
+ "dir",
131
+ "dir_ltr",
132
+ "dir_rtl",
133
+ "finder",
134
+ "save",
135
+ "newDocument",
136
+ "selectAll",
137
+ "pageBreak",
138
+ "pageUp",
139
+ "pageDown",
140
+ "pageNavigator"
141
+ ]);
142
+ /**
143
+ * Built-ins `plugins="auto"` leaves OUT: each needs configuration SunEditor
144
+ * warns about when it is missing (a server `url` / `uploadUrl`, a `templates` or
145
+ * `layouts` list, an external KaTeX / MathJax / PDF service). Ask for them by
146
+ * name — `plugins="auto, image­Gallery"` is not a thing, but
147
+ * `:plugins.prop="[...]"` with the class or `plugins="font, link, template"`
148
+ * is — and supply their options through `options`.
149
+ */
150
+ const AUTO_EXCLUDED_PLUGINS = /* @__PURE__ */ new Set([
151
+ "exportPDF",
152
+ "fileUpload",
153
+ "layout",
154
+ "template",
155
+ "math",
156
+ "imageGallery",
157
+ "videoGallery",
158
+ "audioGallery",
159
+ "fileGallery",
160
+ "fileBrowser"
161
+ ]);
162
+ /** Markers a `buttonList` may carry besides button names. */
163
+ const SPECIAL = /^(\||\/|-left|-right|-center|#fix)$/;
164
+ /**
165
+ * SunEditor's own default (`DEFAULTS.BUTTON_LIST`) — no plugin buttons at all.
166
+ * Mirrored here rather than imported so the presets stay pure.
167
+ */
168
+ const TOOLBAR_DEFAULT = [
169
+ ["undo", "redo"],
170
+ "|",
171
+ [
172
+ "bold",
173
+ "underline",
174
+ "italic",
175
+ "strike",
176
+ "|",
177
+ "subscript",
178
+ "superscript"
179
+ ],
180
+ "|",
181
+ ["removeFormat"],
182
+ "|",
183
+ ["outdent", "indent"],
184
+ "|",
185
+ [
186
+ "fullScreen",
187
+ "showBlocks",
188
+ "codeView"
189
+ ],
190
+ "|",
191
+ ["preview", "print"]
192
+ ];
193
+ /** The essentials: a comment box, a note field. */
194
+ const TOOLBAR_BASIC = [
195
+ ["undo", "redo"],
196
+ "|",
197
+ [
198
+ "bold",
199
+ "underline",
200
+ "italic",
201
+ "strike"
202
+ ],
203
+ "|",
204
+ [
205
+ "list_bulleted",
206
+ "list_numbered",
207
+ "link"
208
+ ],
209
+ "|",
210
+ ["removeFormat"]
211
+ ];
212
+ /** The default: what a document / description / email body needs. */
213
+ const TOOLBAR_STANDARD = [
214
+ ["undo", "redo"],
215
+ "|",
216
+ [
217
+ "blockStyle",
218
+ "font",
219
+ "fontSize"
220
+ ],
221
+ "|",
222
+ [
223
+ "bold",
224
+ "underline",
225
+ "italic",
226
+ "strike"
227
+ ],
228
+ ["fontColor", "backgroundColor"],
229
+ "|",
230
+ [
231
+ "align",
232
+ "list_bulleted",
233
+ "list_numbered",
234
+ "outdent",
235
+ "indent"
236
+ ],
237
+ "|",
238
+ [
239
+ "table",
240
+ "link",
241
+ "image",
242
+ "video"
243
+ ],
244
+ "|",
245
+ [
246
+ "blockquote",
247
+ "codeBlock",
248
+ "hr"
249
+ ],
250
+ "|",
251
+ ["removeFormat"],
252
+ "|",
253
+ ["codeView", "fullScreen"]
254
+ ];
255
+ /**
256
+ * Every built-in that works with no extra configuration. Left out on purpose:
257
+ * the galleries / file browser (need a server `url`), `template` (needs a
258
+ * `templates` list), `math` and `exportPDF` (need external libraries) — pass
259
+ * those through `toolbar` + `options` when the app provides what they need.
260
+ */
261
+ const TOOLBAR_FULL = [
262
+ ["undo", "redo"],
263
+ "|",
264
+ [
265
+ "blockStyle",
266
+ "paragraphStyle",
267
+ "font",
268
+ "fontSize",
269
+ "lineHeight"
270
+ ],
271
+ "|",
272
+ [
273
+ "bold",
274
+ "underline",
275
+ "italic",
276
+ "strike",
277
+ "subscript",
278
+ "superscript"
279
+ ],
280
+ [
281
+ "fontColor",
282
+ "backgroundColor",
283
+ "textStyle",
284
+ "copyFormat",
285
+ "removeFormat"
286
+ ],
287
+ "|",
288
+ [
289
+ "align",
290
+ "list_bulleted",
291
+ "list_numbered",
292
+ "outdent",
293
+ "indent",
294
+ "dir_ltr",
295
+ "dir_rtl"
296
+ ],
297
+ "|",
298
+ [
299
+ "table",
300
+ "layout",
301
+ "link",
302
+ "image",
303
+ "video",
304
+ "audio",
305
+ "embed",
306
+ "drawing"
307
+ ],
308
+ "|",
309
+ [
310
+ "blockquote",
311
+ "codeBlock",
312
+ "hr",
313
+ "pageBreak"
314
+ ],
315
+ "|",
316
+ [
317
+ "showBlocks",
318
+ "codeView",
319
+ "markdownView",
320
+ "fullScreen"
321
+ ],
322
+ "|",
323
+ [
324
+ "finder",
325
+ "selectAll",
326
+ "preview",
327
+ "print"
328
+ ]
329
+ ];
330
+ const TOOLBAR_PRESETS = {
331
+ basic: TOOLBAR_BASIC,
332
+ standard: TOOLBAR_STANDARD,
333
+ full: TOOLBAR_FULL,
334
+ default: TOOLBAR_DEFAULT
335
+ };
336
+ function isToolbarPreset(value) {
337
+ return typeof value === "string" && value in TOOLBAR_PRESETS;
338
+ }
339
+ /**
340
+ * The `buttonList` for a `toolbar` prop value: a preset name, an array, its
341
+ * JSON, or a string of names — `bold, italic | link` (`|` and `/` are honoured
342
+ * as separators, `,`/whitespace split the rest). Unknown → the `standard` preset.
343
+ */
344
+ function resolveToolbar(toolbar) {
345
+ if (toolbar == null || toolbar === "") return TOOLBAR_STANDARD;
346
+ if (Array.isArray(toolbar)) return toolbar;
347
+ if (isToolbarPreset(toolbar)) return TOOLBAR_PRESETS[toolbar];
348
+ if (typeof toolbar !== "string") return TOOLBAR_STANDARD;
349
+ const trimmed = toolbar.trim();
350
+ if (trimmed.startsWith("[")) try {
351
+ const parsed = JSON.parse(trimmed);
352
+ if (Array.isArray(parsed)) return parsed;
353
+ } catch {}
354
+ const out = [];
355
+ let group = [];
356
+ for (const token of trimmed.split(/[\s,]+/).filter(Boolean)) if (SPECIAL.test(token)) {
357
+ if (group.length) out.push(group);
358
+ group = [];
359
+ out.push(token);
360
+ } else group.push(token);
361
+ if (group.length) out.push(group);
362
+ return out.length ? out : TOOLBAR_STANDARD;
363
+ }
364
+ /**
365
+ * Drop the plugin buttons a `buttonList` names that are NOT among `available`
366
+ * plugin keys, so `plugins="none"` (or a trimmed list) with the default toolbar
367
+ * degrades to the core buttons instead of SunEditor rejecting the list.
368
+ * Separators left with nothing on either side are dropped too.
369
+ */
370
+ function pruneToolbar(list, available) {
371
+ const keep = (name) => SPECIAL.test(name) || SUNEDITOR_CORE_BUTTONS.has(name) || available.has(name);
372
+ const out = [];
373
+ for (const item of list) if (Array.isArray(item)) {
374
+ const group = item.filter(keep);
375
+ if (group.some((n) => !SPECIAL.test(n))) out.push(group);
376
+ } else if (keep(item)) out.push(item);
377
+ const cleaned = [];
378
+ for (const item of out) {
379
+ const isSep = typeof item === "string" && SPECIAL.test(item);
380
+ const prev = cleaned[cleaned.length - 1];
381
+ if (isSep && (cleaned.length === 0 || typeof prev === "string" && SPECIAL.test(prev))) continue;
382
+ cleaned.push(item);
383
+ }
384
+ while (cleaned.length && typeof cleaned[cleaned.length - 1] === "string") cleaned.pop();
385
+ return cleaned;
386
+ }
387
+ /**
388
+ * The plugin set to hand SunEditor, from the `plugins` prop and (when needed)
389
+ * the full built-in map. Returns `{ plugins, keys }` — `keys` is what
390
+ * `pruneToolbar` filters against.
391
+ *
392
+ * - `'auto'` / unset → every built-in that needs no configuration (`all` must
393
+ * be supplied; see {@link AUTO_EXCLUDED_PLUGINS}).
394
+ * - `'none'` → nothing.
395
+ * - an array → plugin classes kept as they are, NAMES looked up in `all`.
396
+ * - an object → SunEditor's own `{ name: class }` form.
397
+ * - a string → comma/space-separated names.
398
+ */
399
+ function resolvePlugins(plugins, all) {
400
+ const out = [];
401
+ const keys = /* @__PURE__ */ new Set();
402
+ const push = (key, cls) => {
403
+ if (!cls || out.includes(cls)) return;
404
+ out.push(cls);
405
+ const k = key ?? pluginKey(cls);
406
+ if (k) keys.add(k);
407
+ };
408
+ if (plugins == null || plugins === "" || plugins === "auto") {
409
+ for (const [key, cls] of Object.entries(all ?? {})) if (!AUTO_EXCLUDED_PLUGINS.has(key)) push(key, cls);
410
+ return {
411
+ plugins: out,
412
+ keys
413
+ };
414
+ }
415
+ if (plugins === "none") return {
416
+ plugins: out,
417
+ keys
418
+ };
419
+ if (typeof plugins === "string") {
420
+ for (const name of plugins.split(/[\s,]+/).filter(Boolean)) push(name, all?.[name]);
421
+ return {
422
+ plugins: out,
423
+ keys
424
+ };
425
+ }
426
+ if (Array.isArray(plugins)) {
427
+ for (const entry of plugins) if (typeof entry === "string") push(entry, all?.[entry]);
428
+ else push(void 0, entry);
429
+ return {
430
+ plugins: out,
431
+ keys
432
+ };
433
+ }
434
+ for (const [key, cls] of Object.entries(plugins)) push(key, cls);
435
+ return {
436
+ plugins: out,
437
+ keys
438
+ };
439
+ }
440
+ /** A SunEditor v3 plugin class carries its button name as `static key`. */
441
+ function pluginKey(cls) {
442
+ const key = cls?.key;
443
+ return typeof key === "string" ? key : void 0;
444
+ }
445
+ /** Whether `plugins` needs the full built-in map to be resolved. */
446
+ function pluginsNeedCatalog(plugins) {
447
+ if (plugins == null || plugins === "" || plugins === "auto") return true;
448
+ if (plugins === "none") return false;
449
+ if (typeof plugins === "string") return true;
450
+ if (Array.isArray(plugins)) return plugins.some((p) => typeof p === "string");
451
+ return false;
452
+ }
453
+
454
+ //#endregion
455
+ //#region src/components/rich-text-editor/rich-text-editor-core.ts
456
+ /**
457
+ * `MonoRichTextEditorCore` — render-mode-agnostic logic for `mono-rich-text-editor`,
458
+ * a form field whose input is a [SunEditor](https://suneditor.com) v3 instance.
459
+ *
460
+ * **The peer is optional.** `suneditor` is externalized from mono's build and
461
+ * loaded the first time an element renders (`rich-text-editor-loader.ts`). An
462
+ * app that has not installed it gets an inline message naming the package and
463
+ * the command, plus an `mno-error` event — never a crash.
464
+ *
465
+ * **The editor's DOM lives in LIGHT DOM, in both builds.** SunEditor is styled by
466
+ * one global stylesheet and parks its modals in a `.sun-editor-carrier-wrapper`
467
+ * on `<body>`, so neither could ever be adopted into a shadow root. The core
468
+ * therefore creates ONE mount node (`.mono-rich-text-editor-mount`) and each
469
+ * build decides where it shows: the light build re-homes it into the rendered
470
+ * field frame, the shadow build keeps it as a light child projected through
471
+ * `<slot name="editor">`. Either way it inherits the `--se-*` theme remap the
472
+ * frame declares, and the page sheet reaches it. SSR renders the chrome only —
473
+ * an editor is client state, exactly like `mono-chart` and `mono-date`.
474
+ *
475
+ * **Lifecycle mirrors `date-core`.** `_ensureEditor()` is idempotent and runs
476
+ * from `firstUpdated`, `connectedCallback` and every `updated()` that finds no
477
+ * instance, so a `v-if` / `<KeepAlive>` round trip rebuilds the editor instead
478
+ * of leaving a dead field. A build token plus an `isConnected` re-check after
479
+ * every `await` keeps a superseded build from constructing an editor on a
480
+ * detached node that nothing would ever destroy. `disconnectedCallback`
481
+ * destroys BEFORE `super` so the DOM is still in the tree.
482
+ *
483
+ * **Value model.** `modelValue` is the HTML. SunEditor → element: `onChange`
484
+ * emits `mno-change`, `onInput` emits `mno-input` (the textarea detail shape),
485
+ * an empty editor is published as `''` so `required` means what it says.
486
+ * Element → editor: an outside `modelValue` write reaches `$.html.set()` only
487
+ * when it differs from the last value the editor itself produced — no caret
488
+ * jumps, no echo. `monoForm` binds through {@link MonoFormControlCore} exactly
489
+ * as `mono-textarea` does.
490
+ */
491
+ const MonoRichTextEditorCore = (superClass) => {
492
+ class MonoRichTextEditorCoreClass extends MonoFormControlCore(superClass) {
493
+ constructor(...args) {
494
+ super(...args);
495
+ this.size = "md";
496
+ this.color = "primary";
497
+ this.variant = "outlined";
498
+ this.modelValue = "";
499
+ this.value = "";
500
+ this.name = "";
501
+ this.placeholder = "";
502
+ this.label = "";
503
+ this.helperText = "";
504
+ this.validationState = "default";
505
+ this.validationMessage = "";
506
+ this.errorMessage = "";
507
+ this.successMessage = "";
508
+ this.disabled = false;
509
+ this.readonly = false;
510
+ this.required = false;
511
+ this.cssClass = {};
512
+ this.cssClassName = "";
513
+ this.mode = "classic";
514
+ this.charCounter = false;
515
+ this.statusbar = true;
516
+ this.loadCss = true;
517
+ this._hasLabelSlotState = false;
518
+ this._hasHelperSlotState = false;
519
+ this._error = "";
520
+ this._loading = false;
521
+ this._fieldId = `mono-rich-text-editor-${Math.random().toString(36).slice(2)}`;
522
+ this._messageId = `${this._fieldId}-message`;
523
+ this._editor = null;
524
+ this._building = false;
525
+ this._buildToken = 0;
526
+ this._lastEmitted = "";
527
+ this._lastChanged = "";
528
+ this._ready = false;
529
+ this._titleObservers = [];
530
+ this._onToggleFullScreen = (params) => {
531
+ this._mount?.toggleAttribute("mono-fullscreen", !!params?.is);
532
+ };
533
+ this._onLoad = () => {
534
+ this._ready = true;
535
+ this._loading = false;
536
+ this._applyState();
537
+ this._applyAria();
538
+ const editor = this._editor;
539
+ if (editor) dispatchMonoEvent(this, "ready", { editor });
540
+ };
541
+ this._onChange = (params) => {
542
+ this._publish("change", params);
543
+ };
544
+ this._onInput = (params) => {
545
+ this._publish("input", params);
546
+ };
547
+ this._onFocus = (params) => {
548
+ dispatchMonoEvent(this, "focus", {
549
+ name: this.name || void 0,
550
+ sourceEvent: params
551
+ });
552
+ };
553
+ this._onBlur = (params) => {
554
+ dispatchMonoEvent(this, "blur", {
555
+ name: this.name || void 0,
556
+ sourceEvent: params
557
+ });
558
+ };
559
+ defineHybridPropAliases(this, [
560
+ "modelValue",
561
+ "helperText",
562
+ "validationState",
563
+ "validationMessage",
564
+ "errorMessage",
565
+ "successMessage",
566
+ "charCounter",
567
+ "maxLength",
568
+ "loadCss",
569
+ "textDirection",
570
+ "ariaLabelText",
571
+ "cssClass",
572
+ "minWidth",
573
+ "maxWidth",
574
+ "minHeight",
575
+ "maxHeight"
576
+ ]);
577
+ for (const alias of ["css-class", "cssclass"]) Object.defineProperty(this, alias, {
578
+ get: () => this.cssClass,
579
+ set: (value) => this._setCssClass(value),
580
+ configurable: true,
581
+ enumerable: false
582
+ });
583
+ for (const alias of [
584
+ "ariaLabel",
585
+ "aria-label",
586
+ "arialabel"
587
+ ]) Object.defineProperty(this, alias, {
588
+ get: () => this.ariaLabelText,
589
+ set: (value) => {
590
+ this.ariaLabelText = value == null ? void 0 : String(value);
591
+ },
592
+ configurable: true,
593
+ enumerable: false
594
+ });
595
+ }
596
+ static get observedAttributes() {
597
+ return [
598
+ ...super.observedAttributes ?? [],
599
+ "modelvalue",
600
+ "helpertext",
601
+ "validationstate",
602
+ "validationmessage",
603
+ "errormessage",
604
+ "successmessage",
605
+ "charcounter",
606
+ "maxlength",
607
+ "loadcss",
608
+ "textdirection",
609
+ "arialabeltext",
610
+ "arialabel",
611
+ "css-class",
612
+ "cssclass"
613
+ ];
614
+ }
615
+ attributeChangedCallback(name, oldValue, newValue) {
616
+ super.attributeChangedCallback(name, oldValue, newValue);
617
+ if (oldValue === newValue) return;
618
+ switch (name) {
619
+ case "modelvalue":
620
+ this.modelValue = newValue ?? "";
621
+ return;
622
+ case "helpertext":
623
+ this.helperText = newValue ?? "";
624
+ return;
625
+ case "validationstate":
626
+ this.validationState = newValue ?? "default";
627
+ return;
628
+ case "validationmessage":
629
+ this.validationMessage = newValue ?? "";
630
+ return;
631
+ case "errormessage":
632
+ this.errorMessage = newValue ?? "";
633
+ return;
634
+ case "successmessage":
635
+ this.successMessage = newValue ?? "";
636
+ return;
637
+ case "charcounter":
638
+ this.charCounter = this._toBoolean(newValue);
639
+ return;
640
+ case "maxlength":
641
+ this.maxLength = optionalNumberConverter.fromAttribute(newValue);
642
+ return;
643
+ case "loadcss":
644
+ this.loadCss = this._toBoolean(newValue);
645
+ return;
646
+ case "textdirection":
647
+ this.textDirection = newValue === "rtl" ? "rtl" : newValue === "ltr" ? "ltr" : void 0;
648
+ return;
649
+ case "arialabeltext":
650
+ case "arialabel":
651
+ this.ariaLabelText = newValue ?? void 0;
652
+ return;
653
+ case "css-class":
654
+ case "cssclass": this._setCssClass(newValue);
655
+ }
656
+ }
657
+ static {
658
+ this._configKeys = [
659
+ "mode",
660
+ "toolbar",
661
+ "plugins",
662
+ "language",
663
+ "textDirection",
664
+ "charCounter",
665
+ "maxLength",
666
+ "statusbar",
667
+ "sticky",
668
+ "options",
669
+ "placeholder",
670
+ "height",
671
+ "minHeight",
672
+ "maxHeight"
673
+ ];
674
+ }
675
+ willUpdate(changed) {
676
+ super.willUpdate?.(changed);
677
+ for (const key of [
678
+ "disabled",
679
+ "readonly",
680
+ "required",
681
+ "charCounter",
682
+ "statusbar",
683
+ "loadCss"
684
+ ]) {
685
+ const v = this[key];
686
+ if (typeof v !== "boolean") this[key] = this._toBoolean(v);
687
+ }
688
+ if (changed.has("modelValue") && this.value !== this.modelValue) this.value = this.modelValue ?? "";
689
+ if (changed.has("value") && this.modelValue !== this.value) this.modelValue = String(this.value ?? "");
690
+ }
691
+ connectedCallback() {
692
+ super.connectedCallback();
693
+ if (isServer) return;
694
+ this._ensureMount();
695
+ if (this.hasUpdated) this._ensureEditor();
696
+ }
697
+ disconnectedCallback() {
698
+ this._destroyEditor();
699
+ super.disconnectedCallback();
700
+ }
701
+ firstUpdated() {
702
+ if (isServer) return;
703
+ this._ensureEditor();
704
+ }
705
+ updated(changed) {
706
+ super.updated?.(changed);
707
+ if (isServer) return;
708
+ this._placeMount();
709
+ if (!this._editor) {
710
+ if (!this._building && MonoRichTextEditorCoreClass._configKeys.some((k) => changed.has(k))) this._error = "";
711
+ this._ensureEditor();
712
+ return;
713
+ }
714
+ if (MonoRichTextEditorCoreClass._configKeys.some((k) => changed.has(k))) {
715
+ this._rebuild();
716
+ return;
717
+ }
718
+ if (changed.has("modelValue")) this._applyModelValue();
719
+ if (changed.has("disabled") || changed.has("readonly")) this._applyState();
720
+ if (changed.has("ariaLabelText") || changed.has("label") || changed.has("placeholder")) this._applyAria();
721
+ }
722
+ /** Create the light-DOM mount once. Where it goes is the build's call (`_placeMount`). */
723
+ _ensureMount() {
724
+ if (this._mount) return;
725
+ const mount = document.createElement("div");
726
+ mount.className = "mono-rich-text-editor-mount";
727
+ mount.setAttribute("mono-rte-mount", "");
728
+ this._mount = mount;
729
+ }
730
+ /**
731
+ * Put the mount where this build shows it. Light: inside the rendered
732
+ * `[data-mono-slot="editor"]` frame. Shadow: a light child of the host, with
733
+ * `slot="editor"` so `<slot name="editor">` projects it. Idempotent.
734
+ */
735
+ _placeMount() {
736
+ const mount = this._mount;
737
+ if (!mount) return;
738
+ if (this._useNativeSlots) {
739
+ if (mount.getAttribute("slot") !== "editor") mount.setAttribute("slot", "editor");
740
+ if (mount.parentNode !== this) this.appendChild(mount);
741
+ return;
742
+ }
743
+ const outlet = this.renderRoot.querySelector("[data-mono-slot=\"editor\"]");
744
+ if (outlet && mount.parentNode !== outlet) outlet.appendChild(mount);
745
+ }
746
+ /**
747
+ * Build the instance if there is none — idempotent, safe from every hook.
748
+ * Every `await` is followed by the token / connection re-check: an element
749
+ * that left the tree mid-import must not end up owning an editor.
750
+ */
751
+ async _ensureEditor() {
752
+ if (isServer || this._editor || this._building) return;
753
+ const mount = this._mount;
754
+ if (!mount?.isConnected) return;
755
+ this._building = true;
756
+ this._loading = true;
757
+ const token = ++this._buildToken;
758
+ try {
759
+ const [SUNEDITOR] = await Promise.all([loadSunEditor(), this.loadCss ? loadSunEditorCss() : Promise.resolve()]);
760
+ const catalog = pluginsNeedCatalog(this.plugins) ? await loadSunEditorPlugins() : null;
761
+ const lang = typeof this.language === "string" ? await loadSunEditorLang(this.language) : this.language;
762
+ if (token !== this._buildToken || !this.isConnected || !mount.isConnected || this._editor) return;
763
+ mount.replaceChildren();
764
+ const target = document.createElement("div");
765
+ target.className = "mono-rich-text-editor-target";
766
+ mount.appendChild(target);
767
+ this._lastEmitted = this._lastChanged = this.modelValue || "";
768
+ this._ready = false;
769
+ this._editor = SUNEDITOR.create(target, this._buildOptions(catalog, lang));
770
+ this._error = "";
771
+ this._themeTooltips(mount);
772
+ } catch (err) {
773
+ if (token !== this._buildToken) return;
774
+ const message = err instanceof Error ? err.message : String(err);
775
+ this._error = message;
776
+ this._loading = false;
777
+ dispatchMonoEvent(this, "error", {
778
+ message,
779
+ error: err
780
+ });
781
+ } finally {
782
+ if (token === this._buildToken) this._building = false;
783
+ }
784
+ }
785
+ /**
786
+ * SunEditor labels its dropdown items (font family, font size, the colour
787
+ * palettes …) with `title`, which the browser draws as the OS tooltip — white,
788
+ * system font, out of every theme's reach. Rewrite each into `data-tooltip`
789
+ * (+ `aria-label`, so nothing is lost to assistive tech), which the sheet
790
+ * paints as Basecoat's tooltip; a title that only repeats the item's own text
791
+ * is dropped. The lists are built lazily, on first open, so the mount — and
792
+ * the modal carrier SunEditor parks on <body> — are watched for new ones.
793
+ */
794
+ _themeTooltips(mount) {
795
+ this._titleObservers.forEach((o) => o.disconnect());
796
+ this._titleObservers = [];
797
+ mount.style.setProperty("--_mono-rte-page-font", getComputedStyle(this).fontFamily);
798
+ const retitle = (root) => {
799
+ const nodes = root.matches("[title]") ? [root, ...root.querySelectorAll("[title]")] : [...root.querySelectorAll("[title]")];
800
+ for (const el of nodes) {
801
+ const title = el.getAttribute("title")?.trim();
802
+ el.removeAttribute("title");
803
+ if (!title) continue;
804
+ if (!el.hasAttribute("aria-label")) el.setAttribute("aria-label", title);
805
+ if ((el.textContent ?? "").trim() === title) continue;
806
+ el.setAttribute("data-tooltip", title);
807
+ }
808
+ };
809
+ const watch = (root) => {
810
+ retitle(root);
811
+ if (typeof MutationObserver === "undefined") return;
812
+ const mo = new MutationObserver((records) => {
813
+ for (const r of records) {
814
+ if (r.type === "attributes") {
815
+ if (r.target.hasAttribute("title")) retitle(r.target);
816
+ continue;
817
+ }
818
+ r.addedNodes.forEach((n) => {
819
+ if (n.nodeType === Node.ELEMENT_NODE) retitle(n);
820
+ });
821
+ }
822
+ });
823
+ mo.observe(root, {
824
+ childList: true,
825
+ subtree: true,
826
+ attributes: true,
827
+ attributeFilter: ["title"]
828
+ });
829
+ this._titleObservers.push(mo);
830
+ };
831
+ watch(mount);
832
+ const carriers = document.querySelectorAll(".sun-editor-carrier-wrapper");
833
+ const carrier = carriers[carriers.length - 1];
834
+ if (carrier) {
835
+ carrier.style.setProperty("--_mono-rte-page-font", getComputedStyle(this).fontFamily);
836
+ watch(carrier);
837
+ }
838
+ }
839
+ _buildOptions(catalog, lang) {
840
+ const { plugins, keys } = resolvePlugins(this.plugins, catalog);
841
+ const buttonList = pruneToolbar(resolveToolbar(this.toolbar), keys);
842
+ const consumer = this.options ?? {};
843
+ const consumerEvents = consumer.events ?? {};
844
+ const chain = (mine, name) => (params) => {
845
+ const theirs = consumerEvents[name];
846
+ const result = typeof theirs === "function" ? theirs(params) : void 0;
847
+ mine(params);
848
+ return result;
849
+ };
850
+ const options = {
851
+ value: this.modelValue || "",
852
+ placeholder: this.placeholder || void 0,
853
+ mode: this.mode,
854
+ buttonList,
855
+ plugins,
856
+ lang: lang ?? void 0,
857
+ textDirection: this.textDirection,
858
+ charCounter: this.charCounter || this.maxLength != null,
859
+ charCounter_max: this.maxLength ?? void 0,
860
+ statusbar: this.statusbar,
861
+ toolbar_sticky: this.sticky ?? -1,
862
+ width: "100%",
863
+ height: toCssSize(this.height) ?? "auto",
864
+ minHeight: toCssSize(this.minHeight) ?? void 0,
865
+ maxHeight: toCssSize(this.maxHeight) ?? void 0,
866
+ ...consumer,
867
+ events: {
868
+ ...consumerEvents,
869
+ onload: chain(this._onLoad, "onload"),
870
+ onChange: chain(this._onChange, "onChange"),
871
+ onInput: chain(this._onInput, "onInput"),
872
+ onFocus: chain(this._onFocus, "onFocus"),
873
+ onBlur: chain(this._onBlur, "onBlur"),
874
+ onToggleFullScreen: chain(this._onToggleFullScreen, "onToggleFullScreen")
875
+ }
876
+ };
877
+ for (const key of Object.keys(options)) if (options[key] === void 0) delete options[key];
878
+ return options;
879
+ }
880
+ _destroyEditor() {
881
+ this._buildToken++;
882
+ this._building = false;
883
+ const editor = this._editor;
884
+ this._editor = null;
885
+ this._ready = false;
886
+ this._loading = false;
887
+ this._titleObservers.forEach((o) => o.disconnect());
888
+ this._titleObservers = [];
889
+ if (editor) try {
890
+ editor.destroy();
891
+ } catch {}
892
+ this._mount?.replaceChildren();
893
+ }
894
+ /** Destroy + create, keeping the current HTML (it lives in `modelValue`). */
895
+ _rebuild() {
896
+ this._destroyEditor();
897
+ this._ensureEditor();
898
+ }
899
+ /** The editor's HTML as the field's value — `''` when it holds nothing. */
900
+ _read(data) {
901
+ const editor = this._editor;
902
+ if (!editor) return "";
903
+ try {
904
+ if (editor.isEmpty()) return "";
905
+ } catch {}
906
+ return typeof data === "string" ? data : editor.$.html.get();
907
+ }
908
+ _publish(kind, params) {
909
+ if (this.disabled || this.readonly) return;
910
+ const next = this._read(params?.data);
911
+ const oldValue = this.modelValue;
912
+ if (kind === "change") {
913
+ if (next === this._lastChanged) return;
914
+ this._lastChanged = next;
915
+ }
916
+ this._lastEmitted = next;
917
+ this.value = next;
918
+ this.modelValue = next;
919
+ dispatchMonoEvent(this, kind, {
920
+ modelValue: next,
921
+ currentValue: next,
922
+ oldValue,
923
+ value: next,
924
+ name: this.name || void 0,
925
+ sourceEvent: params
926
+ });
927
+ }
928
+ /** Push an OUTSIDE `modelValue` into the editor — only when it is genuinely new. */
929
+ _applyModelValue() {
930
+ const editor = this._editor;
931
+ if (!editor) return;
932
+ const next = this.modelValue || "";
933
+ if (next === this._lastEmitted) return;
934
+ this._lastEmitted = this._lastChanged = next;
935
+ try {
936
+ editor.$.html.set(next);
937
+ } catch (err) {
938
+ console.warn("[mono-rich-text-editor] could not set the editor content", err);
939
+ }
940
+ }
941
+ _applyState() {
942
+ const editor = this._editor;
943
+ if (!editor || !this._ready) return;
944
+ try {
945
+ if (this.disabled) editor.$.ui.disable();
946
+ else {
947
+ editor.$.ui.enable();
948
+ editor.$.ui.readOnly(!!this.readonly);
949
+ }
950
+ } catch (err) {
951
+ console.warn("[mono-rich-text-editor] could not apply disabled/readonly", err);
952
+ }
953
+ }
954
+ _applyAria() {
955
+ const editor = this._editor;
956
+ if (!editor || !this._ready) return;
957
+ const wysiwyg = editor.$.frameContext?.get?.("wysiwyg");
958
+ if (!wysiwyg) return;
959
+ const label = this.ariaLabelText || this.label || this.placeholder;
960
+ if (label) wysiwyg.setAttribute("aria-label", label);
961
+ else wysiwyg.removeAttribute("aria-label");
962
+ wysiwyg.setAttribute("aria-invalid", this._resolvedValidationState === "invalid" ? "true" : "false");
963
+ if (this._shouldShowFooter) wysiwyg.setAttribute("aria-describedby", this._messageId);
964
+ else wysiwyg.removeAttribute("aria-describedby");
965
+ }
966
+ /** The live SunEditor instance, or `null` before it loads / when the peer is missing. */
967
+ get editor() {
968
+ return this._editor;
969
+ }
970
+ /** The HTML as SunEditor serialises it (`''` when empty). */
971
+ getHtml() {
972
+ return this._read();
973
+ }
974
+ /** Replace the content. Emits `mno-change` like a user edit would. */
975
+ setHtml(html) {
976
+ this.modelValue = html ?? "";
977
+ this._applyModelValue();
978
+ }
979
+ /** Insert HTML at the caret. */
980
+ insertHtml(html) {
981
+ this._editor?.$.html.insert(html);
982
+ }
983
+ /** The plain text of the content. */
984
+ getText() {
985
+ return (this._editor?.$.frameContext?.get?.("wysiwyg"))?.innerText ?? "";
986
+ }
987
+ isEmpty() {
988
+ return this._read() === "";
989
+ }
990
+ focus() {
991
+ this._editor?.$.focusManager.focus();
992
+ }
993
+ blur() {
994
+ this._editor?.$.focusManager.blur();
995
+ }
996
+ /** Toggle (or set) the HTML source view. */
997
+ codeView(value) {
998
+ this._editor?.$.viewer.codeView(value);
999
+ }
1000
+ /** Toggle (or set) full screen. */
1001
+ fullScreen(value) {
1002
+ this._editor?.$.viewer.fullScreen(value);
1003
+ }
1004
+ _setCssClass(value) {
1005
+ if (value == null) {
1006
+ this.cssClass = {};
1007
+ this.cssClassName = "";
1008
+ return;
1009
+ }
1010
+ if (typeof value === "object") {
1011
+ this.cssClass = value;
1012
+ return;
1013
+ }
1014
+ if (typeof value === "string") {
1015
+ const trimmed = value.trim();
1016
+ if (!trimmed) {
1017
+ this.cssClass = {};
1018
+ this.cssClassName = "";
1019
+ return;
1020
+ }
1021
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) try {
1022
+ this.cssClass = JSON.parse(trimmed);
1023
+ return;
1024
+ } catch {}
1025
+ this.cssClassName = trimmed;
1026
+ }
1027
+ }
1028
+ _toBoolean(value) {
1029
+ if (typeof value === "boolean") return value;
1030
+ if (typeof value === "string") {
1031
+ const normalized = value.toLowerCase().trim();
1032
+ return normalized === "" || normalized === "true";
1033
+ }
1034
+ return Boolean(value);
1035
+ }
1036
+ _cls(base, key) {
1037
+ const extra = this.cssClass?.[key];
1038
+ return extra ? `${base} ${extra}` : base;
1039
+ }
1040
+ get _resolvedValidationState() {
1041
+ if (this.validationState && this.validationState !== "default") return this.validationState;
1042
+ if (this.errorMessage) return "invalid";
1043
+ if (this.successMessage) return "valid";
1044
+ return "default";
1045
+ }
1046
+ get _wrapperClasses() {
1047
+ return [
1048
+ "mono-rich-text-editor",
1049
+ this.size,
1050
+ this.color,
1051
+ this.variant,
1052
+ `mode-${this.mode.replace(":", "-")}`,
1053
+ this.disabled ? "disabled" : "",
1054
+ this.readonly ? "readonly" : "",
1055
+ this._resolvedValidationState !== "default" ? `is-${this._resolvedValidationState}` : "",
1056
+ this.value ? "has-value" : "",
1057
+ this._loading ? "is-loading" : "",
1058
+ this._error ? "is-unavailable" : "",
1059
+ this.cssClassName,
1060
+ this.cssClass?.root
1061
+ ].filter(Boolean).join(" ");
1062
+ }
1063
+ get _fieldClasses() {
1064
+ return [
1065
+ this._cls("mono-rich-text-editor-field", "field"),
1066
+ this.size,
1067
+ this.color,
1068
+ this.variant
1069
+ ].filter(Boolean).join(" ");
1070
+ }
1071
+ get _shouldShowFooter() {
1072
+ return Boolean(this.validationMessage || this.errorMessage || this.successMessage || this.helperText || this._hasHelperSlotState);
1073
+ }
1074
+ _renderLabel() {
1075
+ const hasContent = !!this.label || this._hasLabelSlotState;
1076
+ if (!hasContent && !this._slotsAlwaysRender) return nothing;
1077
+ return html`
1078
+ <label class=${this._cls("mono-rich-text-editor-label", "label")} mono-rte-label ?mono-empty=${!hasContent} ?data-empty=${!hasContent}>
1079
+ ${this._slotOutlet("label", this.label)}
1080
+ ${this.required ? html`<span class=${this._cls("mono-rich-text-editor-required", "required")} mono-rte-required-mark>*</span>` : nothing}
1081
+ </label>
1082
+ `;
1083
+ }
1084
+ _renderMessage() {
1085
+ const base = this._cls("mono-rich-text-editor-message", "message");
1086
+ if (this.validationMessage) {
1087
+ const state = this._resolvedValidationState;
1088
+ return html`<div class=${`${base} ${state}`} mono-rte-message=${state} role=${state === "invalid" ? "alert" : nothing}>${this.validationMessage}</div>`;
1089
+ }
1090
+ if (this.errorMessage) return html`<div class=${`${base} invalid`} mono-rte-message="invalid" role="alert">${this.errorMessage}</div>`;
1091
+ if (this.successMessage) return html`<div class=${`${base} valid`} mono-rte-message="valid">${this.successMessage}</div>`;
1092
+ if (this.helperText || this._hasHelperSlotState || this._slotsAlwaysRender) {
1093
+ const empty = !this.helperText && !this._hasHelperSlotState;
1094
+ return html`
1095
+ <div class=${`${base} helper`} mono-rte-message="helper" ?mono-empty=${empty} ?data-empty=${empty}>
1096
+ ${this._slotOutlet("helper", this.helperText)}
1097
+ </div>
1098
+ `;
1099
+ }
1100
+ return nothing;
1101
+ }
1102
+ _renderFooter() {
1103
+ if (!this._shouldShowFooter && !this._slotsAlwaysRender) return nothing;
1104
+ return html`
1105
+ <div class=${this._cls("mono-rich-text-editor-footer", "footer")} mono-rte-footer ?mono-empty=${!this._shouldShowFooter} ?data-empty=${!this._shouldShowFooter}>
1106
+ <div class=${this.cssClass?.messageWrap ?? ""} mono-rte-message-wrap>${this._renderMessage()}</div>
1107
+ </div>
1108
+ `;
1109
+ }
1110
+ /**
1111
+ * The peer-missing / build-failure notice. A SIBLING of the field frame, never
1112
+ * inside it: the frame's children are the mount the build re-homes there, and
1113
+ * a Lit child part beside a node Lit did not render would clear it on update.
1114
+ */
1115
+ _renderUnavailable() {
1116
+ if (!this._error) return nothing;
1117
+ return html`<div class="mono-rich-text-editor-unavailable" mono-rte-unavailable role="alert">${this._error}</div>`;
1118
+ }
1119
+ render() {
1120
+ const state = this._resolvedValidationState;
1121
+ return html`
1122
+ <div
1123
+ class=${this._wrapperClasses}
1124
+ style=${styleMap(buildSizeStyle({
1125
+ width: this.width,
1126
+ minWidth: this.minWidth,
1127
+ maxWidth: this.maxWidth
1128
+ }))}
1129
+ mono-rich-text-editor
1130
+ mono-size=${this.size === "md" ? nothing : this.size}
1131
+ mono-color=${this.color === "primary" ? nothing : this.color}
1132
+ mono-variant=${this.variant === "outlined" ? nothing : this.variant}
1133
+ mono-validation-state=${state === "default" ? nothing : state}
1134
+ mono-mode=${this.mode === "classic" ? nothing : this.mode}
1135
+ ?mono-disabled=${this.disabled}
1136
+ ?mono-readonly=${this.readonly}
1137
+ ?mono-required=${this.required}
1138
+ ?mono-loading=${this._loading}
1139
+ ?mono-unavailable=${!!this._error}
1140
+ ?mono-has-value=${!!this.value}
1141
+ >
1142
+ ${this._renderLabel()}
1143
+ ${this._renderEditorOutlet(this._fieldClasses)}
1144
+ ${this._renderUnavailable()}
1145
+ <div id=${this._messageId} mono-rte-message-outlet>${this._renderFooter()}</div>
1146
+ </div>
1147
+ `;
1148
+ }
1149
+ /** Whether the `label` / `helper` regions render even when empty. Light: no. Shadow: yes. */
1150
+ get _slotsAlwaysRender() {
1151
+ return false;
1152
+ }
1153
+ /** Whether slots are native `<slot>`s (shadow) rather than captured placeholders (light). */
1154
+ get _useNativeSlots() {
1155
+ return false;
1156
+ }
1157
+ _setSlotState(name, has) {
1158
+ if (name === "label") this._hasLabelSlotState = has;
1159
+ else this._hasHelperSlotState = has;
1160
+ }
1161
+ /**
1162
+ * Slot outlet for `label` / `helper`. Light (default): a `data-mono-slot`
1163
+ * placeholder the captured nodes are re-parented into when present, else the
1164
+ * prop `fallback`. Shadow overrides with a native `<slot name>`.
1165
+ */
1166
+ _slotOutlet(name, fallback = nothing) {
1167
+ return (name === "label" ? this._hasLabelSlotState : this._hasHelperSlotState) ? html`<span data-mono-slot=${name}></span>` : html`${fallback}`;
1168
+ }
1169
+ /**
1170
+ * The field frame the editor mount shows in. Its children are NOT Lit's:
1171
+ * light — the mount is appended by `_placeMount`; shadow — overridden to hold
1172
+ * a `<slot name="editor">`. Nothing else may ever render inside it.
1173
+ */
1174
+ _renderEditorOutlet(fieldClass) {
1175
+ return html`<div class=${fieldClass} mono-rte-field data-mono-slot="editor"></div>`;
1176
+ }
1177
+ }
1178
+ __decorate([property({ type: String })], MonoRichTextEditorCoreClass.prototype, "size", void 0);
1179
+ __decorate([property({ type: String })], MonoRichTextEditorCoreClass.prototype, "color", void 0);
1180
+ __decorate([property({ type: String })], MonoRichTextEditorCoreClass.prototype, "variant", void 0);
1181
+ __decorate([property({
1182
+ type: String,
1183
+ attribute: "model-value"
1184
+ })], MonoRichTextEditorCoreClass.prototype, "modelValue", void 0);
1185
+ __decorate([property({ type: String })], MonoRichTextEditorCoreClass.prototype, "value", void 0);
1186
+ __decorate([property({ type: String })], MonoRichTextEditorCoreClass.prototype, "name", void 0);
1187
+ __decorate([property({ type: String })], MonoRichTextEditorCoreClass.prototype, "placeholder", void 0);
1188
+ __decorate([property({ type: String })], MonoRichTextEditorCoreClass.prototype, "label", void 0);
1189
+ __decorate([property({
1190
+ type: String,
1191
+ attribute: "helper-text"
1192
+ })], MonoRichTextEditorCoreClass.prototype, "helperText", void 0);
1193
+ __decorate([property({
1194
+ type: String,
1195
+ attribute: "validation-state"
1196
+ })], MonoRichTextEditorCoreClass.prototype, "validationState", void 0);
1197
+ __decorate([property({
1198
+ type: String,
1199
+ attribute: "validation-message"
1200
+ })], MonoRichTextEditorCoreClass.prototype, "validationMessage", void 0);
1201
+ __decorate([property({
1202
+ type: String,
1203
+ attribute: "error-message"
1204
+ })], MonoRichTextEditorCoreClass.prototype, "errorMessage", void 0);
1205
+ __decorate([property({
1206
+ type: String,
1207
+ attribute: "success-message"
1208
+ })], MonoRichTextEditorCoreClass.prototype, "successMessage", void 0);
1209
+ __decorate([property({
1210
+ type: String,
1211
+ attribute: "aria-label"
1212
+ })], MonoRichTextEditorCoreClass.prototype, "ariaLabelText", void 0);
1213
+ __decorate([property({
1214
+ reflect: true,
1215
+ converter: booleanStringConverter
1216
+ })], MonoRichTextEditorCoreClass.prototype, "disabled", void 0);
1217
+ __decorate([property({
1218
+ reflect: true,
1219
+ converter: booleanStringConverter
1220
+ })], MonoRichTextEditorCoreClass.prototype, "readonly", void 0);
1221
+ __decorate([property({
1222
+ reflect: true,
1223
+ converter: booleanStringConverter
1224
+ })], MonoRichTextEditorCoreClass.prototype, "required", void 0);
1225
+ __decorate([property({ attribute: false })], MonoRichTextEditorCoreClass.prototype, "cssClass", void 0);
1226
+ __decorate([property({ attribute: false })], MonoRichTextEditorCoreClass.prototype, "cssClassName", void 0);
1227
+ __decorate([property({ type: String })], MonoRichTextEditorCoreClass.prototype, "mode", void 0);
1228
+ __decorate([property({ attribute: "toolbar" })], MonoRichTextEditorCoreClass.prototype, "toolbar", void 0);
1229
+ __decorate([property({ attribute: "plugins" })], MonoRichTextEditorCoreClass.prototype, "plugins", void 0);
1230
+ __decorate([property({ attribute: "language" })], MonoRichTextEditorCoreClass.prototype, "language", void 0);
1231
+ __decorate([property({
1232
+ type: String,
1233
+ attribute: "text-direction"
1234
+ })], MonoRichTextEditorCoreClass.prototype, "textDirection", void 0);
1235
+ __decorate([property({
1236
+ attribute: "char-counter",
1237
+ reflect: true,
1238
+ converter: booleanStringConverter
1239
+ })], MonoRichTextEditorCoreClass.prototype, "charCounter", void 0);
1240
+ __decorate([property({
1241
+ attribute: "max-length",
1242
+ converter: optionalNumberConverter
1243
+ })], MonoRichTextEditorCoreClass.prototype, "maxLength", void 0);
1244
+ __decorate([property({
1245
+ reflect: true,
1246
+ converter: booleanStringConverter
1247
+ })], MonoRichTextEditorCoreClass.prototype, "statusbar", void 0);
1248
+ __decorate([property({ converter: optionalNumberConverter })], MonoRichTextEditorCoreClass.prototype, "sticky", void 0);
1249
+ __decorate([property({
1250
+ attribute: "load-css",
1251
+ converter: booleanStringConverter
1252
+ })], MonoRichTextEditorCoreClass.prototype, "loadCss", void 0);
1253
+ __decorate([property({ attribute: false })], MonoRichTextEditorCoreClass.prototype, "options", void 0);
1254
+ __decorate([property({ type: String })], MonoRichTextEditorCoreClass.prototype, "width", void 0);
1255
+ __decorate([property({ type: String })], MonoRichTextEditorCoreClass.prototype, "height", void 0);
1256
+ __decorate([property({
1257
+ type: String,
1258
+ attribute: "min-width"
1259
+ })], MonoRichTextEditorCoreClass.prototype, "minWidth", void 0);
1260
+ __decorate([property({
1261
+ type: String,
1262
+ attribute: "max-width"
1263
+ })], MonoRichTextEditorCoreClass.prototype, "maxWidth", void 0);
1264
+ __decorate([property({
1265
+ type: String,
1266
+ attribute: "min-height"
1267
+ })], MonoRichTextEditorCoreClass.prototype, "minHeight", void 0);
1268
+ __decorate([property({
1269
+ type: String,
1270
+ attribute: "max-height"
1271
+ })], MonoRichTextEditorCoreClass.prototype, "maxHeight", void 0);
1272
+ __decorate([state()], MonoRichTextEditorCoreClass.prototype, "_hasLabelSlotState", void 0);
1273
+ __decorate([state()], MonoRichTextEditorCoreClass.prototype, "_hasHelperSlotState", void 0);
1274
+ __decorate([state()], MonoRichTextEditorCoreClass.prototype, "_error", void 0);
1275
+ __decorate([state()], MonoRichTextEditorCoreClass.prototype, "_loading", void 0);
1276
+ return MonoRichTextEditorCoreClass;
1277
+ };
1278
+
1279
+ //#endregion
1280
+ export { TOOLBAR_DEFAULT as a, TOOLBAR_STANDARD as c, resolveToolbar as d, SUNEDITOR_LANG_CODES as f, loadSunEditorPlugins as g, loadSunEditorLang as h, TOOLBAR_BASIC as i, pruneToolbar as l, loadSunEditorCss as m, AUTO_EXCLUDED_PLUGINS as n, TOOLBAR_FULL as o, loadSunEditor as p, SUNEDITOR_CORE_BUTTONS as r, TOOLBAR_PRESETS as s, MonoRichTextEditorCore as t, resolvePlugins as u };