@mgdis/mg-components 6.27.0 → 6.28.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/loader.cjs.js +1 -1
- package/dist/cjs/mg-action-more_36.cjs.entry.js +365 -77
- package/dist/cjs/mg-components.cjs.js +1 -1
- package/dist/cjs/mg-input-combobox.cjs.entry.js +36 -2
- package/dist/cjs/mg-input-file.cjs.entry.js +25 -2
- package/dist/cjs/mg-input-rich-text-editor.cjs.entry.js +717 -504
- package/dist/collection/assets/jodit/jodit.css +1 -1
- package/dist/collection/components/atoms/mg-button/mg-button.js +86 -13
- package/dist/collection/components/molecules/inputs/mg-input-checkbox/mg-input-checkbox.js +24 -1
- package/dist/collection/components/molecules/inputs/mg-input-combobox/mg-input-combobox.js +36 -2
- package/dist/collection/components/molecules/inputs/mg-input-date/mg-input-date.js +25 -9
- package/dist/collection/components/molecules/inputs/mg-input-file/mg-input-file.js +25 -2
- package/dist/collection/components/molecules/inputs/mg-input-numeric/mg-input-numeric.js +24 -6
- package/dist/collection/components/molecules/inputs/mg-input-password/mg-input-password.js +24 -5
- package/dist/collection/components/molecules/inputs/mg-input-radio/mg-input-radio.js +64 -16
- package/dist/collection/components/molecules/inputs/mg-input-select/mg-input-select.js +32 -10
- package/dist/collection/components/molecules/inputs/mg-input-text/mg-input-text.js +24 -5
- package/dist/collection/components/molecules/inputs/mg-input-textarea/mg-input-textarea.js +24 -6
- package/dist/collection/components/molecules/mg-form/mg-form.js +74 -8
- package/dist/components/mg-button2.js +1 -1
- package/dist/components/mg-form.js +1 -1
- 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 +262 -262
- 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-modal.js +1 -1
- package/dist/custom-elements.json +12 -2
- package/dist/esm/loader.js +1 -1
- package/dist/esm/mg-action-more_36.entry.js +366 -78
- package/dist/esm/mg-components.js +1 -1
- package/dist/esm/mg-input-combobox.entry.js +36 -2
- package/dist/esm/mg-input-file.entry.js +25 -2
- package/dist/esm/mg-input-rich-text-editor.entry.js +717 -504
- package/dist/mg-components/mg-components.esm.js +1 -1
- package/dist/mg-components/p-2198f145.entry.js +1 -0
- package/dist/mg-components/p-d4a4eb78.entry.js +1 -0
- package/dist/mg-components/{p-6f492676.entry.js → p-e8b5e8d8.entry.js} +261 -261
- package/dist/mg-components/p-fdcce8d5.entry.js +1 -0
- package/dist/types/components/atoms/mg-button/mg-button.d.ts +41 -2
- package/dist/types/components/molecules/inputs/mg-input/mg-input.conf.d.ts +1 -0
- package/dist/types/components/molecules/inputs/mg-input-checkbox/mg-input-checkbox.d.ts +9 -0
- package/dist/types/components/molecules/inputs/mg-input-combobox/mg-input-combobox.d.ts +10 -1
- package/dist/types/components/molecules/inputs/mg-input-date/mg-input-date.d.ts +9 -0
- package/dist/types/components/molecules/inputs/mg-input-file/mg-input-file.d.ts +9 -0
- package/dist/types/components/molecules/inputs/mg-input-numeric/mg-input-numeric.d.ts +9 -0
- package/dist/types/components/molecules/inputs/mg-input-password/mg-input-password.d.ts +9 -0
- package/dist/types/components/molecules/inputs/mg-input-radio/mg-input-radio.d.ts +29 -2
- package/dist/types/components/molecules/inputs/mg-input-select/mg-input-select.d.ts +10 -1
- package/dist/types/components/molecules/inputs/mg-input-text/mg-input-text.d.ts +9 -0
- package/dist/types/components/molecules/inputs/mg-input-textarea/mg-input-textarea.d.ts +9 -0
- package/dist/types/components/molecules/mg-form/mg-form.d.ts +18 -0
- package/dist/types/components.d.ts +10 -2
- package/ide/intellij/web-types.json +4 -4
- package/ide/vscode/html-custom-data.json +3 -3
- package/package.json +19 -19
- package/dist/mg-components/p-32a55ddb.entry.js +0 -1
- package/dist/mg-components/p-813d69c7.entry.js +0 -1
- package/dist/mg-components/p-a2445605.entry.js +0 -1
|
@@ -395,6 +395,88 @@ const MgButton = class {
|
|
|
395
395
|
(_b = this.element.querySelector('mg-icon')) === null || _b === void 0 ? void 0 : _b.setAttribute('size', this.size);
|
|
396
396
|
}
|
|
397
397
|
};
|
|
398
|
+
/**
|
|
399
|
+
* Submit a native form the way a native submit button does
|
|
400
|
+
* @param form - the form to submit
|
|
401
|
+
*/
|
|
402
|
+
this.dispatchSubmit = (form) => {
|
|
403
|
+
form.dispatchEvent(new SubmitEvent('submit', { bubbles: true, cancelable: true }));
|
|
404
|
+
};
|
|
405
|
+
/**
|
|
406
|
+
* Wrap a `mg-form` in the actions its public API offers, so nothing reaches into its shadow DOM
|
|
407
|
+
* @param mgForm - the owning mg-form
|
|
408
|
+
* @returns its submit and reset actions
|
|
409
|
+
*/
|
|
410
|
+
this.mgFormActions = (mgForm) => ({
|
|
411
|
+
submit: () => mgForm.requestSubmit(),
|
|
412
|
+
reset: () => mgForm.reset(),
|
|
413
|
+
});
|
|
414
|
+
/**
|
|
415
|
+
* Wrap a native form in the same actions
|
|
416
|
+
* @param form - the owning form
|
|
417
|
+
* @returns its submit and reset actions
|
|
418
|
+
*/
|
|
419
|
+
this.nativeFormActions = (form) => ({
|
|
420
|
+
submit: () => this.dispatchSubmit(form),
|
|
421
|
+
reset: () => form.reset(),
|
|
422
|
+
});
|
|
423
|
+
/**
|
|
424
|
+
* Resolve the form the `form` id points to. An id reference does not cross a shadow boundary, so
|
|
425
|
+
* it resolves in the tree the button belongs to — the document, or the shadow tree it sits in —
|
|
426
|
+
* the way a native form owner does. The ancestor wins when it is the one pointed at: two forms
|
|
427
|
+
* can share an identifier, and a tree-wide lookup would retain the first one.
|
|
428
|
+
* @returns the actions of the form holding that id, or null when none does
|
|
429
|
+
*/
|
|
430
|
+
this.resolveOwnerById = () => {
|
|
431
|
+
const ancestorMgForm = this.element.closest('mg-form');
|
|
432
|
+
if (ancestorMgForm !== null && ancestorMgForm.identifier === this.form)
|
|
433
|
+
return this.mgFormActions(ancestorMgForm);
|
|
434
|
+
const root = this.element.getRootNode();
|
|
435
|
+
const tree = root instanceof ShadowRoot ? root : this.element.ownerDocument;
|
|
436
|
+
const mgForm = Array.from(tree.querySelectorAll('mg-form')).find((element) => element.identifier === this.form);
|
|
437
|
+
if (mgForm !== undefined)
|
|
438
|
+
return this.mgFormActions(mgForm);
|
|
439
|
+
// Resolved by id, as a native form owner is, rather than through a selector an id could break
|
|
440
|
+
const nativeForm = tree.getElementById(this.form);
|
|
441
|
+
return nativeForm instanceof HTMLFormElement ? this.nativeFormActions(nativeForm) : null;
|
|
442
|
+
};
|
|
443
|
+
/**
|
|
444
|
+
* Resolve the form owning this button: an explicit `form` id overrides the ancestor form, and an
|
|
445
|
+
* id matching nothing logs then falls back on it, so a button never loses an association it had.
|
|
446
|
+
* @returns the owning form actions, or null when the button has no form owner
|
|
447
|
+
*/
|
|
448
|
+
this.resolveFormOwner = () => {
|
|
449
|
+
if (index$1.isValidString(this.form)) {
|
|
450
|
+
const ownerById = this.resolveOwnerById();
|
|
451
|
+
if (ownerById !== null)
|
|
452
|
+
return ownerById;
|
|
453
|
+
console.error(`<mg-button> prop "form" matches no form in the button tree. Passed value: ${index$1.toString(this.form)}.`);
|
|
454
|
+
}
|
|
455
|
+
const nativeAncestor = this.element.closest('form');
|
|
456
|
+
if (nativeAncestor !== null)
|
|
457
|
+
return this.nativeFormActions(nativeAncestor);
|
|
458
|
+
const mgAncestor = this.element.closest('mg-form');
|
|
459
|
+
return mgAncestor === null ? null : this.mgFormActions(mgAncestor);
|
|
460
|
+
};
|
|
461
|
+
/**
|
|
462
|
+
* Act on the owning form. The owner is resolved here rather than on load because a native form
|
|
463
|
+
* owner is re-resolved on every submission, never captured once: the button follows a `form`
|
|
464
|
+
* changed after render, and no longer races the target form hydration.
|
|
465
|
+
*/
|
|
466
|
+
this.handleFormClick = () => {
|
|
467
|
+
const isSubmit = ['submit', undefined].includes(this.type);
|
|
468
|
+
// A reset only fires from an explicit association: it has never reset a merely ancestor form
|
|
469
|
+
const isReset = this.type === 'reset' && index$1.isValidString(this.form);
|
|
470
|
+
if (!isSubmit && !isReset)
|
|
471
|
+
return;
|
|
472
|
+
const owner = this.resolveFormOwner();
|
|
473
|
+
if (owner === null)
|
|
474
|
+
return;
|
|
475
|
+
if (isSubmit)
|
|
476
|
+
owner.submit();
|
|
477
|
+
else
|
|
478
|
+
owner.reset();
|
|
479
|
+
};
|
|
398
480
|
}
|
|
399
481
|
validateVariant(newValue, oldValue) {
|
|
400
482
|
// validate new value
|
|
@@ -493,16 +575,7 @@ const MgButton = class {
|
|
|
493
575
|
* Add listners
|
|
494
576
|
*/
|
|
495
577
|
componentDidLoad() {
|
|
496
|
-
|
|
497
|
-
var _a;
|
|
498
|
-
const closestForm = this.element.closest('form') || ((_a = this.element.closest('mg-form')) === null || _a === void 0 ? void 0 : _a.shadowRoot.querySelector('form'));
|
|
499
|
-
// submit buttons should trigger form submition;
|
|
500
|
-
if (closestForm && ['submit', undefined].includes(this.type)) {
|
|
501
|
-
this.element.addEventListener('click', () => {
|
|
502
|
-
closestForm.dispatchEvent(new SubmitEvent('submit', { bubbles: true, cancelable: true }));
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
});
|
|
578
|
+
this.element.addEventListener('click', this.handleFormClick);
|
|
506
579
|
}
|
|
507
580
|
/**
|
|
508
581
|
* Render component
|
|
@@ -510,7 +583,7 @@ const MgButton = class {
|
|
|
510
583
|
*/
|
|
511
584
|
render() {
|
|
512
585
|
var _a;
|
|
513
|
-
return (index.h(index.Host, { key: '
|
|
586
|
+
return (index.h(index.Host, { key: '815bedd3729c652a5faf06c3d451cbc67123ab63', role: "button", tabIndex: this.element.getAttribute('tabindex') || 0, type: this.type, form: this.form, "full-width": this.fullWidth, "aria-label": this.label, "aria-disabled": (_a = this.disabled) === null || _a === void 0 ? void 0 : _a.toString(), onClick: this.handleClick, onKeyup: this.handleKeyup, onKeydown: this.handleKeydown }, index.h("div", { key: '2a1c20c677294870958f01c4042e8f530bf0f89d', class: this.classCollection.join() }, this.loading && index.h("mg-icon", { key: 'db3960249deed458f86bcba16b66bbeb9aac69c1', icon: "loader", spin: true }), index.h("div", { key: '76a3af6c9a105b91b7f6055cc19bbb6f315be1a5', class: "mg-c-button__content" }, index.h("slot", { key: 'ca87921b6c58fbd055a83ea28f5ce58a618f16fe' })))));
|
|
514
587
|
}
|
|
515
588
|
get element() { return index.getElement(this); }
|
|
516
589
|
static get watchers() { return {
|
|
@@ -998,6 +1071,38 @@ const MgForm = class {
|
|
|
998
1071
|
this.formReset.emit(true);
|
|
999
1072
|
}
|
|
1000
1073
|
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Request the form submission: emit `form-submit`, whatever the inputs validity.
|
|
1076
|
+
* This is what a `mg-button` associated with this form goes through, so that reaching the form
|
|
1077
|
+
* needs no access to its shadow DOM. Unlike the native `requestSubmit()`, it runs no constraint
|
|
1078
|
+
* validation: validity is the consumer's call here, as it is on submission from a nested button.
|
|
1079
|
+
* Read `invalid`, or call `displayError()` / `focusFirstInvalidInput()`.
|
|
1080
|
+
* Unlike `reset()`, a readonly form still submits: readonly fields do not block a native
|
|
1081
|
+
* submission either, and a nested button has always submitted such a form.
|
|
1082
|
+
*/
|
|
1083
|
+
async requestSubmit() {
|
|
1084
|
+
this.formSubmit.emit();
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* **Experimental.** The signature may still change in a minor release.
|
|
1088
|
+
*
|
|
1089
|
+
* Display errors, then focus and scroll to the first invalid input. Focusing is what
|
|
1090
|
+
* carries the information for assistive technologies, a scroll announces nothing.
|
|
1091
|
+
* Read the `invalid` property to know whether the form had an invalid input.
|
|
1092
|
+
*/
|
|
1093
|
+
async focusFirstInvalidInput() {
|
|
1094
|
+
if (!this.readonly) {
|
|
1095
|
+
await this.displayError();
|
|
1096
|
+
// Inputs defer their displayError() to a requestAnimationFrame
|
|
1097
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
1098
|
+
// Read at call time: a MutationObserver rebuilds the list on content change
|
|
1099
|
+
const firstInvalidInput = this.mgInputs.find((input) => input.invalid);
|
|
1100
|
+
if (firstInvalidInput !== undefined) {
|
|
1101
|
+
await firstInvalidInput.setFocus();
|
|
1102
|
+
firstInvalidInput.scrollIntoView();
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1001
1106
|
/*************
|
|
1002
1107
|
* Lifecycle *
|
|
1003
1108
|
*************/
|
|
@@ -1016,13 +1121,13 @@ const MgForm = class {
|
|
|
1016
1121
|
this.hasActions = this.element.querySelector('[slot="actions"]') !== null;
|
|
1017
1122
|
// Get slotted mgButtons
|
|
1018
1123
|
this.mgButtons = Array.from(this.element.querySelectorAll('mg-button'));
|
|
1019
|
-
//
|
|
1124
|
+
// Announce the association: a slotted button then drives this form through its public API and
|
|
1125
|
+
// handles its own submit and reset, which is why none is wired here. An id it already carries
|
|
1126
|
+
// wins, read as property and attribute since frameworks pass the prop as one or the other.
|
|
1020
1127
|
this.mgButtons.forEach((mgButton) => {
|
|
1021
|
-
|
|
1022
|
-
if (mgButton.
|
|
1023
|
-
mgButton.
|
|
1024
|
-
this.reset();
|
|
1025
|
-
});
|
|
1128
|
+
var _a;
|
|
1129
|
+
if (!index$1.isValidString((_a = mgButton.form) !== null && _a !== void 0 ? _a : mgButton.getAttribute('form'))) {
|
|
1130
|
+
mgButton.setAttribute('form', this.identifier);
|
|
1026
1131
|
}
|
|
1027
1132
|
});
|
|
1028
1133
|
// Set mgInputs
|
|
@@ -1057,7 +1162,7 @@ const MgForm = class {
|
|
|
1057
1162
|
* @returns HTML Element
|
|
1058
1163
|
*/
|
|
1059
1164
|
render() {
|
|
1060
|
-
return (index.h("form", { key: '
|
|
1165
|
+
return (index.h("form", { key: '0c23474cba5ae38a70162129641128cdd17224cb', class: this.classCollection.join(), id: this.identifier, name: this.name, onSubmit: this.handleFormSubmit, role: this.ariaRole }, this.requiredMessageText && index.h("p", { key: '8938192d2b2f4d1278f6e5037ed7f0f839c44861', innerHTML: this.requiredMessageText }), index.h("slot", { key: 'aefbcb13adbe2632b958c55c2c2c0174d5aaf471' }), !this.readonly && !this.disabled && this.hasActions && (index.h("div", { key: '30675225f5a910945f5b31fb044d3501c323acf9', class: "mg-c-form__actions" }, index.h("slot", { key: '6f5b871264d0237fc1eccfac5c454e61135b81c4', name: "actions" })))));
|
|
1061
1166
|
}
|
|
1062
1167
|
get element() { return index.getElement(this); }
|
|
1063
1168
|
static get watchers() { return {
|
|
@@ -1936,6 +2041,8 @@ const MgInputCheckbox = class {
|
|
|
1936
2041
|
this.inputValid = index.createEvent(this, "input-valid", 7);
|
|
1937
2042
|
// hasDisplayedError (triggered by blur event)
|
|
1938
2043
|
this.hasDisplayedError = false;
|
|
2044
|
+
// raised when `value` changed, so componentDidUpdate revalidates once the DOM is in sync
|
|
2045
|
+
this.validityCheckPending = false;
|
|
1939
2046
|
this.customErrorMessage = { lock: false };
|
|
1940
2047
|
this.mode = 'custom';
|
|
1941
2048
|
// style
|
|
@@ -2218,6 +2325,7 @@ const MgInputCheckbox = class {
|
|
|
2218
2325
|
this.renderMgInputCheckboxList = () => (index.h(MgInputCheckboxList, { checkboxes: this.checkboxItems, id: this.checkboxesId, disabled: this.disabled, name: this.name, invalid: this.invalid }));
|
|
2219
2326
|
}
|
|
2220
2327
|
validateValue(newValue) {
|
|
2328
|
+
this.validityCheckPending = true;
|
|
2221
2329
|
if (isCheckboxItems(newValue)) {
|
|
2222
2330
|
this.checkboxItems = newValue.map((item, index) => (Object.assign(Object.assign({}, item), { _id: `${this.identifier}_${index}`, _handleInput: this.handleInput.bind(this), _handleBlur: this.handleBlur.bind(this), _handleKeydown: this.handleKeydown.bind(this) })));
|
|
2223
2331
|
this.valueChange.emit(newValue);
|
|
@@ -2350,6 +2458,8 @@ const MgInputCheckbox = class {
|
|
|
2350
2458
|
lock: valid ? false : errorMessageLock,
|
|
2351
2459
|
message: valid ? undefined : errorMessage,
|
|
2352
2460
|
};
|
|
2461
|
+
// setError() states the validity explicitly, so drop any pending recomputation
|
|
2462
|
+
this.validityCheckPending = false;
|
|
2353
2463
|
this.setValidity(valid);
|
|
2354
2464
|
this.setErrorMessage(true);
|
|
2355
2465
|
this.hasDisplayedError = this.invalid;
|
|
@@ -2432,8 +2542,26 @@ const MgInputCheckbox = class {
|
|
|
2432
2542
|
// https://stenciljs.com/docs/component-lifecycle#componentwillload
|
|
2433
2543
|
return setTimeout(() => {
|
|
2434
2544
|
this.checkValidity();
|
|
2545
|
+
// the initial check covers the initial value: nothing is pending yet
|
|
2546
|
+
this.validityCheckPending = false;
|
|
2435
2547
|
}, 0);
|
|
2436
2548
|
}
|
|
2549
|
+
/**
|
|
2550
|
+
* Recompute validity once the DOM is in sync with `value`.
|
|
2551
|
+
* `@Watch('value')` fires before Stencil re-renders, so the rendered control still holds the
|
|
2552
|
+
* previous value at that point (visible with a programmatic value change, e.g. a `v-model`
|
|
2553
|
+
* default value). The watcher therefore only raises a flag, and the check runs here, after the
|
|
2554
|
+
* render. Renders unrelated to `value` leave the flag down and recompute nothing.
|
|
2555
|
+
*/
|
|
2556
|
+
componentDidUpdate() {
|
|
2557
|
+
if (this.validityCheckPending && this.checkboxItems.length > 0) {
|
|
2558
|
+
this.validityCheckPending = false;
|
|
2559
|
+
this.checkValidity();
|
|
2560
|
+
if (this.hasDisplayedError) {
|
|
2561
|
+
this.setErrorMessage();
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2437
2565
|
/**
|
|
2438
2566
|
* add listeners and DOM attributed
|
|
2439
2567
|
*/
|
|
@@ -2518,7 +2646,7 @@ const MgInputCheckbox = class {
|
|
|
2518
2646
|
else {
|
|
2519
2647
|
inputContent = this.renderCheckboxMulti();
|
|
2520
2648
|
}
|
|
2521
|
-
return (index.h("mg-input", { key: '
|
|
2649
|
+
return (index.h("mg-input", { key: 'e873b2c1a5e96f5f424f21e3531c6c63c1d9ff39', label: this.label, identifier: this.identifier, class: this.classCollection.join(), labelOnTop: this.labelOnTop, labelHide: this.labelHide, required: !this.readonly ? this.required : undefined, tooltip: this.tooltip, tooltipPosition: this.readonly && readonlyValue.length === 0 ? 'label' : this.tooltipPosition, helpText: !this.readonly ? this.helpText : undefined, errorMessage: !this.readonly ? this.errorMessage : undefined }, inputContent));
|
|
2522
2650
|
}
|
|
2523
2651
|
get element() { return index.getElement(this); }
|
|
2524
2652
|
static get watchers() { return {
|
|
@@ -2571,6 +2699,8 @@ const MgInputDate = class {
|
|
|
2571
2699
|
this.inputValid = index.createEvent(this, "input-valid", 7);
|
|
2572
2700
|
// hasDisplayedError (triggered by blur event)
|
|
2573
2701
|
this.hasDisplayedError = false;
|
|
2702
|
+
// raised when `value` changed, so componentDidUpdate revalidates once the DOM is in sync
|
|
2703
|
+
this.validityCheckPending = false;
|
|
2574
2704
|
this.customErrorMessage = { lock: false };
|
|
2575
2705
|
/**
|
|
2576
2706
|
* Input name
|
|
@@ -2642,10 +2772,6 @@ const MgInputDate = class {
|
|
|
2642
2772
|
* Handle input event
|
|
2643
2773
|
*/
|
|
2644
2774
|
this.handleInput = () => {
|
|
2645
|
-
this.checkValidity();
|
|
2646
|
-
if (this.hasDisplayedError) {
|
|
2647
|
-
this.setErrorMessage();
|
|
2648
|
-
}
|
|
2649
2775
|
this.value = this.input.value;
|
|
2650
2776
|
};
|
|
2651
2777
|
/**
|
|
@@ -2667,11 +2793,8 @@ const MgInputDate = class {
|
|
|
2667
2793
|
// when we reset the field we need to test a blank value.
|
|
2668
2794
|
if (['Delete', 'Backspace'].includes(event.key)) {
|
|
2669
2795
|
event.preventDefault();
|
|
2796
|
+
// validity is recomputed in componentDidUpdate, once the input actually holds the blank value
|
|
2670
2797
|
this.value = null;
|
|
2671
|
-
this.checkValidity();
|
|
2672
|
-
if (this.hasDisplayedError) {
|
|
2673
|
-
this.setErrorMessage();
|
|
2674
|
-
}
|
|
2675
2798
|
}
|
|
2676
2799
|
};
|
|
2677
2800
|
/**
|
|
@@ -2758,6 +2881,7 @@ const MgInputDate = class {
|
|
|
2758
2881
|
};
|
|
2759
2882
|
}
|
|
2760
2883
|
validateValue(newValue) {
|
|
2884
|
+
this.validityCheckPending = true;
|
|
2761
2885
|
// When the input is not fully completed or has been cleared, the value becomes an empty string.
|
|
2762
2886
|
if (['', undefined].includes(newValue)) {
|
|
2763
2887
|
// need to force value update to `null` to prevent extra render
|
|
@@ -2850,6 +2974,8 @@ const MgInputDate = class {
|
|
|
2850
2974
|
lock: valid ? false : errorMessageLock,
|
|
2851
2975
|
message: valid ? undefined : errorMessage,
|
|
2852
2976
|
};
|
|
2977
|
+
// setError() states the validity explicitly, so drop any pending recomputation
|
|
2978
|
+
this.validityCheckPending = false;
|
|
2853
2979
|
this.setValidity(valid);
|
|
2854
2980
|
this.setErrorMessage(true);
|
|
2855
2981
|
this.hasDisplayedError = this.invalid;
|
|
@@ -2920,14 +3046,32 @@ const MgInputDate = class {
|
|
|
2920
3046
|
// https://stenciljs.com/docs/component-lifecycle#componentwillload
|
|
2921
3047
|
return setTimeout(() => {
|
|
2922
3048
|
this.checkValidity();
|
|
3049
|
+
// the initial check covers the initial value: nothing is pending yet
|
|
3050
|
+
this.validityCheckPending = false;
|
|
2923
3051
|
}, 0);
|
|
2924
3052
|
}
|
|
3053
|
+
/**
|
|
3054
|
+
* Recompute validity once the DOM is in sync with `value`.
|
|
3055
|
+
* `@Watch('value')` fires before Stencil re-renders, so the rendered control still holds the
|
|
3056
|
+
* previous value at that point (visible with a programmatic value change, e.g. a `v-model`
|
|
3057
|
+
* default value). The watcher therefore only raises a flag, and the check runs here, after the
|
|
3058
|
+
* render. Renders unrelated to `value` leave the flag down and recompute nothing.
|
|
3059
|
+
*/
|
|
3060
|
+
componentDidUpdate() {
|
|
3061
|
+
if (this.validityCheckPending && this.input !== undefined) {
|
|
3062
|
+
this.validityCheckPending = false;
|
|
3063
|
+
this.checkValidity();
|
|
3064
|
+
if (this.hasDisplayedError) {
|
|
3065
|
+
this.setErrorMessage();
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
2925
3069
|
/**
|
|
2926
3070
|
* Render
|
|
2927
3071
|
* @returns HTML Element
|
|
2928
3072
|
*/
|
|
2929
3073
|
render() {
|
|
2930
|
-
return (index.h("mg-input", { key: '
|
|
3074
|
+
return (index.h("mg-input", { key: '3d3f6910dde9c32bbf3d0c853e0c778380ed40fc', 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 && this.value === null ? 'label' : this.tooltipPosition, helpText: this.formatHelpText(this.helpText), errorMessage: this.errorMessage }, this.readonly ? (this.value && index.h("b", { class: "mg-c-input__readonly-value" }, index$2.localeDate(this.value, this.locale))) : (index.h("input", { type: "date", class: "mg-c-input__box", min: this.min, max: this.max, value: this.value, id: this.identifier, name: this.name, disabled: this.disabled, required: this.required, "aria-invalid": (this.invalid === true).toString(), onInput: this.handleInput, onBlur: this.handleBlur, onKeyDown: this.handleKeyDown, ref: (el) => {
|
|
2931
3075
|
if (el !== null)
|
|
2932
3076
|
this.input = el;
|
|
2933
3077
|
} }))));
|
|
@@ -2979,6 +3123,8 @@ const MgInputNumeric = class {
|
|
|
2979
3123
|
this.inputValid = index.createEvent(this, "input-valid", 7);
|
|
2980
3124
|
// hasDisplayedError (triggered by blur event)
|
|
2981
3125
|
this.hasDisplayedError = false;
|
|
3126
|
+
// raised when `value` changed, so componentDidUpdate revalidates once the DOM is in sync
|
|
3127
|
+
this.validityCheckPending = false;
|
|
2982
3128
|
this.customErrorMessage = { lock: false };
|
|
2983
3129
|
/**
|
|
2984
3130
|
* Input name
|
|
@@ -3045,11 +3191,6 @@ const MgInputNumeric = class {
|
|
|
3045
3191
|
*/
|
|
3046
3192
|
this.handleInput = () => {
|
|
3047
3193
|
this.value = this.input.value;
|
|
3048
|
-
// Check validity
|
|
3049
|
-
this.checkValidity();
|
|
3050
|
-
if (this.hasDisplayedError) {
|
|
3051
|
-
this.setErrorMessage();
|
|
3052
|
-
}
|
|
3053
3194
|
};
|
|
3054
3195
|
/**
|
|
3055
3196
|
* Handle focus event
|
|
@@ -3199,6 +3340,7 @@ const MgInputNumeric = class {
|
|
|
3199
3340
|
}
|
|
3200
3341
|
validateValue(newValue) {
|
|
3201
3342
|
var _a;
|
|
3343
|
+
this.validityCheckPending = true;
|
|
3202
3344
|
// has input value is always render as string we get a stringified value or a '' for nullish value, so we test string type
|
|
3203
3345
|
if (typeof newValue === 'string') {
|
|
3204
3346
|
// Check if integer value starts with '0' (leading zero)
|
|
@@ -3319,6 +3461,8 @@ const MgInputNumeric = class {
|
|
|
3319
3461
|
lock: valid ? false : errorMessageLock,
|
|
3320
3462
|
message: valid ? undefined : errorMessage,
|
|
3321
3463
|
};
|
|
3464
|
+
// setError() states the validity explicitly, so drop any pending recomputation
|
|
3465
|
+
this.validityCheckPending = false;
|
|
3322
3466
|
this.setValidity(valid);
|
|
3323
3467
|
this.setErrorMessage(true);
|
|
3324
3468
|
this.hasDisplayedError = this.invalid;
|
|
@@ -3431,14 +3575,32 @@ const MgInputNumeric = class {
|
|
|
3431
3575
|
// https://stenciljs.com/docs/component-lifecycle#componentwillload
|
|
3432
3576
|
return setTimeout(() => {
|
|
3433
3577
|
this.checkValidity();
|
|
3578
|
+
// the initial check covers the initial value: nothing is pending yet
|
|
3579
|
+
this.validityCheckPending = false;
|
|
3434
3580
|
}, 0);
|
|
3435
3581
|
}
|
|
3582
|
+
/**
|
|
3583
|
+
* Recompute validity once the DOM is in sync with `value`.
|
|
3584
|
+
* `@Watch('value')` fires before Stencil re-renders, so the rendered control still holds the
|
|
3585
|
+
* previous value at that point (visible with a programmatic value change, e.g. a `v-model`
|
|
3586
|
+
* default value). The watcher therefore only raises a flag, and the check runs here, after the
|
|
3587
|
+
* render. Renders unrelated to `value` leave the flag down and recompute nothing.
|
|
3588
|
+
*/
|
|
3589
|
+
componentDidUpdate() {
|
|
3590
|
+
if (this.validityCheckPending && this.input !== undefined) {
|
|
3591
|
+
this.validityCheckPending = false;
|
|
3592
|
+
this.checkValidity();
|
|
3593
|
+
if (this.hasDisplayedError) {
|
|
3594
|
+
this.setErrorMessage();
|
|
3595
|
+
}
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3436
3598
|
/**
|
|
3437
3599
|
* Render
|
|
3438
3600
|
* @returns HTML Element
|
|
3439
3601
|
*/
|
|
3440
3602
|
render() {
|
|
3441
|
-
return (index.h("mg-input", { key: '
|
|
3603
|
+
return (index.h("mg-input", { key: '8a9a2c269754aa1259e79dd5e68cc0ed6b578fd1', 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 && this.value === undefined ? 'label' : this.tooltipPosition, helpText: this.formatHelpText(this.helpText), errorMessage: this.errorMessage }, this.readonly
|
|
3442
3604
|
? this.readonlyValue && this.renderReadonly()
|
|
3443
3605
|
: [
|
|
3444
3606
|
index.h("input", { key: "input", type: "text", class: "mg-c-input__box mg-c-input__box--width", value: this.displayValue(), id: this.identifier, name: this.name, placeholder: this.placeholder, title: this.placeholder, disabled: this.disabled, required: this.required, autocomplete: "off", "aria-invalid": (this.invalid === true).toString(), onInput: this.handleInput, onFocus: this.handleFocus, onBlur: this.handleBlur, ref: (el) => {
|
|
@@ -3501,6 +3663,8 @@ const MgInputPassword = class {
|
|
|
3501
3663
|
// hasDisplayedError (triggered by blur event)
|
|
3502
3664
|
this.hasDisplayedError = false;
|
|
3503
3665
|
this.customErrorMessage = { lock: false };
|
|
3666
|
+
// raised when `value` changed, so componentDidUpdate revalidates once the DOM is in sync
|
|
3667
|
+
this.validityCheckPending = false;
|
|
3504
3668
|
/**
|
|
3505
3669
|
* Input name
|
|
3506
3670
|
* If not set the value equals the identifier
|
|
@@ -3546,10 +3710,6 @@ const MgInputPassword = class {
|
|
|
3546
3710
|
* Handle input event
|
|
3547
3711
|
*/
|
|
3548
3712
|
this.handleInput = () => {
|
|
3549
|
-
this.checkValidity();
|
|
3550
|
-
if (this.hasDisplayedError) {
|
|
3551
|
-
this.setErrorMessage();
|
|
3552
|
-
}
|
|
3553
3713
|
this.value = this.input.value;
|
|
3554
3714
|
};
|
|
3555
3715
|
/**
|
|
@@ -3594,6 +3754,7 @@ const MgInputPassword = class {
|
|
|
3594
3754
|
};
|
|
3595
3755
|
}
|
|
3596
3756
|
handleValue(newValue) {
|
|
3757
|
+
this.validityCheckPending = true;
|
|
3597
3758
|
this.valueChange.emit(newValue);
|
|
3598
3759
|
}
|
|
3599
3760
|
watchReadonly(newValue) {
|
|
@@ -3674,6 +3835,8 @@ const MgInputPassword = class {
|
|
|
3674
3835
|
lock: valid ? false : errorMessageLock,
|
|
3675
3836
|
message: valid ? undefined : errorMessage,
|
|
3676
3837
|
};
|
|
3838
|
+
// setError() states the validity explicitly, so drop any pending recomputation
|
|
3839
|
+
this.validityCheckPending = false;
|
|
3677
3840
|
this.setValidity(valid);
|
|
3678
3841
|
this.setErrorMessage(true);
|
|
3679
3842
|
this.hasDisplayedError = this.invalid;
|
|
@@ -3736,15 +3899,33 @@ const MgInputPassword = class {
|
|
|
3736
3899
|
// https://stenciljs.com/docs/component-lifecycle#componentwillload
|
|
3737
3900
|
return setTimeout(() => {
|
|
3738
3901
|
this.checkValidity();
|
|
3902
|
+
// the initial check covers the initial value: nothing is pending yet
|
|
3903
|
+
this.validityCheckPending = false;
|
|
3739
3904
|
}, 0);
|
|
3740
3905
|
}
|
|
3906
|
+
/**
|
|
3907
|
+
* Recompute validity once the DOM is in sync with `value`.
|
|
3908
|
+
* `@Watch('value')` fires before Stencil re-renders, so the rendered control still holds the
|
|
3909
|
+
* previous value at that point (visible with a programmatic value change, e.g. a `v-model`
|
|
3910
|
+
* default value). The watcher therefore only raises a flag, and the check runs here, after the
|
|
3911
|
+
* render. Renders unrelated to `value` leave the flag down and recompute nothing.
|
|
3912
|
+
*/
|
|
3913
|
+
componentDidUpdate() {
|
|
3914
|
+
if (this.validityCheckPending && this.input !== undefined) {
|
|
3915
|
+
this.validityCheckPending = false;
|
|
3916
|
+
this.checkValidity();
|
|
3917
|
+
if (this.hasDisplayedError) {
|
|
3918
|
+
this.setErrorMessage();
|
|
3919
|
+
}
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3741
3922
|
/**
|
|
3742
3923
|
* Render
|
|
3743
3924
|
* @returns HTML Element
|
|
3744
3925
|
*/
|
|
3745
3926
|
render() {
|
|
3746
3927
|
const displayPasswordIcon = this.displayPassword ? 'eye-slash' : 'eye';
|
|
3747
|
-
return (index.h("mg-input", { key: '
|
|
3928
|
+
return (index.h("mg-input", { key: '2d9498c380536dc32177d1ac16a513ee43944a72', 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 && this.value === undefined ? 'label' : this.tooltipPosition, helpText: this.helpText, errorMessage: this.errorMessage }, this.readonly ? (this.value !== undefined && index.h("b", { class: "mg-c-input__readonly-value" }, '•'.repeat(this.value.length))) : (index.h("span", { class: "mg-c-input__input-group" }, index.h("input", { type: this.displayPassword ? 'text' : 'password', class: "mg-c-input__box mg-c-input__box--width", value: this.value, id: this.identifier, name: this.name, placeholder: this.placeholder, title: this.placeholder, disabled: this.disabled, required: this.required, maxlength: this.maxlength, "aria-invalid": (this.invalid === true).toString(), onInput: this.handleInput, onBlur: this.handleBlur, ref: (el) => {
|
|
3748
3929
|
if (el !== null)
|
|
3749
3930
|
this.input = el;
|
|
3750
3931
|
} }), index.h("mg-button", { label: this.messages.input.password[this.displayPassword ? 'hide' : 'display'], disabled: this.disabled, variant: "flat", class: "mg-c-input__append-button", "is-icon": true, onClick: this.toggleDisplayPassword, "aria-controls": this.identifier }, index.h("mg-icon", { class: "mg-c-input__input-icon", icon: displayPasswordIcon }))))));
|
|
@@ -3792,12 +3973,12 @@ const MgInputRadio = class {
|
|
|
3792
3973
|
/************
|
|
3793
3974
|
* Internal *
|
|
3794
3975
|
************/
|
|
3795
|
-
// HTML selector
|
|
3796
|
-
this.inputs = [];
|
|
3797
3976
|
// classes
|
|
3798
3977
|
this.classVerticalList = 'mg-c-input--vertical-list';
|
|
3799
3978
|
// hasDisplayedError (triggered by blur event)
|
|
3800
3979
|
this.hasDisplayedError = false;
|
|
3980
|
+
// raised when `value` or `items` changed, so componentDidUpdate revalidates once the DOM is in sync
|
|
3981
|
+
this.validityCheckPending = false;
|
|
3801
3982
|
this.customErrorMessage = { lock: false };
|
|
3802
3983
|
/**
|
|
3803
3984
|
* Input name
|
|
@@ -3841,7 +4022,6 @@ const MgInputRadio = class {
|
|
|
3841
4022
|
* @param event - input event
|
|
3842
4023
|
*/
|
|
3843
4024
|
this.handleInput = (event) => {
|
|
3844
|
-
this.checkValidity();
|
|
3845
4025
|
this.value = this.options[event.target.value].value;
|
|
3846
4026
|
};
|
|
3847
4027
|
/**
|
|
@@ -3854,11 +4034,23 @@ const MgInputRadio = class {
|
|
|
3854
4034
|
// reset guard
|
|
3855
4035
|
this.handlerInProgress = undefined;
|
|
3856
4036
|
};
|
|
4037
|
+
/**
|
|
4038
|
+
* Check if the required constraint is fulfilled
|
|
4039
|
+
* The native group validity cannot answer it: a browser keeps the checked member a group had, even
|
|
4040
|
+
* once that input is removed from the DOM. Options that cannot be selected are ignored.
|
|
4041
|
+
* @returns required constraint is fulfilled
|
|
4042
|
+
*/
|
|
4043
|
+
this.validateRequired = () => {
|
|
4044
|
+
const selectableOptions = this.options.filter((option) => !option.disabled);
|
|
4045
|
+
return (!this.required ||
|
|
4046
|
+
selectableOptions.length < 1 ||
|
|
4047
|
+
selectableOptions.some((option) => this.isSelectedValue(option.value)));
|
|
4048
|
+
};
|
|
3857
4049
|
/**
|
|
3858
4050
|
* Check if input is valid
|
|
3859
4051
|
*/
|
|
3860
4052
|
this.checkValidity = () => {
|
|
3861
|
-
this.setValidity(this.readonly || this.disabled || this.getInvalidElement() === undefined);
|
|
4053
|
+
this.setValidity(this.readonly || this.disabled || (this.getInvalidElement() === undefined && this.validateRequired()));
|
|
3862
4054
|
};
|
|
3863
4055
|
/**
|
|
3864
4056
|
* Set input error message
|
|
@@ -3874,7 +4066,7 @@ const MgInputRadio = class {
|
|
|
3874
4066
|
this.errorMessage = this.customErrorMessage.message;
|
|
3875
4067
|
}
|
|
3876
4068
|
// required
|
|
3877
|
-
else if (invalidElement.validity.valueMissing) {
|
|
4069
|
+
else if (invalidElement === undefined || invalidElement.validity.valueMissing) {
|
|
3878
4070
|
this.errorMessage = this.messages.errors.required;
|
|
3879
4071
|
}
|
|
3880
4072
|
}
|
|
@@ -3883,11 +4075,24 @@ const MgInputRadio = class {
|
|
|
3883
4075
|
* get invalid element
|
|
3884
4076
|
* @returns element
|
|
3885
4077
|
*/
|
|
3886
|
-
this.getInvalidElement = () => this.
|
|
4078
|
+
this.getInvalidElement = () => this.getInputs().find((input) => !input.disabled && !input.readOnly && !input.checkValidity());
|
|
4079
|
+
/**
|
|
4080
|
+
* Get the rendered radio inputs
|
|
4081
|
+
* Read from the DOM: references kept from a render would outlive the inputs they point to.
|
|
4082
|
+
* @returns rendered radio inputs
|
|
4083
|
+
*/
|
|
4084
|
+
this.getInputs = () => Array.from(this.element.shadowRoot.querySelectorAll('input[type="radio"]'));
|
|
4085
|
+
/**
|
|
4086
|
+
* Check if a value is the selected one
|
|
4087
|
+
* @param optionValue - option value to compare to the component value
|
|
4088
|
+
* @returns option value is the selected one
|
|
4089
|
+
*/
|
|
4090
|
+
this.isSelectedValue = (optionValue) => JSON.stringify(this.value) === JSON.stringify(optionValue);
|
|
3887
4091
|
}
|
|
3888
4092
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3889
4093
|
watchValue(newValue) {
|
|
3890
4094
|
var _a;
|
|
4095
|
+
this.validityCheckPending = true;
|
|
3891
4096
|
if (index$1.allItemsAreString(this.items) && typeof newValue === 'string') {
|
|
3892
4097
|
this.readonlyValue = newValue;
|
|
3893
4098
|
}
|
|
@@ -3899,7 +4104,7 @@ const MgInputRadio = class {
|
|
|
3899
4104
|
}
|
|
3900
4105
|
this.valueChange.emit(newValue);
|
|
3901
4106
|
}
|
|
3902
|
-
validateItems(newValue) {
|
|
4107
|
+
validateItems(newValue, oldValue) {
|
|
3903
4108
|
// Validate if items have required min length
|
|
3904
4109
|
if (typeof newValue === 'object' && newValue.length < 2) {
|
|
3905
4110
|
throw new Error(`<mg-input-radio> prop "items" require at least 2 items. Passed value: ${index$1.toString(newValue)}.`);
|
|
@@ -3915,6 +4120,14 @@ const MgInputRadio = class {
|
|
|
3915
4120
|
else {
|
|
3916
4121
|
throw new Error(`<mg-input-radio> prop "items" is required and all items must be the same type, string or RadioOption. Passed value: ${index$1.toString(newValue)}.`);
|
|
3917
4122
|
}
|
|
4123
|
+
// `oldValue` is undefined on init
|
|
4124
|
+
if (oldValue !== undefined) {
|
|
4125
|
+
// the options cannot display a value they no longer offer, drop it
|
|
4126
|
+
if (this.value !== undefined && !this.options.some((option) => this.isSelectedValue(option.value))) {
|
|
4127
|
+
this.value = undefined;
|
|
4128
|
+
}
|
|
4129
|
+
this.validityCheckPending = true;
|
|
4130
|
+
}
|
|
3918
4131
|
}
|
|
3919
4132
|
watchInputVerticalList(newValue) {
|
|
3920
4133
|
if (newValue)
|
|
@@ -3929,7 +4142,7 @@ const MgInputRadio = class {
|
|
|
3929
4142
|
this.classCollection.delete(mgInput_conf.classReadonly);
|
|
3930
4143
|
}
|
|
3931
4144
|
handleValidityChange(newValue, _oldValue, prop) {
|
|
3932
|
-
this.
|
|
4145
|
+
this.getInputs().forEach((input) => {
|
|
3933
4146
|
input[prop] = newValue;
|
|
3934
4147
|
});
|
|
3935
4148
|
this.checkValidity();
|
|
@@ -3948,9 +4161,8 @@ const MgInputRadio = class {
|
|
|
3948
4161
|
* Set focus on input.
|
|
3949
4162
|
*/
|
|
3950
4163
|
async setFocus() {
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
}
|
|
4164
|
+
var _a;
|
|
4165
|
+
(_a = this.element.shadowRoot.querySelector('input')) === null || _a === void 0 ? void 0 : _a.focus();
|
|
3954
4166
|
}
|
|
3955
4167
|
/**
|
|
3956
4168
|
* Display input error if it exists.
|
|
@@ -3992,6 +4204,8 @@ const MgInputRadio = class {
|
|
|
3992
4204
|
lock: valid ? false : errorMessageLock,
|
|
3993
4205
|
message: valid ? undefined : errorMessage,
|
|
3994
4206
|
};
|
|
4207
|
+
// setError() states the validity explicitly, so drop any pending recomputation
|
|
4208
|
+
this.validityCheckPending = false;
|
|
3995
4209
|
this.setValidity(valid);
|
|
3996
4210
|
this.setErrorMessage(true);
|
|
3997
4211
|
this.hasDisplayedError = this.invalid;
|
|
@@ -4057,20 +4271,35 @@ const MgInputRadio = class {
|
|
|
4057
4271
|
// https://stenciljs.com/docs/component-lifecycle#componentwillload
|
|
4058
4272
|
return setTimeout(() => {
|
|
4059
4273
|
this.checkValidity();
|
|
4274
|
+
// the initial check covers the initial value: nothing is pending yet
|
|
4275
|
+
this.validityCheckPending = false;
|
|
4060
4276
|
}, 0);
|
|
4061
4277
|
}
|
|
4278
|
+
/**
|
|
4279
|
+
* Recompute validity once the DOM is in sync with `value`.
|
|
4280
|
+
* `@Watch('value')` fires before Stencil re-renders, so the rendered control still holds the
|
|
4281
|
+
* previous value at that point (visible with a programmatic value change, e.g. a `v-model`
|
|
4282
|
+
* default value). The watcher therefore only raises a flag, and the check runs here, after the
|
|
4283
|
+
* render. Renders unrelated to `value` leave the flag down and recompute nothing.
|
|
4284
|
+
*/
|
|
4285
|
+
componentDidUpdate() {
|
|
4286
|
+
if (this.validityCheckPending && this.getInputs().length > 0) {
|
|
4287
|
+
this.validityCheckPending = false;
|
|
4288
|
+
this.checkValidity();
|
|
4289
|
+
if (this.hasDisplayedError) {
|
|
4290
|
+
this.setErrorMessage();
|
|
4291
|
+
}
|
|
4292
|
+
}
|
|
4293
|
+
}
|
|
4062
4294
|
/**
|
|
4063
4295
|
* Render
|
|
4064
4296
|
* @returns HTML Element
|
|
4065
4297
|
*/
|
|
4066
4298
|
render() {
|
|
4067
|
-
return (index.h("mg-input", { key: '
|
|
4299
|
+
return (index.h("mg-input", { key: '1fd4b600eb95f2ff5c753884c40b982e0552d576', 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 && !this.value ? 'label' : this.tooltipPosition, helpText: this.helpText, errorMessage: this.errorMessage }, this.readonly ? (this.readonlyValue && index.h("b", { class: "mg-c-input__readonly-value" }, this.readonlyValue)) : (index.h("div", { class: "mg-c-input__input-group-container" }, this.options.map((input, index$1) => (index.h("div", { key: input.title, class: {
|
|
4068
4300
|
'mg-c-input__input-group': true,
|
|
4069
4301
|
'mg-c-input__input-group--disabled': this.disabled || input.disabled,
|
|
4070
|
-
} }, index.h("input", { type: "radio", id: this.identifier + '_' + index$1, name: this.identifier, value: index$1, checked:
|
|
4071
|
-
if (el !== null)
|
|
4072
|
-
this.inputs[index$1] = el;
|
|
4073
|
-
} }), index.h("label", { htmlFor: this.identifier + '_' + index$1 }, input.title))))))));
|
|
4302
|
+
} }, index.h("input", { type: "radio", id: this.identifier + '_' + index$1, name: this.identifier, value: index$1, checked: this.isSelectedValue(this.options[index$1].value), disabled: this.disabled || input.disabled, required: this.required, onBlur: this.handleBlur, onInput: this.handleInput }), index.h("label", { htmlFor: this.identifier + '_' + index$1 }, input.title))))))));
|
|
4074
4303
|
}
|
|
4075
4304
|
get element() { return index.getElement(this); }
|
|
4076
4305
|
static get watchers() { return {
|
|
@@ -4123,8 +4352,9 @@ const isOptGroup = (optgroup) => typeof optgroup === 'object' &&
|
|
|
4123
4352
|
typeof optgroup.group === 'string' &&
|
|
4124
4353
|
allItemsAreOptions(optgroup.options);
|
|
4125
4354
|
/**
|
|
4126
|
-
*
|
|
4355
|
+
* Report, without enforcing, options that cannot be unambiguously differentiated by their title
|
|
4127
4356
|
* Two options can share the same title only when they belong to different groups
|
|
4357
|
+
* An option is identified by its render index, so a duplicated title only harms readability: it is reported to the developer and the field still renders
|
|
4128
4358
|
* @param items - select options to validate
|
|
4129
4359
|
*/
|
|
4130
4360
|
const validateUniqueTitles = (items) => {
|
|
@@ -4136,7 +4366,7 @@ const validateUniqueTitles = (items) => {
|
|
|
4136
4366
|
const titles = titlesByGroup.get(group);
|
|
4137
4367
|
if (titles.has(title)) {
|
|
4138
4368
|
const groupContext = group === undefined ? 'outside of a group' : `within the group "${group}"`;
|
|
4139
|
-
|
|
4369
|
+
console.error(`<mg-input-select> prop "items" must not contain options with the same "title" ${groupContext}. Duplicated title: "${title}".`);
|
|
4140
4370
|
}
|
|
4141
4371
|
titles.add(title);
|
|
4142
4372
|
});
|
|
@@ -4172,6 +4402,8 @@ const MgInputSelect = class {
|
|
|
4172
4402
|
this.inputValid = index.createEvent(this, "input-valid", 7);
|
|
4173
4403
|
// hasDisplayedError (triggered by blur event)
|
|
4174
4404
|
this.hasDisplayedError = false;
|
|
4405
|
+
// raised when `value` or `items` changed, so componentDidUpdate revalidates once the DOM is in sync
|
|
4406
|
+
this.validityCheckPending = false;
|
|
4175
4407
|
this.customErrorMessage = { lock: false };
|
|
4176
4408
|
/**
|
|
4177
4409
|
* Input name
|
|
@@ -4319,18 +4551,14 @@ const MgInputSelect = class {
|
|
|
4319
4551
|
this.renderOption = (option, index$1) => (index.h("option", { key: index$1, value: `${index$1}`, selected: JSON.stringify(this.value) === JSON.stringify(option.value), disabled: option.disabled }, option.title));
|
|
4320
4552
|
}
|
|
4321
4553
|
validateValue(newValue) {
|
|
4322
|
-
|
|
4323
|
-
this.checkValidity();
|
|
4324
|
-
if (this.hasDisplayedError) {
|
|
4325
|
-
this.setErrorMessage();
|
|
4326
|
-
}
|
|
4327
|
-
}, 0);
|
|
4554
|
+
this.validityCheckPending = true;
|
|
4328
4555
|
this.valueChange.emit(newValue);
|
|
4329
4556
|
}
|
|
4330
|
-
validateItems(newValue) {
|
|
4557
|
+
validateItems(newValue, oldValue) {
|
|
4331
4558
|
// Empty options
|
|
4332
4559
|
if (newValue.length === 0) {
|
|
4333
4560
|
this.options = [];
|
|
4561
|
+
this.valueExist = false;
|
|
4334
4562
|
}
|
|
4335
4563
|
// String array
|
|
4336
4564
|
else if (index$1.allItemsAreString(newValue)) {
|
|
@@ -4356,6 +4584,9 @@ const MgInputSelect = class {
|
|
|
4356
4584
|
else {
|
|
4357
4585
|
throw new Error(`<mg-input-select> prop "items" is required, can be an empty Array or all items must be the same type: string or Option. Passed value: ${index$1.toString(newValue)}.`);
|
|
4358
4586
|
}
|
|
4587
|
+
// `oldValue` is undefined on init. The value is kept: an unmatched one renders the placeholder.
|
|
4588
|
+
if (oldValue !== undefined)
|
|
4589
|
+
this.validityCheckPending = true;
|
|
4359
4590
|
}
|
|
4360
4591
|
watchReadonly(newValue) {
|
|
4361
4592
|
if (newValue)
|
|
@@ -4435,6 +4666,8 @@ const MgInputSelect = class {
|
|
|
4435
4666
|
lock: valid ? false : errorMessageLock,
|
|
4436
4667
|
message: valid ? undefined : errorMessage,
|
|
4437
4668
|
};
|
|
4669
|
+
// setError() states the validity explicitly, so drop any pending recomputation
|
|
4670
|
+
this.validityCheckPending = false;
|
|
4438
4671
|
this.setValidity(valid);
|
|
4439
4672
|
this.setErrorMessage(true);
|
|
4440
4673
|
this.hasDisplayedError = this.invalid;
|
|
@@ -4505,8 +4738,26 @@ const MgInputSelect = class {
|
|
|
4505
4738
|
// https://stenciljs.com/docs/component-lifecycle#componentwillload
|
|
4506
4739
|
return setTimeout(() => {
|
|
4507
4740
|
this.checkValidity();
|
|
4741
|
+
// the initial check covers the initial value: nothing is pending yet
|
|
4742
|
+
this.validityCheckPending = false;
|
|
4508
4743
|
}, 0);
|
|
4509
4744
|
}
|
|
4745
|
+
/**
|
|
4746
|
+
* Recompute validity once the DOM is in sync with `value`.
|
|
4747
|
+
* `@Watch('value')` fires before Stencil re-renders, so the rendered control still holds the
|
|
4748
|
+
* previous value at that point (visible with a programmatic value change, e.g. a `v-model`
|
|
4749
|
+
* default value). The watcher therefore only raises a flag, and the check runs here, after the
|
|
4750
|
+
* render. Renders unrelated to `value` leave the flag down and recompute nothing.
|
|
4751
|
+
*/
|
|
4752
|
+
componentDidUpdate() {
|
|
4753
|
+
if (this.validityCheckPending && this.input !== undefined) {
|
|
4754
|
+
this.validityCheckPending = false;
|
|
4755
|
+
this.checkValidity();
|
|
4756
|
+
if (this.hasDisplayedError) {
|
|
4757
|
+
this.setErrorMessage();
|
|
4758
|
+
}
|
|
4759
|
+
}
|
|
4760
|
+
}
|
|
4510
4761
|
/**
|
|
4511
4762
|
* Render
|
|
4512
4763
|
* @returns HTML Element
|
|
@@ -4515,7 +4766,7 @@ const MgInputSelect = class {
|
|
|
4515
4766
|
const readonlyValue = this.getReadonlyValue();
|
|
4516
4767
|
// Running index shared across groups, so each option gets a unique value matching its position in getOptions()
|
|
4517
4768
|
let optionIndex = 0;
|
|
4518
|
-
return (index.h("mg-input", { key: '
|
|
4769
|
+
return (index.h("mg-input", { key: 'ca4a3a1b95094505bff8bf062566a633a1b12d1a', 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 && index.h("b", { class: "mg-c-input__readonly-value" }, readonlyValue)) : (index.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) => {
|
|
4519
4770
|
if (el !== null)
|
|
4520
4771
|
this.input = el;
|
|
4521
4772
|
} }, (!this.placeholderHide || !this.valueExist) && ( // In case passed value does not match any option we display the placeholder
|
|
@@ -4589,6 +4840,8 @@ const MgInputText = class {
|
|
|
4589
4840
|
// hasDisplayedError (triggered by blur event)
|
|
4590
4841
|
this.hasDisplayedError = false;
|
|
4591
4842
|
this.customErrorMessage = { lock: false };
|
|
4843
|
+
// raised when `value` changed, so componentDidUpdate revalidates once the DOM is in sync
|
|
4844
|
+
this.validityCheckPending = false;
|
|
4592
4845
|
/**
|
|
4593
4846
|
* Input name
|
|
4594
4847
|
* If not set the value equals the identifier
|
|
@@ -4653,10 +4906,6 @@ const MgInputText = class {
|
|
|
4653
4906
|
* Handle input event
|
|
4654
4907
|
*/
|
|
4655
4908
|
this.handleInput = () => {
|
|
4656
|
-
this.checkValidity();
|
|
4657
|
-
if (this.hasDisplayedError) {
|
|
4658
|
-
this.setErrorMessage();
|
|
4659
|
-
}
|
|
4660
4909
|
this.value = this.input.value;
|
|
4661
4910
|
};
|
|
4662
4911
|
/**
|
|
@@ -4737,6 +4986,7 @@ const MgInputText = class {
|
|
|
4737
4986
|
}
|
|
4738
4987
|
handleValue(newValue) {
|
|
4739
4988
|
var _a, _b;
|
|
4989
|
+
this.validityCheckPending = true;
|
|
4740
4990
|
if ((_a = this.datalistoptions) === null || _a === void 0 ? void 0 : _a.every(isOption$1)) {
|
|
4741
4991
|
this.valueChange.emit(((_b = this.datalistoptions.find((option) => option.title === newValue)) === null || _b === void 0 ? void 0 : _b.value) || newValue);
|
|
4742
4992
|
}
|
|
@@ -4856,6 +5106,8 @@ const MgInputText = class {
|
|
|
4856
5106
|
lock: valid ? false : errorMessageLock,
|
|
4857
5107
|
message: valid ? undefined : errorMessage,
|
|
4858
5108
|
};
|
|
5109
|
+
// setError() states the validity explicitly, so drop any pending recomputation
|
|
5110
|
+
this.validityCheckPending = false;
|
|
4859
5111
|
this.setValidity(valid);
|
|
4860
5112
|
this.setErrorMessage(true);
|
|
4861
5113
|
this.hasDisplayedError = this.invalid;
|
|
@@ -4928,14 +5180,32 @@ const MgInputText = class {
|
|
|
4928
5180
|
// https://stenciljs.com/docs/component-lifecycle#componentwillload
|
|
4929
5181
|
return setTimeout(() => {
|
|
4930
5182
|
this.checkValidity();
|
|
5183
|
+
// the initial check covers the initial value: nothing is pending yet
|
|
5184
|
+
this.validityCheckPending = false;
|
|
4931
5185
|
}, 0);
|
|
4932
5186
|
}
|
|
5187
|
+
/**
|
|
5188
|
+
* Recompute validity once the DOM is in sync with `value`.
|
|
5189
|
+
* `@Watch('value')` fires before Stencil re-renders, so the rendered control still holds the
|
|
5190
|
+
* previous value at that point (visible with a programmatic value change, e.g. a `v-model`
|
|
5191
|
+
* default value). The watcher therefore only raises a flag, and the check runs here, after the
|
|
5192
|
+
* render. Renders unrelated to `value` leave the flag down and recompute nothing.
|
|
5193
|
+
*/
|
|
5194
|
+
componentDidUpdate() {
|
|
5195
|
+
if (this.validityCheckPending && this.input !== undefined) {
|
|
5196
|
+
this.validityCheckPending = false;
|
|
5197
|
+
this.checkValidity();
|
|
5198
|
+
if (this.hasDisplayedError) {
|
|
5199
|
+
this.setErrorMessage();
|
|
5200
|
+
}
|
|
5201
|
+
}
|
|
5202
|
+
}
|
|
4933
5203
|
/**
|
|
4934
5204
|
* Render
|
|
4935
5205
|
* @returns HTML Element
|
|
4936
5206
|
*/
|
|
4937
5207
|
render() {
|
|
4938
|
-
return (index.h("mg-input", { key: '
|
|
5208
|
+
return (index.h("mg-input", { key: '20a89d186c673936740cce348977cc0a8471fafb', 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
|
|
4939
5209
|
? this.value && this.renderReadonly()
|
|
4940
5210
|
: [
|
|
4941
5211
|
index.h("div", { key: "input", class: "mg-c-input__input-group-container", style: {
|
|
@@ -5004,6 +5274,8 @@ const MgInputTextarea = class {
|
|
|
5004
5274
|
this.inputValid = index.createEvent(this, "input-valid", 7);
|
|
5005
5275
|
// hasDisplayedError (triggered by blur event)
|
|
5006
5276
|
this.hasDisplayedError = false;
|
|
5277
|
+
// raised when `value` changed, so componentDidUpdate revalidates once the DOM is in sync
|
|
5278
|
+
this.validityCheckPending = false;
|
|
5007
5279
|
this.customErrorMessage = { lock: false };
|
|
5008
5280
|
/**
|
|
5009
5281
|
* Input name
|
|
@@ -5062,10 +5334,6 @@ const MgInputTextarea = class {
|
|
|
5062
5334
|
* Handle input event
|
|
5063
5335
|
*/
|
|
5064
5336
|
this.handleInput = () => {
|
|
5065
|
-
if (this.hasDisplayedError) {
|
|
5066
|
-
this.checkValidity();
|
|
5067
|
-
this.setErrorMessage();
|
|
5068
|
-
}
|
|
5069
5337
|
this.value = this.input.value;
|
|
5070
5338
|
};
|
|
5071
5339
|
/**
|
|
@@ -5115,7 +5383,7 @@ const MgInputTextarea = class {
|
|
|
5115
5383
|
};
|
|
5116
5384
|
}
|
|
5117
5385
|
handleValue(newValue) {
|
|
5118
|
-
this.
|
|
5386
|
+
this.validityCheckPending = true;
|
|
5119
5387
|
this.valueChange.emit(newValue);
|
|
5120
5388
|
}
|
|
5121
5389
|
watchReadonly(newValue) {
|
|
@@ -5209,6 +5477,8 @@ const MgInputTextarea = class {
|
|
|
5209
5477
|
lock: valid ? false : errorMessageLock,
|
|
5210
5478
|
message: valid ? undefined : errorMessage,
|
|
5211
5479
|
};
|
|
5480
|
+
// setError() states the validity explicitly, so drop any pending recomputation
|
|
5481
|
+
this.validityCheckPending = false;
|
|
5212
5482
|
this.setValidity(valid);
|
|
5213
5483
|
this.setErrorMessage(true);
|
|
5214
5484
|
this.hasDisplayedError = this.invalid;
|
|
@@ -5276,14 +5546,32 @@ const MgInputTextarea = class {
|
|
|
5276
5546
|
// https://stenciljs.com/docs/component-lifecycle#componentwillload
|
|
5277
5547
|
return setTimeout(() => {
|
|
5278
5548
|
this.checkValidity();
|
|
5549
|
+
// the initial check covers the initial value: nothing is pending yet
|
|
5550
|
+
this.validityCheckPending = false;
|
|
5279
5551
|
}, 0);
|
|
5280
5552
|
}
|
|
5553
|
+
/**
|
|
5554
|
+
* Recompute validity once the DOM is in sync with `value`.
|
|
5555
|
+
* `@Watch('value')` fires before Stencil re-renders, so the rendered control still holds the
|
|
5556
|
+
* previous value at that point (visible with a programmatic value change, e.g. a `v-model`
|
|
5557
|
+
* default value). The watcher therefore only raises a flag, and the check runs here, after the
|
|
5558
|
+
* render. Renders unrelated to `value` leave the flag down and recompute nothing.
|
|
5559
|
+
*/
|
|
5560
|
+
componentDidUpdate() {
|
|
5561
|
+
if (this.validityCheckPending && this.input !== undefined) {
|
|
5562
|
+
this.validityCheckPending = false;
|
|
5563
|
+
this.checkValidity();
|
|
5564
|
+
if (this.hasDisplayedError) {
|
|
5565
|
+
this.setErrorMessage();
|
|
5566
|
+
}
|
|
5567
|
+
}
|
|
5568
|
+
}
|
|
5281
5569
|
/**
|
|
5282
5570
|
* Render
|
|
5283
5571
|
* @returns HTML Element
|
|
5284
5572
|
*/
|
|
5285
5573
|
render() {
|
|
5286
|
-
return (index.h("mg-input", { key: '
|
|
5574
|
+
return (index.h("mg-input", { key: 'e3bf8b4bbddccaf86a78f8517cc529aa41cc61d6', 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 ? (this.value && index.h("b", { class: "mg-c-input__readonly-value" }, this.value)) : (index.h("div", { class: "mg-c-input__input-group-container" }, index.h("textarea", { class: {
|
|
5287
5575
|
'mg-c-input__box': true,
|
|
5288
5576
|
'mg-c-input__box--width': true,
|
|
5289
5577
|
'mg-c-input__box--resizable': this.resizable === 'both',
|
|
@@ -6562,7 +6850,7 @@ MgMessage.style = mgMessageCss();
|
|
|
6562
6850
|
*/
|
|
6563
6851
|
const dialogRoles = ['dialog', 'alertdialog'];
|
|
6564
6852
|
|
|
6565
|
-
const mgModalCss = () => `:host{--mg-c-card-border-radius:var(--mg-c-modal-border-radius);--mg-c-card-spacing:var(--mg-b-size-16) var(--mg-b-size-24);--mg-c-card-border:none}.mg-c-modal{max-height:100dvh;box-sizing:border-box;border:none;background:none;color:inherit}.mg-c-modal[open]{display:flex;padding:var(--mg-b-size-24) var(--mg-b-size-8)}.mg-c-modal::backdrop{background-color:var(--mg-b-color-dark);opacity:.65}.mg-c-modal mg-card{display:flex;width:calc(75*var(--mg-b-size-8));max-width:100%;max-height:100dvh}.mg-c-modal__dialog{position:relative;display:flex;height:fit-content;max-height:100%;flex-direction:column;align-self:center;row-gap:var(--mg-b-size-16)}.mg-c-modal__title{margin:0;font-family:var(--mg-b-font-family-heading);font-size:var(--mg-c-modal-title-font-size);font-weight:600}.mg-c-modal__close-button{height:var(--mg-c-modal-title-font-size);margin-top:calc((var(--mg-b-size-min-height) - var(--mg-c-modal-title-font-size)*var(--mg-b-line-height))/2*-1);margin-right:calc((var(--mg-b-size-min-height) - var(--mg-b-size-16))/2*-1);margin-left:var(--mg-b-size-16);float:right}.mg-c-modal__content{padding:var(--mg-b-size-16);margin:calc(var(--mg-b-size-16)*-1);overflow-y:auto}.mg-c-modal__footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--mg-b-size-8)}.mg-c-modal ::slotted(*:not(mg-panel,mg-message,mg-modal)){--mg-c-card-border:var(--mg-c-card-border-default);--mg-c-card-spacing:var(--mg-c-card-spacing-default);--mg-c-card-border-radius:var(--mg-c-card-border-radius-default);--mg-c-card-color-background:var(--mg-c-card-color-background-default);--mg-c-card-box-shadow:var(--mg-c-card-box-shadow-default);--mg-c-card-max-width:unset;--mg-c-card-min-width:unset;--mg-c-card-max-height:unset;--mg-c-card-overflow:var(--mg-c-card-overflow-default)}`;
|
|
6853
|
+
const mgModalCss = () => `:host{--mg-c-card-border-radius:var(--mg-c-modal-border-radius);--mg-c-card-spacing:var(--mg-b-size-16) var(--mg-b-size-24);--mg-c-card-border:none}.mg-c-modal{max-height:100dvh;box-sizing:border-box;border:none;background:none;color:inherit}.mg-c-modal[open]{display:flex;padding:var(--mg-b-size-24) var(--mg-b-size-8)}.mg-c-modal::backdrop{background-color:var(--mg-b-color-dark);opacity:.65}.mg-c-modal mg-card{display:flex;width:calc(75*var(--mg-b-size-8));max-width:100%;max-height:100dvh}.mg-c-modal__dialog{position:relative;display:flex;height:fit-content;max-height:100%;flex-direction:column;align-self:center;row-gap:var(--mg-b-size-16)}.mg-c-modal__title{margin:0;font-family:var(--mg-b-font-family-heading);font-size:var(--mg-c-modal-title-font-size);font-weight:600}.mg-c-modal__close-button{height:var(--mg-c-modal-title-font-size);margin-top:calc((var(--mg-b-size-min-height) - var(--mg-c-modal-title-font-size)*var(--mg-b-line-height))/2*-1);margin-right:calc((var(--mg-b-size-min-height) - var(--mg-b-size-16))/2*-1);margin-left:var(--mg-b-size-16);float:right}.mg-c-modal__content{padding:var(--mg-b-size-16);margin:calc(var(--mg-b-size-16)*-1);overflow-y:auto;scroll-padding-block:var(--mg-b-size-16)}.mg-c-modal__footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--mg-b-size-8)}.mg-c-modal ::slotted(*:not(mg-panel,mg-message,mg-modal)){--mg-c-card-border:var(--mg-c-card-border-default);--mg-c-card-spacing:var(--mg-c-card-spacing-default);--mg-c-card-border-radius:var(--mg-c-card-border-radius-default);--mg-c-card-color-background:var(--mg-c-card-color-background-default);--mg-c-card-box-shadow:var(--mg-c-card-box-shadow-default);--mg-c-card-max-width:unset;--mg-c-card-min-width:unset;--mg-c-card-max-height:unset;--mg-c-card-overflow:var(--mg-c-card-overflow-default)}`;
|
|
6566
6854
|
|
|
6567
6855
|
const MgModal = class {
|
|
6568
6856
|
constructor(hostRef) {
|