@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.
- package/dist/accordion-core-DaNyPWRr.js +277 -0
- package/dist/alert-core-DWtHbX_-.js +134 -0
- package/dist/breadcrumb-list-core-Dh68T8Cf.js +747 -0
- package/dist/{mono-button-CLkHg3WW.js → button-core-DerXg84Q.js} +3 -276
- package/dist/button-dropdown-core-DKYEOyjy.js +654 -0
- package/dist/button-utils-D5-66M02.js +63 -0
- package/dist/card-utils-l80qAmrN.js +312 -0
- package/dist/chart-core-DV7hD3ZY.js +801 -0
- package/dist/checkbox-utils-DKdrhAzF.js +337 -0
- package/dist/chip-utils-DpRrd7Zj.js +403 -0
- package/dist/{data-source-controller-C6C4ej_M.js → data-source-controller-DS_JLrmS.js} +1 -1
- package/dist/{data-source-options-fxT5QIX4.js → data-source-options-DJUNU26C.js} +6 -6
- package/dist/{data-source-read-BL266IW0.js → data-source-read-uKJpRAzx.js} +2 -2
- package/dist/date-core-CyuSyvvG.js +734 -0
- package/dist/drawer-core-DbFWvNln.js +759 -0
- package/dist/dropdown-core-BCH1pK14.js +511 -0
- package/dist/dropdown-table-core-SfHUJVFq.js +1342 -0
- package/dist/export.js +1 -1
- package/dist/{field-path-BabiMrrA.js → field-path-DK2VBWHl.js} +1 -1
- package/dist/field-tooltip.css_raw-DVblekCl.js +5 -0
- package/dist/{field-validation.css_raw-Cx6SGrfP.js → field-validation.css_raw-BU7C6173.js} +1 -170
- package/dist/file-upload-core-Cz_dBQMx.js +624 -0
- package/dist/filter-builder-core-DyWjbBP7.js +381 -0
- package/dist/{filter-builder-B6Y2mmbM.js → filter-builder-vbqIuPhX.js} +1 -1
- package/dist/{filter-eval-ChDSaAUH.js → filter-eval-CqeBnMYh.js} +1 -1
- package/dist/{filter-odata-Bi27XUpQ.js → filter-odata-GsczYKNC.js} +1 -1
- package/dist/{hydration-flush-BaE9gN3C.js → hydration-flush-Volt9X7Q.js} +2 -1071
- package/dist/index.js +11 -11
- package/dist/{index.node-DTqDBca7.js → index.node-Csy9zrr1.js} +4 -4
- package/dist/index.node.js +11 -11
- package/dist/input-utils-BglY-k0H.js +1145 -0
- package/dist/menu-core-DkAYuCZ2.js +831 -0
- package/dist/modal-core-CSBSPN_m.js +844 -0
- package/dist/mono-button-DVvZ03P-.js +280 -0
- package/dist/{mono-button.shadow-DqZMpcqY.js → mono-button.shadow-BANxMGln.js} +6 -594
- package/dist/{mono-data-chart-NKPdAgVq.js → mono-data-chart-ChF4J9RT.js} +6 -6
- package/dist/{mono-data-dropdown-B2iRpJuI.js → mono-data-dropdown-Bgj2PDfm.js} +1 -1
- package/dist/{mono-data-grid-llJCX9MC.js → mono-data-grid-DJkp96N-.js} +144 -46
- package/dist/{mono-event-BPku9HpS.js → mono-event-CAZf0F_k.js} +14 -9
- package/dist/{mono-form-controller-BrA10erm.js → mono-form-controller-DxZLvyg6.js} +2 -1
- package/dist/mono-table-checkbox-core-BKOMx8R5.js +5288 -0
- package/dist/nav-core-B5qU2dzn.js +225 -0
- package/dist/{normalize-error-D93O4q8g.js → normalize-error-BEcd1tmS.js} +2 -2
- package/dist/otp-core-DXg3vFLh.js +758 -0
- package/dist/radio-utils-Dk9Tl1jz.js +319 -0
- package/dist/rich-text-editor-core-Ddd_QaLn.js +1280 -0
- package/dist/select-utils-BgArYHk8.js +2140 -0
- package/dist/sidebar-core-CD6txDo3.js +583 -0
- package/dist/slider-core-vcWr321-.js +1014 -0
- package/dist/src/components/dropdown-table/dropdown-table-core.d.ts +2 -2
- package/dist/src/components/dropdown-table/dropdown-table-types.d.ts +1 -1
- package/dist/src/components/dropdown-table/index.d.ts +1 -1
- package/dist/src/components/dropdown-table/index.shadow.d.ts +1 -1
- package/dist/src/components/dropdown-table/mono-data-dropdown.d.ts +1 -1
- package/dist/src/components/form/form-types.d.ts +9 -3
- package/dist/src/components/input/input-core.d.ts +1 -1
- package/dist/src/components/input/input-types.d.ts +1 -1
- package/dist/src/components/otp/otp-core.d.ts +1 -1
- package/dist/src/components/select/select-core.d.ts +1 -1
- package/dist/src/components/select/select-types.d.ts +1 -1
- package/dist/src/components/slider/slider-core.d.ts +1 -1
- package/dist/src/components/slider/slider-types.d.ts +1 -1
- package/dist/src/components/table/filter-suggestion.d.ts +171 -0
- package/dist/src/components/table/index.d.ts +5 -4
- package/dist/src/components/table/index.shadow.d.ts +5 -4
- package/dist/src/components/table/mono-data-grid.d.ts +22 -3
- package/dist/src/components/table/mono-table-empty-core.d.ts +37 -0
- package/dist/src/components/table/mono-table-search-core.d.ts +22 -3
- package/dist/src/components/table/table-types.d.ts +74 -4
- package/dist/src/components/tag-input/tag-input-core.d.ts +1 -1
- package/dist/src/components/tag-input/tag-input-types.d.ts +1 -1
- package/dist/src/components/textarea/textarea-core.d.ts +1 -1
- package/dist/src/composables/mono-event.d.ts +7 -1
- package/dist/src/entries/index.d.ts +8 -6
- package/dist/src/entries/index.node.d.ts +8 -6
- package/dist/src/search/index.d.ts +1 -1
- package/dist/src/utils/group-count.d.ts +36 -0
- package/dist/switch-utils-CTZ4id2V.js +338 -0
- package/dist/tabs-core-r5-B8k_N.js +317 -0
- package/dist/tag-input-utils-D2JA90DQ.js +3060 -0
- package/dist/textarea-utils-VU1KeXm8.js +821 -0
- package/dist/ui/accordion.js +2 -274
- package/dist/ui/alert.js +2 -131
- package/dist/ui/breadcrumb.js +4 -745
- package/dist/ui/button-dropdown.js +4 -652
- package/dist/ui/button.js +2 -63
- package/dist/ui/card.js +2 -310
- package/dist/ui/chart.js +4 -800
- package/dist/ui/checkbox.js +4 -335
- package/dist/ui/chip.js +4 -402
- package/dist/ui/date.js +3 -732
- package/dist/ui/drawer.js +3 -757
- package/dist/ui/dropdown-table.js +5 -1341
- package/dist/ui/dropdown.js +4 -509
- package/dist/ui/file-upload.js +3 -622
- package/dist/ui/filter.js +5 -380
- package/dist/ui/form.js +1 -1
- package/dist/ui/index.css +118 -1
- package/dist/ui/input.js +3 -1141
- package/dist/ui/menu.js +4 -828
- package/dist/ui/modal.js +4 -843
- package/dist/ui/nav.js +4 -223
- package/dist/ui/otp.js +4 -756
- package/dist/ui/radio.js +4 -317
- package/dist/ui/rich-text-editor.js +4 -1278
- package/dist/ui/select.js +5 -2138
- package/dist/ui/shadow/accordion.js +4 -273
- package/dist/ui/shadow/alert.js +4 -130
- package/dist/ui/shadow/breadcrumb.js +5 -744
- package/dist/ui/shadow/button-dropdown.js +6 -652
- package/dist/ui/shadow/button.js +3 -63
- package/dist/ui/shadow/card.js +4 -309
- package/dist/ui/shadow/chart.js +6 -1576
- package/dist/ui/shadow/checkbox.js +4 -334
- package/dist/ui/shadow/chip.js +4 -396
- package/dist/ui/shadow/date.js +7 -731
- package/dist/ui/shadow/drawer.js +4 -756
- package/dist/ui/shadow/dropdown-table.js +8 -1762
- package/dist/ui/shadow/dropdown.js +4 -508
- package/dist/ui/shadow/file-upload.js +4 -620
- package/dist/ui/shadow/filter.js +7 -379
- package/dist/ui/shadow/input.js +6 -1140
- package/dist/ui/shadow/menu.js +5 -828
- package/dist/ui/shadow/modal.js +6 -1063
- package/dist/ui/shadow/nav.js +5 -223
- package/dist/ui/shadow/otp.js +6 -754
- package/dist/ui/shadow/radio.js +4 -316
- package/dist/ui/shadow/rich-text-editor.js +4 -1276
- package/dist/ui/shadow/select.js +6 -2136
- package/dist/ui/shadow/sidebar.js +5 -581
- package/dist/ui/shadow/slider.js +5 -1010
- package/dist/ui/shadow/switch.js +4 -335
- package/dist/ui/shadow/table.js +10 -4501
- package/dist/ui/shadow/tabs.js +6 -315
- package/dist/ui/shadow/tag-input.js +7 -3057
- package/dist/ui/shadow/textarea.js +6 -817
- package/dist/ui/sidebar.js +3 -581
- package/dist/ui/slider.js +4 -1012
- package/dist/ui/switch.js +4 -336
- package/dist/ui/table.js +9 -4502
- package/dist/ui/tabs.js +4 -315
- package/dist/ui/tag-input.js +5 -3058
- package/dist/ui/textarea.js +4 -819
- package/dist/vue.d.ts +3 -2
- package/package.json +3 -3
- package/dist/chip-strip-bNfLn52Z.js +0 -215
- package/dist/data-source-controller-Dx6IQ2CN.js +0 -243
- package/dist/data-source-options-BM4r4PRw.js +0 -558
- package/dist/data-source-read-HyBCRg1t.js +0 -242
- package/dist/excel-BXzr3uI1.js +0 -784
- package/dist/export-ixRdCS2y.js +0 -2388
- package/dist/field-tooltip-addon-CWCp19mJ.js +0 -702
- package/dist/field-tooltip.css_raw-U5UeTa2d.js +0 -269
- package/dist/filter-builder-C0T3pMx2.js +0 -208
- package/dist/form-control-core-BbiACMtL.js +0 -226
- package/dist/icon-ClxnYhBG.js +0 -19
- package/dist/import-Dc4eXC02.js +0 -612
- package/dist/light-slots-_no0r2Z-.js +0 -246
- package/dist/markdown-uGlE_OfJ.js +0 -20191
- package/dist/mono-data-grid-e9ZVBlNN.js +0 -4240
- 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, imageGallery"` 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 };
|