@mono-lit/helper 0.0.9 → 0.1.0

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