@mgdis/mg-components 6.24.0 → 6.26.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.
- package/dist/cjs/index-Acmyl4hv.js +5 -0
- package/dist/cjs/{index-BxB20_Vw.js → index-B6J2EllP.js} +3 -1
- package/dist/cjs/{index-BEF-cqV9.js → index-BmFwLEZT.js} +5 -1
- package/dist/cjs/{index-CpENFzEo.js → index-DrZECzp6.js} +14 -6
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/mg-action-more_36.cjs.entry.js +452 -261
- package/dist/cjs/mg-alert.cjs.entry.js +7 -8
- package/dist/cjs/mg-breadcrumb.cjs.entry.js +27 -10
- package/dist/cjs/mg-components.cjs.js +2 -2
- package/dist/cjs/mg-fieldset.cjs.entry.js +8 -8
- package/dist/cjs/mg-illustration.cjs.entry.js +57 -0
- package/dist/cjs/mg-input-combobox.cjs.entry.js +40 -23
- package/dist/cjs/mg-input-file.cjs.entry.js +12 -11
- package/dist/cjs/mg-input-rich-text-editor.cjs.entry.js +2565 -4013
- package/dist/cjs/mg-loader.cjs.entry.js +5 -5
- package/dist/cjs/mg-progress.cjs.entry.js +3 -3
- package/dist/collection/assets/illustrations/index.js +1 -0
- package/dist/collection/assets/jodit/jodit.css +5821 -0
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/atoms/internals/mg-character-left/mg-character-left.js +1 -1
- package/dist/collection/components/atoms/internals/mg-input-title/mg-input-title.js +1 -1
- package/dist/collection/components/atoms/mg-badge/mg-badge.js +1 -1
- package/dist/collection/components/atoms/mg-button/mg-button.js +4 -1
- package/dist/collection/components/atoms/mg-card/mg-card.js +1 -1
- package/dist/collection/components/atoms/mg-divider/mg-divider.conf.js +4 -0
- package/dist/collection/components/atoms/mg-divider/mg-divider.js +62 -3
- package/dist/collection/components/atoms/mg-icon/mg-icon.js +1 -1
- package/dist/collection/components/atoms/mg-illustration/mg-illustration.conf.js +1 -0
- package/dist/collection/components/atoms/mg-illustration/mg-illustration.js +95 -0
- package/dist/collection/components/atoms/mg-tag/mg-tag.js +1 -1
- package/dist/collection/components/atoms/mg-tooltip/mg-tooltip-content/mg-tooltip-content.js +1 -1
- package/dist/collection/components/atoms/mg-tooltip/mg-tooltip.js +9 -7
- package/dist/collection/components/molecules/inputs/mg-input/mg-input.js +84 -19
- package/dist/collection/components/molecules/inputs/mg-input-checkbox/MgInputCheckboxList.js +5 -2
- package/dist/collection/components/molecules/inputs/mg-input-checkbox/MgInputCheckboxPaginated.js +5 -1
- package/dist/collection/components/molecules/inputs/mg-input-checkbox/mg-input-checkbox.js +30 -22
- package/dist/collection/components/molecules/inputs/mg-input-combobox/mg-input-combobox.js +69 -25
- package/dist/collection/components/molecules/inputs/mg-input-date/mg-input-date.js +14 -8
- package/dist/collection/components/molecules/inputs/mg-input-file/mg-input-file.js +8 -7
- package/dist/collection/components/molecules/inputs/mg-input-numeric/mg-input-numeric.js +21 -12
- package/dist/collection/components/molecules/inputs/mg-input-password/mg-input-password.js +9 -8
- package/dist/collection/components/molecules/inputs/mg-input-radio/mg-input-radio.js +15 -10
- package/dist/collection/components/molecules/inputs/mg-input-rich-text-editor/editor/custom-properties.css +50 -0
- package/dist/collection/components/molecules/inputs/mg-input-rich-text-editor/editor/index.js +29 -3
- package/dist/collection/components/molecules/inputs/mg-input-rich-text-editor/mg-input-rich-text-editor.js +262 -9
- package/dist/collection/components/molecules/inputs/mg-input-select/mg-input-select.js +21 -19
- package/dist/collection/components/molecules/inputs/mg-input-text/mg-input-text.js +18 -13
- package/dist/collection/components/molecules/inputs/mg-input-textarea/mg-input-textarea.js +7 -7
- package/dist/collection/components/molecules/inputs/mg-input-toggle/mg-input-toggle.js +10 -9
- package/dist/collection/components/molecules/internals/mg-item-more/mg-item-more.js +1 -1
- package/dist/collection/components/molecules/menus/mg-menu/mg-menu.js +7 -5
- package/dist/collection/components/molecules/menus/mg-menu-item/mg-menu-item.js +18 -17
- package/dist/collection/components/molecules/mg-action-more/mg-action-more.js +7 -4
- package/dist/collection/components/molecules/mg-alert/mg-alert.js +6 -7
- package/dist/collection/components/molecules/mg-breadcrumb/mg-breadcrumb.js +49 -6
- package/dist/collection/components/molecules/mg-details/mg-details.js +1 -1
- package/dist/collection/components/molecules/mg-fieldset/mg-fieldset.js +6 -6
- package/dist/collection/components/molecules/mg-form/mg-form.js +16 -13
- package/dist/collection/components/molecules/mg-illustrated-message/mg-illustrated-message.conf.js +4 -0
- package/dist/collection/components/molecules/mg-illustrated-message/mg-illustrated-message.js +51 -2
- package/dist/collection/components/molecules/mg-loader/mg-loader.js +1 -1
- package/dist/collection/components/molecules/mg-message/mg-message.js +2 -2
- package/dist/collection/components/molecules/mg-modal/mg-modal.js +2 -2
- package/dist/collection/components/molecules/mg-pagination/mg-pagination.js +8 -4
- package/dist/collection/components/molecules/mg-panel/mg-panel.js +13 -4
- package/dist/collection/components/molecules/mg-popover/mg-popover-content/mg-popover-content.js +2 -2
- package/dist/collection/components/molecules/mg-popover/mg-popover.js +24 -37
- package/dist/collection/components/molecules/mg-progress/mg-progress.js +1 -1
- package/dist/collection/components/molecules/mg-skip-links/mg-skip-links.js +5 -3
- package/dist/collection/components/molecules/mg-table/mg-table.js +10 -6
- package/dist/collection/components/molecules/mg-tabs/mg-tabs.js +12 -9
- package/dist/collection/utils/behaviors.utils.js +3 -3
- package/dist/collection/utils/playwright.fixture.js +7 -2
- package/dist/components/mg-action-more.js +1 -1
- package/dist/components/mg-alert.js +1 -1
- package/dist/components/mg-badge2.js +1 -1
- package/dist/components/mg-breadcrumb.js +1 -1
- package/dist/components/mg-button2.js +1 -1
- package/dist/components/mg-card2.js +1 -1
- package/dist/components/mg-character-left2.js +1 -1
- package/dist/components/mg-details.js +1 -1
- package/dist/components/mg-divider2.js +1 -1
- package/dist/components/mg-fieldset.js +1 -1
- package/dist/components/mg-form.js +1 -1
- package/dist/components/mg-icon2.js +1 -1
- package/dist/components/mg-illustrated-message.js +1 -1
- package/dist/components/mg-illustration.d.ts +11 -0
- package/dist/components/mg-illustration.js +1 -0
- package/dist/components/mg-input-checkbox.js +1 -1
- package/dist/components/mg-input-combobox.js +1 -1
- package/dist/components/mg-input-date.js +1 -1
- package/dist/components/mg-input-file.js +1 -1
- package/dist/components/mg-input-numeric.js +1 -1
- package/dist/components/mg-input-password.js +1 -1
- package/dist/components/mg-input-radio.js +1 -1
- package/dist/components/mg-input-rich-text-editor.js +294 -284
- package/dist/components/mg-input-select2.js +1 -1
- package/dist/components/mg-input-text2.js +1 -1
- package/dist/components/mg-input-textarea.js +1 -1
- package/dist/components/mg-input-title2.js +1 -1
- package/dist/components/mg-input-toggle.js +1 -1
- package/dist/components/mg-input2.js +1 -1
- package/dist/components/mg-item-more2.js +1 -1
- package/dist/components/mg-loader2.js +1 -1
- package/dist/components/mg-menu-item2.js +1 -1
- package/dist/components/mg-message2.js +1 -1
- package/dist/components/mg-modal.js +1 -1
- package/dist/components/mg-pagination.js +1 -1
- package/dist/components/mg-panel.js +1 -1
- package/dist/components/mg-popover-content2.js +1 -1
- package/dist/components/mg-popover2.js +1 -1
- package/dist/components/mg-progress.js +1 -1
- package/dist/components/mg-skip-links.js +1 -1
- package/dist/components/mg-table.js +1 -1
- package/dist/components/mg-tabs2.js +1 -1
- package/dist/components/mg-tag.js +1 -1
- package/dist/components/mg-tooltip-content2.js +1 -1
- package/dist/components/mg-tooltip2.js +1 -1
- package/dist/custom-elements.json +197 -48
- package/dist/esm/{index-C7xjtdiw.js → index-91BOpzAB.js} +14 -6
- package/dist/esm/{index-DSEloqPn.js → index-BfblyCaJ.js} +3 -1
- package/dist/esm/index-Ci9Hv7DG.js +3 -0
- package/dist/esm/{index-DshvCiTL.js → index-D4bO_UCn.js} +5 -1
- package/dist/esm/loader.js +3 -3
- package/dist/esm/mg-action-more_36.entry.js +449 -258
- package/dist/esm/mg-alert.entry.js +7 -8
- package/dist/esm/mg-breadcrumb.entry.js +27 -10
- package/dist/esm/mg-components.js +3 -3
- package/dist/esm/mg-fieldset.entry.js +8 -8
- package/dist/esm/mg-illustration.entry.js +55 -0
- package/dist/esm/mg-input-combobox.entry.js +40 -23
- package/dist/esm/mg-input-file.entry.js +12 -11
- package/dist/esm/mg-input-rich-text-editor.entry.js +2550 -3998
- package/dist/esm/mg-loader.entry.js +5 -5
- package/dist/esm/mg-progress.entry.js +3 -3
- package/dist/mg-components/mg-components.css +1 -1
- package/dist/mg-components/mg-components.esm.js +1 -1
- package/dist/mg-components/p-206505b5.entry.js +1667 -0
- package/dist/mg-components/{p-cdb01923.entry.js → p-3ad7441c.entry.js} +1 -1
- package/dist/mg-components/p-413b4536.entry.js +1 -0
- package/dist/mg-components/p-5dff879a.entry.js +1 -0
- package/dist/mg-components/{p-08d3d957.entry.js → p-96fc508e.entry.js} +1 -1
- package/dist/mg-components/p-Ci9Hv7DG.js +1 -0
- package/dist/mg-components/p-D4bO_UCn.js +2 -0
- package/dist/mg-components/{p-d0b6d8f5.entry.js → p-ad533d08.entry.js} +1 -1
- package/dist/mg-components/p-b20f3698.entry.js +1 -0
- package/dist/mg-components/p-bf2252c9.entry.js +1 -0
- package/dist/mg-components/p-d0d12800.entry.js +1 -0
- package/dist/mg-components/p-f8e58181.entry.js +1 -0
- package/dist/types/assets/illustrations/index.d.ts +21 -0
- package/dist/types/components/atoms/mg-divider/mg-divider.conf.d.ts +9 -0
- package/dist/types/components/atoms/mg-divider/mg-divider.d.ts +13 -0
- package/dist/types/components/atoms/mg-illustration/mg-illustration.conf.d.ts +5 -0
- package/dist/types/components/atoms/mg-illustration/mg-illustration.d.ts +24 -0
- package/dist/types/components/molecules/inputs/mg-input/mg-input.d.ts +19 -0
- package/dist/types/components/molecules/inputs/mg-input-checkbox/mg-input-checkbox.d.ts +1 -1
- package/dist/types/components/molecules/inputs/mg-input-combobox/mg-input-combobox.d.ts +10 -5
- package/dist/types/components/molecules/inputs/mg-input-date/mg-input-date.d.ts +2 -2
- package/dist/types/components/molecules/inputs/mg-input-numeric/mg-input-numeric.d.ts +2 -2
- package/dist/types/components/molecules/inputs/mg-input-password/mg-input-password.d.ts +2 -2
- package/dist/types/components/molecules/inputs/mg-input-radio/mg-input-radio.d.ts +1 -1
- package/dist/types/components/molecules/inputs/mg-input-rich-text-editor/editor/editor.conf.d.ts +4 -0
- package/dist/types/components/molecules/inputs/mg-input-rich-text-editor/mg-input-rich-text-editor.conf.d.ts +25 -0
- package/dist/types/components/molecules/inputs/mg-input-rich-text-editor/mg-input-rich-text-editor.d.ts +61 -2
- package/dist/types/components/molecules/inputs/mg-input-select/mg-input-select.d.ts +2 -2
- package/dist/types/components/molecules/inputs/mg-input-text/mg-input-text.d.ts +2 -2
- package/dist/types/components/molecules/inputs/mg-input-textarea/mg-input-textarea.d.ts +2 -2
- package/dist/types/components/molecules/inputs/mg-input-toggle/mg-input-toggle.d.ts +2 -2
- package/dist/types/components/molecules/menus/mg-menu-item/mg-menu-item.d.ts +2 -2
- package/dist/types/components/molecules/mg-alert/mg-alert.d.ts +2 -2
- package/dist/types/components/molecules/mg-breadcrumb/mg-breadcrumb.d.ts +11 -0
- package/dist/types/components/molecules/mg-illustrated-message/mg-illustrated-message.conf.d.ts +8 -0
- package/dist/types/components/molecules/mg-illustrated-message/mg-illustrated-message.d.ts +9 -1
- package/dist/types/components/molecules/mg-popover/mg-popover-content/mg-popover-content.d.ts +1 -1
- package/dist/types/components/molecules/mg-popover/mg-popover.d.ts +3 -3
- package/dist/types/components/molecules/mg-skip-links/mg-skip-links.d.ts +1 -1
- package/dist/types/components/molecules/mg-tabs/mg-tabs.d.ts +1 -1
- package/dist/types/components.d.ts +158 -42
- package/ide/intellij/web-types.json +145 -65
- package/ide/vscode/css-custom-data.json +6 -2
- package/ide/vscode/html-custom-data.json +216 -33
- package/package.json +22 -22
- package/dist/collection/components/molecules/inputs/mg-input-rich-text-editor/editor/custom-properties.scss +0 -212
- package/dist/mg-components/p-13feb37a.entry.js +0 -1
- package/dist/mg-components/p-7c63e469.entry.js +0 -1
- package/dist/mg-components/p-7fd3e519.entry.js +0 -1
- package/dist/mg-components/p-9953b835.entry.js +0 -1
- package/dist/mg-components/p-9c0a9fc7.entry.js +0 -1657
- package/dist/mg-components/p-DshvCiTL.js +0 -2
- package/dist/mg-components/p-a338088e.entry.js +0 -1
- /package/dist/mg-components/{p-C7xjtdiw.js → p-91BOpzAB.js} +0 -0
- /package/dist/mg-components/{p-DSEloqPn.js → p-BfblyCaJ.js} +0 -0
|
@@ -5,9 +5,33 @@ import { classReadonly, classDisabled } from "../mg-input/mg-input.conf";
|
|
|
5
5
|
import { initLocales } from "../../../../locales";
|
|
6
6
|
import { Sanitizer } from "@mgdis/sanitize-html";
|
|
7
7
|
import { defineEditor } from "./editor";
|
|
8
|
-
import {
|
|
8
|
+
import { icons } from "../../../../assets/icons";
|
|
9
|
+
import { DEFAULT_MODULES, } from "./mg-input-rich-text-editor.conf";
|
|
10
|
+
/**
|
|
11
|
+
* RichTextEditorCustomAction type guard
|
|
12
|
+
* @param action - customActions array entry
|
|
13
|
+
* @returns true if action matches RichTextEditorCustomAction shape
|
|
14
|
+
*/
|
|
15
|
+
const isValidCustomAction = (action) => {
|
|
16
|
+
const candidate = action;
|
|
17
|
+
return (typeof candidate === 'object' &&
|
|
18
|
+
candidate !== null &&
|
|
19
|
+
isValidString(candidate.name) &&
|
|
20
|
+
isValidString(candidate.label) &&
|
|
21
|
+
isValidString(candidate.icon));
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Check if an array contains duplicate values
|
|
25
|
+
* @param values - values to check
|
|
26
|
+
* @returns true if at least one value appears more than once
|
|
27
|
+
*/
|
|
28
|
+
const hasDuplicates = (values) => new Set(values).size !== values.length;
|
|
9
29
|
export class MgInputRichTextEditor {
|
|
10
30
|
constructor() {
|
|
31
|
+
// Snapshot of the selection captured when a custom action is triggered.
|
|
32
|
+
// Lets consumers read/replace the selection after an async operation (e.g. a network request),
|
|
33
|
+
// even though focus has moved to the toolbar button or their own UI meanwhile.
|
|
34
|
+
this.savedSelection = null;
|
|
11
35
|
// hasDisplayedError (triggered by blur event)
|
|
12
36
|
this.hasDisplayedError = false;
|
|
13
37
|
// Custom error message
|
|
@@ -134,6 +158,44 @@ export class MgInputRichTextEditor {
|
|
|
134
158
|
if (this.hasDisplayedError) {
|
|
135
159
|
this.setErrorMessage();
|
|
136
160
|
}
|
|
161
|
+
// Content changed: any previously snapshotted selection range is now stale
|
|
162
|
+
this.savedSelection = null;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Capture the current selection (plain text, sanitized HTML and a cloned range).
|
|
166
|
+
* @returns Selection snapshot
|
|
167
|
+
*/
|
|
168
|
+
this.captureSelection = () => {
|
|
169
|
+
const selection = this.editor.s;
|
|
170
|
+
return {
|
|
171
|
+
text: selection.range.toString(),
|
|
172
|
+
html: this.sanitizer.sanitize(selection.html),
|
|
173
|
+
range: selection.range.cloneRange(),
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Handle a custom action button click.
|
|
178
|
+
* Snapshots the current selection then emits the `custom-action` event with the action name.
|
|
179
|
+
* @param name - the triggered action name
|
|
180
|
+
*/
|
|
181
|
+
this.handleCustomAction = (name) => {
|
|
182
|
+
if (this.readonly || this.disabled)
|
|
183
|
+
return;
|
|
184
|
+
this.savedSelection = this.captureSelection();
|
|
185
|
+
this.customAction.emit(name);
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Handle Jodit `changeSelection` event: emit the `selection-change` event.
|
|
189
|
+
*/
|
|
190
|
+
this.handleSelectionChange = () => {
|
|
191
|
+
if (this.editor === undefined || this.readonly || this.disabled)
|
|
192
|
+
return;
|
|
193
|
+
const selection = this.editor.s;
|
|
194
|
+
this.selectionChange.emit({
|
|
195
|
+
text: selection.range.toString(),
|
|
196
|
+
html: this.sanitizer.sanitize(selection.html),
|
|
197
|
+
isCollapsed: selection.isCollapsed(),
|
|
198
|
+
});
|
|
137
199
|
};
|
|
138
200
|
/**
|
|
139
201
|
* Initialize sanitizer with current sanitizerOptions
|
|
@@ -186,10 +248,29 @@ export class MgInputRichTextEditor {
|
|
|
186
248
|
}
|
|
187
249
|
}
|
|
188
250
|
watchModules(newValue) {
|
|
189
|
-
if (newValue !== undefined &&
|
|
251
|
+
if (newValue !== undefined &&
|
|
252
|
+
(!Array.isArray(newValue) || newValue.length === 0 || !newValue.every(isValidString))) {
|
|
190
253
|
throw new Error(`<mg-input-rich-text-editor> prop "modules" must be a non-empty array of strings. Passed value: "${toString(newValue)}".`);
|
|
191
254
|
}
|
|
192
255
|
}
|
|
256
|
+
watchCustomActions(newValue) {
|
|
257
|
+
if (newValue === undefined)
|
|
258
|
+
return;
|
|
259
|
+
if (!Array.isArray(newValue) ||
|
|
260
|
+
!newValue.every(isValidCustomAction) ||
|
|
261
|
+
hasDuplicates(newValue.map((action) => action.name))) {
|
|
262
|
+
throw new Error(`<mg-input-rich-text-editor> prop "customActions" must be an array of objects with non-empty and unique "name", non-empty "label" and non-empty "icon". Passed value: "${toString(newValue)}".`);
|
|
263
|
+
}
|
|
264
|
+
// Restrict icons to the design system icon set (mg-icon names) for consistent theming and maintenance
|
|
265
|
+
const actionWithInvalidIcon = newValue.find((action) => !Object.hasOwn(icons, action.icon));
|
|
266
|
+
if (actionWithInvalidIcon !== undefined) {
|
|
267
|
+
throw new Error(`<mg-input-rich-text-editor> prop "customActions" icon must be a valid mg-icon name. Passed value: "${toString(actionWithInvalidIcon.icon)}".`);
|
|
268
|
+
}
|
|
269
|
+
// Two custom actions sharing the same icon would be visually indistinguishable in the toolbar
|
|
270
|
+
if (hasDuplicates(newValue.map((action) => action.icon))) {
|
|
271
|
+
throw new Error(`<mg-input-rich-text-editor> prop "customActions" icon must be unique across actions. Passed value: "${toString(newValue)}".`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
193
274
|
watchSanitizerOptions(newValue) {
|
|
194
275
|
if (newValue !== undefined && (typeof newValue !== 'object' || newValue === null || Array.isArray(newValue))) {
|
|
195
276
|
throw new Error(`<mg-input-rich-text-editor> prop "sanitizerOptions" must be an object. Passed value: "${toString(newValue)}".`);
|
|
@@ -219,6 +300,46 @@ export class MgInputRichTextEditor {
|
|
|
219
300
|
async getEditorText() {
|
|
220
301
|
return this.editor.editor.textContent.trim();
|
|
221
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* Get the current text selection as plain text.
|
|
305
|
+
* When a custom action is in progress, returns the selection snapshotted when the action was triggered.
|
|
306
|
+
* @returns Plain text of the selection (empty string if nothing is selected)
|
|
307
|
+
*/
|
|
308
|
+
async getSelectedText() {
|
|
309
|
+
var _a, _b;
|
|
310
|
+
if (this.savedSelection !== null)
|
|
311
|
+
return this.savedSelection.text;
|
|
312
|
+
return (_b = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.s.range.toString()) !== null && _b !== void 0 ? _b : '';
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get the current text selection as HTML.
|
|
316
|
+
* When a custom action is in progress, returns the selection snapshotted when the action was triggered.
|
|
317
|
+
* @returns Sanitized HTML of the selection (empty string if nothing is selected)
|
|
318
|
+
*/
|
|
319
|
+
async getSelectedHTML() {
|
|
320
|
+
var _a, _b;
|
|
321
|
+
if (this.savedSelection !== null)
|
|
322
|
+
return this.savedSelection.html;
|
|
323
|
+
return this.sanitizer.sanitize((_b = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.s.html) !== null && _b !== void 0 ? _b : '');
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Replace the current text selection with the given content.
|
|
327
|
+
* When a custom action is in progress, the selection snapshotted when the action was triggered is
|
|
328
|
+
* restored first, so the replacement targets the right range even after focus moved away (e.g. during
|
|
329
|
+
* an async network request). No-op when the editor is readonly or disabled.
|
|
330
|
+
* @param content - HTML (or plain text) content to insert in place of the selection. It is sanitized.
|
|
331
|
+
*/
|
|
332
|
+
async replaceSelection(content) {
|
|
333
|
+
if (this.readonly || this.disabled || this.editor === undefined)
|
|
334
|
+
return;
|
|
335
|
+
const sanitized = this.sanitizer.sanitize(content);
|
|
336
|
+
// Restore the snapshotted selection (survives focus changes during async work)
|
|
337
|
+
if (this.savedSelection !== null) {
|
|
338
|
+
this.editor.s.selectRange(this.savedSelection.range);
|
|
339
|
+
this.savedSelection = null;
|
|
340
|
+
}
|
|
341
|
+
this.editor.s.insertHTML(sanitized);
|
|
342
|
+
}
|
|
222
343
|
/**
|
|
223
344
|
* Display input error if it exists.
|
|
224
345
|
*/
|
|
@@ -229,7 +350,7 @@ export class MgInputRichTextEditor {
|
|
|
229
350
|
// - Async operations are completed
|
|
230
351
|
// - No timing issues with Stencil's render cycle
|
|
231
352
|
// - Keep everything in sync both inside and outside the component
|
|
232
|
-
return new Promise(resolve => {
|
|
353
|
+
return new Promise((resolve) => {
|
|
233
354
|
requestAnimationFrame(() => {
|
|
234
355
|
this.checkValidity();
|
|
235
356
|
this.setErrorMessage();
|
|
@@ -277,7 +398,7 @@ export class MgInputRichTextEditor {
|
|
|
277
398
|
// - Async operations are completed
|
|
278
399
|
// - No timing issues with Stencil's render cycle
|
|
279
400
|
// - Keep everything in sync both inside and outside the component
|
|
280
|
-
return new Promise(resolve => {
|
|
401
|
+
return new Promise((resolve) => {
|
|
281
402
|
requestAnimationFrame(() => {
|
|
282
403
|
// unlock validity check by reseting customErrorMessage
|
|
283
404
|
this.customErrorMessage = { lock: false };
|
|
@@ -321,6 +442,7 @@ export class MgInputRichTextEditor {
|
|
|
321
442
|
this.watchReadonly(this.readonly);
|
|
322
443
|
this.watchDisabled(this.disabled);
|
|
323
444
|
this.watchModules(this.modules);
|
|
445
|
+
this.watchCustomActions(this.customActions);
|
|
324
446
|
this.watchSanitizerOptions(this.sanitizerOptions);
|
|
325
447
|
// Initialize sanitizer with optional configuration
|
|
326
448
|
this.initializeSanitizer();
|
|
@@ -339,6 +461,7 @@ export class MgInputRichTextEditor {
|
|
|
339
461
|
if (!this.readonly) {
|
|
340
462
|
this.editor = defineEditor(this.element, this.editorElement, {
|
|
341
463
|
modules: (_a = this.modules) !== null && _a !== void 0 ? _a : DEFAULT_MODULES,
|
|
464
|
+
customActions: this.customActions,
|
|
342
465
|
readOnly: this.readonly || this.disabled,
|
|
343
466
|
disabled: this.disabled,
|
|
344
467
|
placeholder: this.placeholder,
|
|
@@ -347,6 +470,8 @@ export class MgInputRichTextEditor {
|
|
|
347
470
|
handleTextChange: this.handleTextChange,
|
|
348
471
|
handleBlur: this.handleBlur,
|
|
349
472
|
handleFocus: this.handleFocus,
|
|
473
|
+
handleCustomAction: this.handleCustomAction,
|
|
474
|
+
handleSelectionChange: this.handleSelectionChange,
|
|
350
475
|
});
|
|
351
476
|
// Track the initial title element set up by defineEditor
|
|
352
477
|
this.currentTitleElement = this.element.shadowRoot.querySelector('mg-input-title');
|
|
@@ -377,7 +502,7 @@ export class MgInputRichTextEditor {
|
|
|
377
502
|
* @returns HTML mg-input Element
|
|
378
503
|
*/
|
|
379
504
|
render() {
|
|
380
|
-
return (h("mg-input", { key: '
|
|
505
|
+
return (h("mg-input", { key: 'c42ba3eb1eafa645fa0774d65090c7819168ffd7', identifier: this.identifier, class: this.classCollection.join(), label: this.label, labelOnTop: this.labelOnTop, labelHide: this.labelHide, required: this.required, tooltip: this.tooltip, tooltipPosition: this.tooltipPosition, helpText: this.helpText, errorMessage: this.hasDisplayedError ? this.errorMessage : undefined }, this.readonly ? (h("div", { class: "mg-c-input__readonly-value", innerHTML: this.value })) : (h("div", { id: this.identifier, class: "mg-c-input__wrapper" }, h("textarea", { name: this.name, ref: (el) => {
|
|
381
506
|
if (el !== null)
|
|
382
507
|
this.editorElement = el;
|
|
383
508
|
} })))));
|
|
@@ -386,12 +511,12 @@ export class MgInputRichTextEditor {
|
|
|
386
511
|
static get encapsulation() { return "shadow"; }
|
|
387
512
|
static get originalStyleUrls() {
|
|
388
513
|
return {
|
|
389
|
-
"$": ["
|
|
514
|
+
"$": ["../../../../assets/jodit/jodit.css", "./editor/custom-properties.css", "../../../../../node_modules/@mgdis/styles/dist/components/mg-input-rich-text-editor.css"]
|
|
390
515
|
};
|
|
391
516
|
}
|
|
392
517
|
static get styleUrls() {
|
|
393
518
|
return {
|
|
394
|
-
"$": ["
|
|
519
|
+
"$": ["../../../../assets/jodit/jodit.css", "editor/custom-properties.css", "../../../../../node_modules/@mgdis/styles/dist/components/mg-input-rich-text-editor.css"]
|
|
395
520
|
};
|
|
396
521
|
}
|
|
397
522
|
static get properties() {
|
|
@@ -742,6 +867,30 @@ export class MgInputRichTextEditor {
|
|
|
742
867
|
"reflect": false,
|
|
743
868
|
"attribute": "modules"
|
|
744
869
|
},
|
|
870
|
+
"customActions": {
|
|
871
|
+
"type": "unknown",
|
|
872
|
+
"mutable": false,
|
|
873
|
+
"complexType": {
|
|
874
|
+
"original": "RichTextEditorCustomAction[]",
|
|
875
|
+
"resolved": "RichTextEditorCustomAction[]",
|
|
876
|
+
"references": {
|
|
877
|
+
"RichTextEditorCustomAction": {
|
|
878
|
+
"location": "import",
|
|
879
|
+
"path": "./mg-input-rich-text-editor.conf",
|
|
880
|
+
"id": "src/components/molecules/inputs/mg-input-rich-text-editor/mg-input-rich-text-editor.conf.ts::RichTextEditorCustomAction",
|
|
881
|
+
"referenceLocation": "RichTextEditorCustomAction"
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
},
|
|
885
|
+
"required": false,
|
|
886
|
+
"optional": true,
|
|
887
|
+
"docs": {
|
|
888
|
+
"tags": [],
|
|
889
|
+
"text": "Inject custom action buttons in the toolbar (e.g. to insert merge fields or apply custom formatting).\nButtons are appended after the built-in `modules`.\nEach action is an object `{ name, label, icon }`:\n- `name`: unique identifier, returned in the `custom-action` event detail on click.\n- `label`: accessible label used as the button tooltip and aria-label.\n- `icon`: design system `mg-icon` name rendered inside the button, unique across actions.\nThe action behaviour is the consumer's responsibility: listen to `custom-action`,\nthen read/write the selection with `getSelectedText()` / `getSelectedHTML()` / `replaceSelection()`."
|
|
890
|
+
},
|
|
891
|
+
"getter": false,
|
|
892
|
+
"setter": false
|
|
893
|
+
},
|
|
745
894
|
"sanitizerOptions": {
|
|
746
895
|
"type": "unknown",
|
|
747
896
|
"mutable": false,
|
|
@@ -821,7 +970,7 @@ export class MgInputRichTextEditor {
|
|
|
821
970
|
"composed": true,
|
|
822
971
|
"docs": {
|
|
823
972
|
"tags": [],
|
|
824
|
-
"text": "
|
|
973
|
+
"text": "Emitted event when checking validity"
|
|
825
974
|
},
|
|
826
975
|
"complexType": {
|
|
827
976
|
"original": "boolean",
|
|
@@ -836,13 +985,50 @@ export class MgInputRichTextEditor {
|
|
|
836
985
|
"composed": true,
|
|
837
986
|
"docs": {
|
|
838
987
|
"tags": [],
|
|
839
|
-
"text": "
|
|
988
|
+
"text": "Emitted event when value change"
|
|
989
|
+
},
|
|
990
|
+
"complexType": {
|
|
991
|
+
"original": "string",
|
|
992
|
+
"resolved": "string",
|
|
993
|
+
"references": {}
|
|
994
|
+
}
|
|
995
|
+
}, {
|
|
996
|
+
"method": "customAction",
|
|
997
|
+
"name": "custom-action",
|
|
998
|
+
"bubbles": true,
|
|
999
|
+
"cancelable": true,
|
|
1000
|
+
"composed": true,
|
|
1001
|
+
"docs": {
|
|
1002
|
+
"tags": [],
|
|
1003
|
+
"text": "Emitted event when a custom action button is clicked.\nThe detail contains the action `name`."
|
|
840
1004
|
},
|
|
841
1005
|
"complexType": {
|
|
842
1006
|
"original": "string",
|
|
843
1007
|
"resolved": "string",
|
|
844
1008
|
"references": {}
|
|
845
1009
|
}
|
|
1010
|
+
}, {
|
|
1011
|
+
"method": "selectionChange",
|
|
1012
|
+
"name": "selection-change",
|
|
1013
|
+
"bubbles": true,
|
|
1014
|
+
"cancelable": true,
|
|
1015
|
+
"composed": true,
|
|
1016
|
+
"docs": {
|
|
1017
|
+
"tags": [],
|
|
1018
|
+
"text": "Emitted event when the text selection changes.\nThe detail contains the selected `text`, sanitized `html` and whether the selection `isCollapsed`."
|
|
1019
|
+
},
|
|
1020
|
+
"complexType": {
|
|
1021
|
+
"original": "SelectionChange",
|
|
1022
|
+
"resolved": "{ text: string; html: string; isCollapsed: boolean; }",
|
|
1023
|
+
"references": {
|
|
1024
|
+
"SelectionChange": {
|
|
1025
|
+
"location": "import",
|
|
1026
|
+
"path": "./mg-input-rich-text-editor.conf",
|
|
1027
|
+
"id": "src/components/molecules/inputs/mg-input-rich-text-editor/mg-input-rich-text-editor.conf.ts::SelectionChange",
|
|
1028
|
+
"referenceLocation": "SelectionChange"
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
846
1032
|
}];
|
|
847
1033
|
}
|
|
848
1034
|
static get methods() {
|
|
@@ -904,6 +1090,70 @@ export class MgInputRichTextEditor {
|
|
|
904
1090
|
}]
|
|
905
1091
|
}
|
|
906
1092
|
},
|
|
1093
|
+
"getSelectedText": {
|
|
1094
|
+
"complexType": {
|
|
1095
|
+
"signature": "() => Promise<string>",
|
|
1096
|
+
"parameters": [],
|
|
1097
|
+
"references": {
|
|
1098
|
+
"Promise": {
|
|
1099
|
+
"location": "global",
|
|
1100
|
+
"id": "global::Promise"
|
|
1101
|
+
}
|
|
1102
|
+
},
|
|
1103
|
+
"return": "Promise<string>"
|
|
1104
|
+
},
|
|
1105
|
+
"docs": {
|
|
1106
|
+
"text": "Get the current text selection as plain text.\nWhen a custom action is in progress, returns the selection snapshotted when the action was triggered.",
|
|
1107
|
+
"tags": [{
|
|
1108
|
+
"name": "returns",
|
|
1109
|
+
"text": "Plain text of the selection (empty string if nothing is selected)"
|
|
1110
|
+
}]
|
|
1111
|
+
}
|
|
1112
|
+
},
|
|
1113
|
+
"getSelectedHTML": {
|
|
1114
|
+
"complexType": {
|
|
1115
|
+
"signature": "() => Promise<string>",
|
|
1116
|
+
"parameters": [],
|
|
1117
|
+
"references": {
|
|
1118
|
+
"Promise": {
|
|
1119
|
+
"location": "global",
|
|
1120
|
+
"id": "global::Promise"
|
|
1121
|
+
}
|
|
1122
|
+
},
|
|
1123
|
+
"return": "Promise<string>"
|
|
1124
|
+
},
|
|
1125
|
+
"docs": {
|
|
1126
|
+
"text": "Get the current text selection as HTML.\nWhen a custom action is in progress, returns the selection snapshotted when the action was triggered.",
|
|
1127
|
+
"tags": [{
|
|
1128
|
+
"name": "returns",
|
|
1129
|
+
"text": "Sanitized HTML of the selection (empty string if nothing is selected)"
|
|
1130
|
+
}]
|
|
1131
|
+
}
|
|
1132
|
+
},
|
|
1133
|
+
"replaceSelection": {
|
|
1134
|
+
"complexType": {
|
|
1135
|
+
"signature": "(content: string) => Promise<void>",
|
|
1136
|
+
"parameters": [{
|
|
1137
|
+
"name": "content",
|
|
1138
|
+
"type": "string",
|
|
1139
|
+
"docs": "- HTML (or plain text) content to insert in place of the selection. It is sanitized."
|
|
1140
|
+
}],
|
|
1141
|
+
"references": {
|
|
1142
|
+
"Promise": {
|
|
1143
|
+
"location": "global",
|
|
1144
|
+
"id": "global::Promise"
|
|
1145
|
+
}
|
|
1146
|
+
},
|
|
1147
|
+
"return": "Promise<void>"
|
|
1148
|
+
},
|
|
1149
|
+
"docs": {
|
|
1150
|
+
"text": "Replace the current text selection with the given content.\nWhen a custom action is in progress, the selection snapshotted when the action was triggered is\nrestored first, so the replacement targets the right range even after focus moved away (e.g. during\nan async network request). No-op when the editor is readonly or disabled.",
|
|
1151
|
+
"tags": [{
|
|
1152
|
+
"name": "param",
|
|
1153
|
+
"text": "content - HTML (or plain text) content to insert in place of the selection. It is sanitized."
|
|
1154
|
+
}]
|
|
1155
|
+
}
|
|
1156
|
+
},
|
|
907
1157
|
"displayError": {
|
|
908
1158
|
"complexType": {
|
|
909
1159
|
"signature": "() => Promise<void>",
|
|
@@ -1008,6 +1258,9 @@ export class MgInputRichTextEditor {
|
|
|
1008
1258
|
}, {
|
|
1009
1259
|
"propName": "modules",
|
|
1010
1260
|
"methodName": "watchModules"
|
|
1261
|
+
}, {
|
|
1262
|
+
"propName": "customActions",
|
|
1263
|
+
"methodName": "watchCustomActions"
|
|
1011
1264
|
}, {
|
|
1012
1265
|
"propName": "sanitizerOptions",
|
|
1013
1266
|
"methodName": "watchSanitizerOptions"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { h } from "@stencil/core";
|
|
2
2
|
import { ClassList, allItemsAreString, isValidString, toString } from "@mgdis/core-ui-helpers/dist/utils";
|
|
3
3
|
import { normalizeBooleanAttributes } from "@mgdis/core-ui-helpers/dist/stencil";
|
|
4
|
-
import { classReadonly, classDisabled, widths } from "../mg-input/mg-input.conf";
|
|
4
|
+
import { classReadonly, classDisabled, widths, } from "../mg-input/mg-input.conf";
|
|
5
5
|
import { initLocales } from "../../../../locales";
|
|
6
6
|
/**
|
|
7
7
|
* Check if item is a well configured option
|
|
@@ -14,13 +14,15 @@ const isOption = (option) => typeof option === 'object' && typeof option.title =
|
|
|
14
14
|
* @param items - select option
|
|
15
15
|
* @returns select option array type is valid
|
|
16
16
|
*/
|
|
17
|
-
const allItemsAreOptions = (items) => Array.isArray(items) && items.every(item => isOption(item));
|
|
17
|
+
const allItemsAreOptions = (items) => Array.isArray(items) && items.every((item) => isOption(item));
|
|
18
18
|
/**
|
|
19
19
|
* Check if item is a well configured optgroup
|
|
20
20
|
* @param optgroup - select option
|
|
21
21
|
* @returns select optgroup type is valid
|
|
22
22
|
*/
|
|
23
|
-
const isOptGroup = (optgroup) => typeof optgroup === 'object' &&
|
|
23
|
+
const isOptGroup = (optgroup) => typeof optgroup === 'object' &&
|
|
24
|
+
typeof optgroup.group === 'string' &&
|
|
25
|
+
allItemsAreOptions(optgroup.options);
|
|
24
26
|
/**
|
|
25
27
|
* Ensure options can be unambiguously differentiated by their title
|
|
26
28
|
* Two options can share the same title only when they belong to different groups
|
|
@@ -49,7 +51,7 @@ const validateUniqueTitles = (items) => {
|
|
|
49
51
|
const groupOptions = (acc, { group, title, value, disabled }) => {
|
|
50
52
|
if (group !== undefined) {
|
|
51
53
|
// Check if group is already created
|
|
52
|
-
const optGroup = acc.find(grp => grp.group === group);
|
|
54
|
+
const optGroup = acc.find((grp) => grp.group === group);
|
|
53
55
|
// Add to group
|
|
54
56
|
if (optGroup !== undefined) {
|
|
55
57
|
optGroup.options.push({ title, value, disabled });
|
|
@@ -117,10 +119,10 @@ export class MgInputSelect {
|
|
|
117
119
|
this.getReadonlyValue = () => {
|
|
118
120
|
var _a;
|
|
119
121
|
if (allItemsAreString(this.items) && typeof this.value === 'string') {
|
|
120
|
-
return this.items.find(item => item === this.value);
|
|
122
|
+
return this.items.find((item) => item === this.value);
|
|
121
123
|
}
|
|
122
124
|
else if (allItemsAreOptions(this.items)) {
|
|
123
|
-
return (_a = this.items.find(item => item.value === this.value)) === null || _a === void 0 ? void 0 : _a.title;
|
|
125
|
+
return (_a = this.items.find((item) => item.value === this.value)) === null || _a === void 0 ? void 0 : _a.title;
|
|
124
126
|
}
|
|
125
127
|
else {
|
|
126
128
|
return null;
|
|
@@ -131,7 +133,7 @@ export class MgInputSelect {
|
|
|
131
133
|
* The select value is the position of an option in this list, so it uniquely identifies an option even when several share the same title
|
|
132
134
|
* @returns flat select options
|
|
133
135
|
*/
|
|
134
|
-
this.getOptions = () => this.options.flatMap(option => (isOptGroup(option) ? option.options : [option]));
|
|
136
|
+
this.getOptions = () => this.options.flatMap((option) => (isOptGroup(option) ? option.options : [option]));
|
|
135
137
|
/**
|
|
136
138
|
* Get the option matching the current select value
|
|
137
139
|
* @returns matching option or undefined
|
|
@@ -145,7 +147,7 @@ export class MgInputSelect {
|
|
|
145
147
|
// The select value is normally the render index of the selected option
|
|
146
148
|
const optionByIndex = options[Number(this.input.value)];
|
|
147
149
|
// Fallback for an unknown value injected programmatically (stored as a disabled option keyed by its own value)
|
|
148
|
-
return optionByIndex !== null && optionByIndex !== void 0 ? optionByIndex : options.find(option => option.value === this.input.value);
|
|
150
|
+
return optionByIndex !== null && optionByIndex !== void 0 ? optionByIndex : options.find((option) => option.value === this.input.value);
|
|
149
151
|
};
|
|
150
152
|
/**
|
|
151
153
|
* Handle input event
|
|
@@ -230,18 +232,18 @@ export class MgInputSelect {
|
|
|
230
232
|
}
|
|
231
233
|
// String array
|
|
232
234
|
else if (allItemsAreString(newValue)) {
|
|
233
|
-
validateUniqueTitles(newValue.map(item => ({ title: item })));
|
|
235
|
+
validateUniqueTitles(newValue.map((item) => ({ title: item })));
|
|
234
236
|
if (typeof this.value === 'string') {
|
|
235
237
|
this.valueExist = newValue.includes(this.value);
|
|
236
238
|
}
|
|
237
|
-
this.options = newValue.map(item => ({ title: item, value: item }));
|
|
239
|
+
this.options = newValue.map((item) => ({ title: item, value: item }));
|
|
238
240
|
}
|
|
239
241
|
// Object array
|
|
240
242
|
else if (allItemsAreOptions(newValue)) {
|
|
241
243
|
validateUniqueTitles(newValue);
|
|
242
|
-
this.valueExist = newValue.map(item => item.value).includes(this.value);
|
|
244
|
+
this.valueExist = newValue.map((item) => item.value).includes(this.value);
|
|
243
245
|
// Grouped object options
|
|
244
|
-
if (newValue.some(item => Boolean(item.group))) {
|
|
246
|
+
if (newValue.some((item) => Boolean(item.group))) {
|
|
245
247
|
this.options = newValue.reduce(groupOptions, []);
|
|
246
248
|
}
|
|
247
249
|
// Standart object options
|
|
@@ -277,7 +279,7 @@ export class MgInputSelect {
|
|
|
277
279
|
}
|
|
278
280
|
watchMgWidth(newValue) {
|
|
279
281
|
// reset width class
|
|
280
|
-
widths.forEach(width => {
|
|
282
|
+
widths.forEach((width) => {
|
|
281
283
|
this.classCollection.delete(`mg-c-input--width-${width}`);
|
|
282
284
|
});
|
|
283
285
|
// apply new width
|
|
@@ -301,7 +303,7 @@ export class MgInputSelect {
|
|
|
301
303
|
// - Async operations are completed
|
|
302
304
|
// - No timing issues with Stencil's render cycle
|
|
303
305
|
// - Keep everything in sync both inside and outside the component
|
|
304
|
-
return new Promise(resolve => {
|
|
306
|
+
return new Promise((resolve) => {
|
|
305
307
|
requestAnimationFrame(() => {
|
|
306
308
|
this.checkValidity();
|
|
307
309
|
this.setErrorMessage();
|
|
@@ -348,7 +350,7 @@ export class MgInputSelect {
|
|
|
348
350
|
// - Async operations are completed
|
|
349
351
|
// - No timing issues with Stencil's render cycle
|
|
350
352
|
// - Keep everything in sync both inside and outside the component
|
|
351
|
-
return new Promise(resolve => {
|
|
353
|
+
return new Promise((resolve) => {
|
|
352
354
|
requestAnimationFrame(() => {
|
|
353
355
|
// unlock validity check by reseting customErrorMessage
|
|
354
356
|
this.customErrorMessage = { lock: false };
|
|
@@ -411,11 +413,11 @@ export class MgInputSelect {
|
|
|
411
413
|
const readonlyValue = this.getReadonlyValue();
|
|
412
414
|
// Running index shared across groups, so each option gets a unique value matching its position in getOptions()
|
|
413
415
|
let optionIndex = 0;
|
|
414
|
-
return (h("mg-input", { key: '
|
|
416
|
+
return (h("mg-input", { key: 'aab8c17ced01c0afbec9114f280ee2b7fa73cdfc', label: this.label, identifier: this.identifier, class: this.classCollection.join(), labelOnTop: this.labelOnTop, labelHide: this.labelHide, required: this.required, tooltip: this.tooltip, tooltipPosition: this.readonly && readonlyValue === null ? 'label' : this.tooltipPosition, helpText: this.helpText, errorMessage: this.errorMessage }, this.readonly ? (readonlyValue && h("b", { class: "mg-c-input__readonly-value" }, readonlyValue)) : (h("select", { class: "mg-c-input__box", id: this.identifier, name: this.name, title: this.placeholder, disabled: this.disabled, required: this.required, "aria-invalid": (this.invalid === true).toString(), onInput: this.handleInput, onBlur: this.handleBlur, ref: (el) => {
|
|
415
417
|
if (el !== null)
|
|
416
418
|
this.input = el;
|
|
417
419
|
} }, (!this.placeholderHide || !this.valueExist) && ( // In case passed value does not match any option we display the placeholder
|
|
418
|
-
h("option", { value: "", disabled: this.placeholderDisabled && this.valueExist }, this.placeholder)), this.options.map(option => isOptGroup(option) ? (h("optgroup", { label: option.group, key: option.group }, option.options.map(groupedOption => this.renderOption(groupedOption, optionIndex++)))) : (isOption(option) && this.renderOption(option, optionIndex++)))))));
|
|
420
|
+
h("option", { value: "", disabled: this.placeholderDisabled && this.valueExist }, this.placeholder)), this.options.map((option) => isOptGroup(option) ? (h("optgroup", { label: option.group, key: option.group }, option.options.map((groupedOption) => this.renderOption(groupedOption, optionIndex++)))) : (isOption(option) && this.renderOption(option, optionIndex++)))))));
|
|
419
421
|
}
|
|
420
422
|
static get is() { return "mg-input-select"; }
|
|
421
423
|
static get encapsulation() { return "shadow"; }
|
|
@@ -839,7 +841,7 @@ export class MgInputSelect {
|
|
|
839
841
|
"composed": true,
|
|
840
842
|
"docs": {
|
|
841
843
|
"tags": [],
|
|
842
|
-
"text": "
|
|
844
|
+
"text": "Emitted event when value change"
|
|
843
845
|
},
|
|
844
846
|
"complexType": {
|
|
845
847
|
"original": "HTMLMgInputCheckboxElement['value']",
|
|
@@ -859,7 +861,7 @@ export class MgInputSelect {
|
|
|
859
861
|
"composed": true,
|
|
860
862
|
"docs": {
|
|
861
863
|
"tags": [],
|
|
862
|
-
"text": "
|
|
864
|
+
"text": "Emitted event when checking validity"
|
|
863
865
|
},
|
|
864
866
|
"complexType": {
|
|
865
867
|
"original": "HTMLMgInputCheckboxElement['valid']",
|
|
@@ -2,14 +2,16 @@ import { h } from "@stencil/core";
|
|
|
2
2
|
import { ClassList, allItemsAreString, isValidString, toString } from "@mgdis/core-ui-helpers/dist/utils";
|
|
3
3
|
import { normalizeBooleanAttributes } from "@mgdis/core-ui-helpers/dist/stencil";
|
|
4
4
|
import { helpTextTypes, textTypes } from "./mg-input-text.conf";
|
|
5
|
-
import { widths, classReadonly, classDisabled, classDisplayCharacterLeft } from "../mg-input/mg-input.conf";
|
|
5
|
+
import { widths, classReadonly, classDisabled, classDisplayCharacterLeft, } from "../mg-input/mg-input.conf";
|
|
6
6
|
import { initLocales } from "../../../../locales";
|
|
7
7
|
/**
|
|
8
8
|
* Check if object is an option
|
|
9
9
|
* @param option - object to validate
|
|
10
10
|
* @returns true id object is an option
|
|
11
11
|
*/
|
|
12
|
-
const isOption = (option) => typeof option === 'object' &&
|
|
12
|
+
const isOption = (option) => typeof option === 'object' &&
|
|
13
|
+
typeof option.title === 'string' &&
|
|
14
|
+
option.value !== undefined;
|
|
13
15
|
/**
|
|
14
16
|
* Check if datalist options are well structured.
|
|
15
17
|
* @param options - Datalist options to check.
|
|
@@ -86,7 +88,8 @@ export class MgInputText {
|
|
|
86
88
|
*/
|
|
87
89
|
this.validatePattern = () => {
|
|
88
90
|
if ((this.pattern !== undefined || this.patternErrorMessage !== undefined) && // At least one is defined
|
|
89
|
-
(!isValidString(this.pattern) ||
|
|
91
|
+
(!isValidString(this.pattern) ||
|
|
92
|
+
(!helpTextTypes.includes(this.type) && !isValidString(this.patternErrorMessage))) // Both must be defined
|
|
90
93
|
) {
|
|
91
94
|
throw new Error(`<mg-input-text> props "pattern" and "patternErrorMessage" must be non-empty string and paired. Passed value: "pattern='${this.pattern}'" and "patternErrorMessage='${this.patternErrorMessage}'".`);
|
|
92
95
|
}
|
|
@@ -159,7 +162,7 @@ export class MgInputText {
|
|
|
159
162
|
this.slotContent = slotAppendInput[0].textContent;
|
|
160
163
|
}
|
|
161
164
|
}
|
|
162
|
-
else if (slotAppendInput.filter(slot => slot.nodeName === 'MG-BUTTON').length > 1) {
|
|
165
|
+
else if (slotAppendInput.filter((slot) => slot.nodeName === 'MG-BUTTON').length > 1) {
|
|
163
166
|
this.classCollection.add(this.classIsInputGroupAppend);
|
|
164
167
|
this.classCollection.add(this.classHasButtonsGroupAppend);
|
|
165
168
|
}
|
|
@@ -180,7 +183,7 @@ export class MgInputText {
|
|
|
180
183
|
handleValue(newValue) {
|
|
181
184
|
var _a, _b;
|
|
182
185
|
if ((_a = this.datalistoptions) === null || _a === void 0 ? void 0 : _a.every(isOption)) {
|
|
183
|
-
this.valueChange.emit(((_b = this.datalistoptions.find(option => option.title === newValue)) === null || _b === void 0 ? void 0 : _b.value) || newValue);
|
|
186
|
+
this.valueChange.emit(((_b = this.datalistoptions.find((option) => option.title === newValue)) === null || _b === void 0 ? void 0 : _b.value) || newValue);
|
|
184
187
|
}
|
|
185
188
|
else {
|
|
186
189
|
this.valueChange.emit(newValue);
|
|
@@ -228,7 +231,7 @@ export class MgInputText {
|
|
|
228
231
|
}
|
|
229
232
|
watchMgWidth(newValue) {
|
|
230
233
|
// reset width class
|
|
231
|
-
widths.forEach(width => {
|
|
234
|
+
widths.forEach((width) => {
|
|
232
235
|
this.classCollection.delete(`mg-c-input--width-${width}`);
|
|
233
236
|
});
|
|
234
237
|
// apply new width
|
|
@@ -268,7 +271,7 @@ export class MgInputText {
|
|
|
268
271
|
// - Async operations are completed
|
|
269
272
|
// - No timing issues with Stencil's render cycle
|
|
270
273
|
// - Keep everything in sync both inside and outside the component
|
|
271
|
-
return new Promise(resolve => {
|
|
274
|
+
return new Promise((resolve) => {
|
|
272
275
|
requestAnimationFrame(() => {
|
|
273
276
|
this.checkValidity();
|
|
274
277
|
this.setErrorMessage();
|
|
@@ -315,7 +318,7 @@ export class MgInputText {
|
|
|
315
318
|
// - Async operations are completed
|
|
316
319
|
// - No timing issues with Stencil's render cycle
|
|
317
320
|
// - Keep everything in sync both inside and outside the component
|
|
318
|
-
return new Promise(resolve => {
|
|
321
|
+
return new Promise((resolve) => {
|
|
319
322
|
requestAnimationFrame(() => {
|
|
320
323
|
// unlock validity check by reseting customErrorMessage
|
|
321
324
|
this.customErrorMessage = { lock: false };
|
|
@@ -377,15 +380,17 @@ export class MgInputText {
|
|
|
377
380
|
* @returns HTML Element
|
|
378
381
|
*/
|
|
379
382
|
render() {
|
|
380
|
-
return (h("mg-input", { key: '
|
|
383
|
+
return (h("mg-input", { key: '3454b5f94af7b47a2c94b1416f59f840552ef70a', label: this.label, identifier: this.identifier, class: this.classCollection.join(), ariaDescribedbyIDs: this.characterLeftId, labelOnTop: this.labelOnTop, labelHide: this.labelHide, required: this.required, tooltip: this.tooltip, tooltipPosition: this.readonly && this.value === undefined ? 'label' : this.tooltipPosition, helpText: this.helpText, errorMessage: this.errorMessage }, this.readonly
|
|
381
384
|
? this.value && this.renderReadonly()
|
|
382
385
|
: [
|
|
383
386
|
h("div", { key: "input", class: "mg-c-input__input-group-container", style: {
|
|
384
|
-
'--mg-c-character-left-message-length': (!this.characterLeftHide
|
|
387
|
+
'--mg-c-character-left-message-length': (!this.characterLeftHide
|
|
388
|
+
? this.maxlength.toString().length * 2 + 1
|
|
389
|
+
: 0).toString(),
|
|
385
390
|
} }, this.icon !== undefined && h("mg-icon", { icon: this.icon }), h("input", { type: this.type === 'emails' ? 'email' : this.type, multiple: this.type === 'emails', class: "mg-c-input__box mg-c-input__box--width", value: this.value, id: this.identifier, list: this.hasDatalist() ? this.datalistId : undefined, autocomplete: this.hasDatalist() ? 'off' : undefined, name: this.name, placeholder: this.placeholder, title: this.placeholder, maxlength: this.maxlength, disabled: this.disabled, required: this.required, "aria-invalid": (this.invalid === true).toString(), pattern: this.pattern, onInput: this.handleInput, onBlur: this.handleBlur, ref: (el) => {
|
|
386
391
|
if (el !== null)
|
|
387
392
|
this.input = el;
|
|
388
|
-
} }), this.hasDatalist() && (h("datalist", { id: this.datalistId }, this.datalistoptions.map(option => (h("option", { value: isOption(option) ? option.title : option, key: option }))))), !this.characterLeftHide && this.maxlength > 0 && (h("mg-character-left", { identifier: this.characterLeftId, characters: this.value, maxlength: this.maxlength }))),
|
|
393
|
+
} }), this.hasDatalist() && (h("datalist", { id: this.datalistId }, this.datalistoptions.map((option) => (h("option", { value: isOption(option) ? option.title : option, key: option }))))), !this.characterLeftHide && this.maxlength > 0 && (h("mg-character-left", { identifier: this.characterLeftId, characters: this.value, maxlength: this.maxlength }))),
|
|
389
394
|
h("slot", { key: "slot", name: "append-input" }),
|
|
390
395
|
]));
|
|
391
396
|
}
|
|
@@ -901,7 +906,7 @@ export class MgInputText {
|
|
|
901
906
|
"composed": true,
|
|
902
907
|
"docs": {
|
|
903
908
|
"tags": [],
|
|
904
|
-
"text": "
|
|
909
|
+
"text": "Emitted event when value change"
|
|
905
910
|
},
|
|
906
911
|
"complexType": {
|
|
907
912
|
"original": "HTMLMgInputTextElement['value']",
|
|
@@ -921,7 +926,7 @@ export class MgInputText {
|
|
|
921
926
|
"composed": true,
|
|
922
927
|
"docs": {
|
|
923
928
|
"tags": [],
|
|
924
|
-
"text": "
|
|
929
|
+
"text": "Emitted event when checking validity"
|
|
925
930
|
},
|
|
926
931
|
"complexType": {
|
|
927
932
|
"original": "HTMLMgInputTextElement['valid']",
|