@schukai/monster 4.56.0 → 4.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/package.json +1 -1
  3. package/source/components/data/stylesheet/metric-graph.mjs +1 -1
  4. package/source/components/data/stylesheet/metric.mjs +1 -1
  5. package/source/components/datatable/dataset.mjs +10 -0
  6. package/source/components/datatable/datasource/rest.mjs +141 -14
  7. package/source/components/datatable/datasource.mjs +8 -1
  8. package/source/components/datatable/datatable.mjs +3 -7
  9. package/source/components/datatable/save-button.mjs +348 -334
  10. package/source/components/datatable/status.mjs +7 -0
  11. package/source/components/datatable/util.mjs +7 -0
  12. package/source/components/form/button-bar.mjs +193 -95
  13. package/source/components/form/field-set.mjs +283 -283
  14. package/source/components/form/form.mjs +407 -162
  15. package/source/components/form/login.mjs +1571 -1571
  16. package/source/components/form/quantity.mjs +233 -233
  17. package/source/components/form/select.mjs +3106 -3101
  18. package/source/components/form/style/field-set.pcss +6 -2
  19. package/source/components/form/style/form.pcss +8 -0
  20. package/source/components/form/stylesheet/field-set.mjs +1 -1
  21. package/source/components/form/stylesheet/form.mjs +1 -1
  22. package/source/components/form/stylesheet/select.mjs +13 -6
  23. package/source/components/style/typography.css +2 -2
  24. package/source/components/tree-menu/stylesheet/tree-menu.mjs +1 -1
  25. package/source/constraints/abstract.mjs +17 -17
  26. package/source/dom/customelement.mjs +962 -963
  27. package/source/dom/updater.mjs +874 -863
  28. package/source/dom/util/init-options-from-attributes.mjs +56 -56
  29. package/source/monster.mjs +0 -1
  30. package/source/net/webconnect.mjs +325 -325
  31. package/source/types/is.mjs +66 -66
@@ -21,29 +21,29 @@ import { Formatter } from "../text/formatter.mjs";
21
21
  import { parseDataURL } from "../types/dataurl.mjs";
22
22
  import { getGlobalObject } from "../types/global.mjs";
23
23
  import {
24
- isArray,
25
- isFunction,
26
- isIterable,
27
- isObject,
28
- isString,
24
+ isArray,
25
+ isFunction,
26
+ isIterable,
27
+ isObject,
28
+ isString,
29
29
  } from "../types/is.mjs";
30
30
  import { Observer } from "../types/observer.mjs";
31
31
  import { ProxyObserver } from "../types/proxyobserver.mjs";
32
32
  import {
33
- validateFunction,
34
- validateInstance,
35
- validateObject,
33
+ validateFunction,
34
+ validateInstance,
35
+ validateObject,
36
36
  } from "../types/validate.mjs";
37
37
  import { clone } from "../util/clone.mjs";
38
38
  import { getLinkedObjects, hasObjectLink } from "./attributes.mjs";
39
39
  import {
40
- ATTRIBUTE_DISABLED,
41
- ATTRIBUTE_OPTIONS,
42
- ATTRIBUTE_INIT_CALLBACK,
43
- ATTRIBUTE_OPTIONS_SELECTOR,
44
- ATTRIBUTE_SCRIPT_HOST,
45
- customElementUpdaterLinkSymbol,
46
- initControlCallbackName,
40
+ ATTRIBUTE_DISABLED,
41
+ ATTRIBUTE_OPTIONS,
42
+ ATTRIBUTE_INIT_CALLBACK,
43
+ ATTRIBUTE_OPTIONS_SELECTOR,
44
+ ATTRIBUTE_SCRIPT_HOST,
45
+ customElementUpdaterLinkSymbol,
46
+ initControlCallbackName,
47
47
  } from "./constants.mjs";
48
48
  import { findDocumentTemplate, Template } from "./template.mjs";
49
49
  import { addObjectWithUpdaterToElement } from "./updater.mjs";
@@ -55,13 +55,13 @@ import { setOptionFromAttribute } from "./util/set-option-from-attribute.mjs";
55
55
  import { addErrorAttribute } from "./error.mjs";
56
56
 
57
57
  export {
58
- CustomElement,
59
- initMethodSymbol,
60
- assembleMethodSymbol,
61
- attributeObserverSymbol,
62
- registerCustomElement,
63
- getSlottedElements,
64
- updaterTransformerMethodsSymbol,
58
+ CustomElement,
59
+ initMethodSymbol,
60
+ assembleMethodSymbol,
61
+ attributeObserverSymbol,
62
+ registerCustomElement,
63
+ getSlottedElements,
64
+ updaterTransformerMethodsSymbol,
65
65
  };
66
66
 
67
67
  /**
@@ -73,14 +73,14 @@ const initMethodSymbol = Symbol.for("@schukai/monster/dom/@@initMethodSymbol");
73
73
  * @type {symbol}
74
74
  */
75
75
  const assembleMethodSymbol = Symbol.for(
76
- "@schukai/monster/dom/@@assembleMethodSymbol",
76
+ "@schukai/monster/dom/@@assembleMethodSymbol",
77
77
  );
78
78
 
79
79
  /**
80
80
  * @type {symbol}
81
81
  */
82
82
  const updaterTransformerMethodsSymbol = Symbol.for(
83
- "@schukai/monster/dom/@@updaterTransformerMethodsSymbol",
83
+ "@schukai/monster/dom/@@updaterTransformerMethodsSymbol",
84
84
  );
85
85
 
86
86
  /**
@@ -88,7 +88,7 @@ const updaterTransformerMethodsSymbol = Symbol.for(
88
88
  * @type {symbol}
89
89
  */
90
90
  const attributeObserverSymbol = Symbol.for(
91
- "@schukai/monster/dom/@@attributeObserver",
91
+ "@schukai/monster/dom/@@attributeObserver",
92
92
  );
93
93
 
94
94
  /**
@@ -96,7 +96,7 @@ const attributeObserverSymbol = Symbol.for(
96
96
  * @type {symbol}
97
97
  */
98
98
  const attributeMutationObserverSymbol = Symbol(
99
- "@schukai/monster/dom/@@mutationObserver",
99
+ "@schukai/monster/dom/@@mutationObserver",
100
100
  );
101
101
 
102
102
  /**
@@ -185,580 +185,580 @@ const scriptHostElementSymbol = Symbol("scriptHostElement");
185
185
  * @summary A base class for HTML5 custom controls.
186
186
  */
187
187
  class CustomElement extends HTMLElement {
188
- /**
189
- * A new object is created. First, the `initOptions` method is called. Here the
190
- * options can be defined in derived classes. Subsequently, the shadowRoot is initialized.
191
- *
192
- * IMPORTANT: CustomControls instances are not created via the constructor, but either via a tag in the HTML or via <code>document.createElement()</code>.
193
- *
194
- * @throws {Error} the option attribute does not contain a valid JSON definition.
195
- */
196
- constructor() {
197
- super();
198
-
199
- this[attributeObserverSymbol] = {};
200
-
201
- const options = initOptionsFromAttributes(this, extend({}, this.defaults));
202
- if (!isObject(options)) {
203
- throw new Error(
204
- `The options are not defined correctly in the ${this.getTag()} element.`,
205
- );
206
- }
207
-
208
- if (this.customization instanceof Map) {
209
- const pathfinder = new Pathfinder(options);
210
- this.customization.forEach((value, key) => {
211
- if (key === undefined || key === null || key === "") {
212
- return;
213
- }
214
- pathfinder.setVia(key, value);
215
- });
216
- }
217
-
218
- this[internalSymbol] = new ProxyObserver({ options });
219
- this[initMethodSymbol]();
220
- initOptionObserver.call(this);
221
- this[scriptHostElementSymbol] = [];
222
- }
223
-
224
- /**
225
- * This method is called by the `instanceof` operator.
226
- *
227
- * @return {symbol}
228
- * @since 2.1.0
229
- */
230
- static get [instanceSymbol]() {
231
- return Symbol.for("@schukai/monster/dom/custom-element@@instance");
232
- }
233
-
234
- /**
235
- * This method determines which attributes are to be
236
- * monitored by `attributeChangedCallback()`. Unfortunately, this method is static.
237
- * Therefore, the `observedAttributes` property cannot be changed during runtime.
238
- *
239
- * @return {string[]}
240
- * @since 1.15.0
241
- */
242
- static get observedAttributes() {
243
- return [];
244
- }
245
-
246
- /**
247
- *
248
- * @param attribute
249
- * @param callback
250
- * @return {CustomElement}
251
- */
252
- addAttributeObserver(attribute, callback) {
253
- validateFunction(callback);
254
- this[attributeObserverSymbol][attribute] = callback;
255
- return this;
256
- }
257
-
258
- /**
259
- *
260
- * @param attribute
261
- * @return {CustomElement}
262
- */
263
- removeAttributeObserver(attribute) {
264
- delete this[attributeObserverSymbol][attribute];
265
- return this;
266
- }
267
-
268
- /**
269
- * The `customization` property allows overwriting the defaults.
270
- * Unlike the defaults that expect an object, the customization is a Map.
271
- * This also allows overwriting individual values in a deeper structure
272
- * without having to redefine the entire structure and thus changing the defaults.
273
- * @returns {Map}
274
- */
275
- get customization() {
276
- return new Map();
277
- }
278
-
279
- /**
280
- * The `defaults` property defines the default values for a control. If you want to override these,
281
- * you can use various methods, which are described in the documentation available at
282
- * {@link https://monsterjs.orgendocconfigurate-a-monster-control}.
283
- *
284
- * The individual configuration values are listed below:
285
- *
286
- * More information about the shadowRoot can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow),
287
- * in the [HTML Standard](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements) or in the [WHATWG Wiki](https://wiki.whatwg.org/wiki/Custom_Elements).
288
- *
289
- * More information about the template element can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).
290
- *
291
- * More information about the slot element can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot).
292
- *
293
- * @property {boolean} disabled=false Specifies whether the control is disabled. When present, it makes the element non-mutable, non-focusable, and non-submittable with the form.
294
- * @property {string} shadowMode=open Specifies the mode of the shadow root. When set to `open`, elements in the shadow root are accessible from JavaScript outside the root, while setting it to `closed` denies access to the root's nodes from JavaScript outside it.
295
- * @property {Boolean} delegatesFocus=true Specifies the behavior of the control with respect to focusability. When set to `true`, it mitigates custom element issues around focusability. When a non-focusable part of the shadow DOM is clicked, the first focusable part is given focus, and the shadow host is given any available :focus styling.
296
- * @property {Object} templates Specifies the templates used by the control.
297
- * @property {string} templates.main=undefined Specifies the main template used by the control.
298
- * @property {Object} templateMapping Specifies the mapping of templates.
299
- * @property {Object} templateFormatter Specifies the formatter for the templates.
300
- * @property {Object} templateFormatter.marker Specifies the marker for the templates.
301
- * @property {Function} templateFormatter.marker.open=null Specifies the opening marker for the templates.
302
- * @property {Function} templateFormatter.marker.close=null Specifies the closing marker for the templates.
303
- * @property {Boolean} templateFormatter.i18n=false Specifies whether the templates should be formatted with i18n.
304
- * @property {Boolean} eventProcessing=false Specifies whether the control processes events.
305
- * @since 1.8.0
306
- */
307
- get defaults() {
308
- return {
309
- disabled: false,
310
- shadowMode: "open",
311
- delegatesFocus: true,
312
- templates: {
313
- main: undefined,
314
- },
315
- templateMapping: {},
316
- templateFormatter: {
317
- marker: {
318
- open: null,
319
- close: null,
320
- },
321
- i18n: false,
322
- },
323
-
324
- eventProcessing: false,
325
- };
326
- }
327
-
328
- /**
329
- * This method updates the labels of the element.
330
- * The labels are defined in the option object.
331
- * The key of the label is used to retrieve the translation from the document.
332
- * If the translation is different from the label, the label is updated.
333
- *
334
- * Before you can use this method, you must have loaded the translations.
335
- *
336
- * @return {CustomElement}
337
- * @throws {Error} Cannot find an element with translations. Add a translation object to the document.
338
- */
339
- updateI18n() {
340
- let translations;
341
-
342
- try {
343
- translations = getDocumentTranslations();
344
- } catch (e) {
345
- addErrorAttribute(this, e);
346
- return this;
347
- }
348
-
349
- if (!translations) {
350
- return this;
351
- }
352
-
353
- const labels = this.getOption("labels");
354
- if (!(isObject(labels) || isIterable(labels))) {
355
- return this;
356
- }
357
-
358
- for (const key in labels) {
359
- const def = labels[key];
360
-
361
- if (isString(def)) {
362
- const text = translations.getText(key, def);
363
- if (text !== def) {
364
- this.setOption(`labels.${key}`, text);
365
- }
366
- continue;
367
- } else if (isObject(def)) {
368
- for (const k in def) {
369
- const d = def[k];
370
-
371
- const text = translations.getPluralRuleText(key, k, d);
372
- if (!isString(text)) {
373
- throw new Error("Invalid labels definition");
374
- }
375
- if (text !== d) {
376
- this.setOption(`labels.${key}.${k}`, text);
377
- }
378
- }
379
- continue;
380
- }
381
-
382
- throw new Error("Invalid labels definition");
383
- }
384
- return this;
385
- }
386
-
387
- /**
388
- * The `getTag()` method returns the tag name associated with the custom element. This method should be overwritten
389
- * by the derived class.
390
- *
391
- * Note that there is no check on the name of the tag in this class. It is the responsibility of
392
- * the developer to assign an appropriate tag name. If the name is not valid, the
393
- * `registerCustomElement()` method will issue an error.
394
- *
395
- * @see https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
396
- * @throws {Error} This method must be overridden by the derived class.
397
- * @return {string} The tag name associated with the custom element.
398
- * @since 1.7.0
399
- */
400
- static getTag() {
401
- throw new Error(
402
- "The method `getTag()` must be overridden by the derived class.",
403
- );
404
- }
405
-
406
- /**
407
- * The `getCSSStyleSheet()` method returns a `CSSStyleSheet` object that defines the styles for the custom element.
408
- * If the environment does not support the `CSSStyleSheet` constructor, then an object can be built using the provided detour.
409
- *
410
- * If `undefined` is returned, then the shadow root does not receive a stylesheet.
411
- *
412
- * Example usage:
413
- *
414
- * ```js
415
- * class MyElement extends CustomElement {
416
- * static getCSSStyleSheet() {
417
- * const sheet = new CSSStyleSheet();
418
- * sheet.replaceSync("p { color: red; }");
419
- * return sheet;
420
- * }
421
- * }
422
- * ```
423
- *
424
- * If the environment does not support the `CSSStyleSheet` constructor,
425
- * you can use the following workaround to create the stylesheet:
426
- *
427
- * ```js
428
- * const doc = document.implementation.createHTMLDocument('title');
429
- * let style = doc.createElement("style");
430
- * style.innerHTML = "p { color: red; }";
431
- * style.appendChild(document.createTextNode(""));
432
- * doc.head.appendChild(style);
433
- * return doc.styleSheets[0];
434
- * ```
435
- *
436
- * @return {CSSStyleSheet|CSSStyleSheet[]|string|undefined} A `CSSStyleSheet` object or an array of such objects that define the styles for the custom element, or `undefined` if no stylesheet should be applied.
437
- */
438
- static getCSSStyleSheet() {
439
- return undefined;
440
- }
441
-
442
- /**
443
- * attach a new observer
444
- *
445
- * @param {Observer} observer
446
- * @return {CustomElement}
447
- */
448
- attachObserver(observer) {
449
- this[internalSymbol].attachObserver(observer);
450
- return this;
451
- }
452
-
453
- /**
454
- * detach a observer
455
- *
456
- * @param {Observer} observer
457
- * @return {CustomElement}
458
- */
459
- detachObserver(observer) {
460
- this[internalSymbol].detachObserver(observer);
461
- return this;
462
- }
463
-
464
- /**
465
- * @param {Observer} observer
466
- * @return {ProxyObserver}
467
- */
468
- containsObserver(observer) {
469
- return this[internalSymbol].containsObserver(observer);
470
- }
471
-
472
- /**
473
- * nested options can be specified by path `a.b.c`
474
- *
475
- * @param {string} path
476
- * @param {*} defaultValue
477
- * @return {*}
478
- * @since 1.10.0
479
- */
480
- getOption(path, defaultValue = undefined) {
481
- let value;
482
-
483
- try {
484
- value = new Pathfinder(
485
- this[internalSymbol].getRealSubject()["options"],
486
- ).getVia(path);
487
- } catch (e) {}
488
-
489
- if (value === undefined) return defaultValue;
490
- return value;
491
- }
492
-
493
- /**
494
- * Set option and inform elements
495
- *
496
- * @param {string} path
497
- * @param {*} value
498
- * @return {CustomElement}
499
- * @since 1.14.0
500
- */
501
- setOption(path, value) {
502
- new Pathfinder(this[internalSymbol].getSubject()["options"]).setVia(
503
- path,
504
- value,
505
- );
506
- return this;
507
- }
508
-
509
- /**
510
- * @since 1.15.0
511
- * @param {string|object} options
512
- * @return {CustomElement}
513
- */
514
- setOptions(options) {
515
- if (isString(options)) {
516
- options = parseOptionsJSON.call(this, options);
517
- }
518
- // 2024-01-21: remove this.defaults, otherwise it will overwrite
519
- // the current settings that have already been made.
520
- // https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/136
521
- extend(this[internalSymbol].getSubject()["options"], options);
522
-
523
- return this;
524
- }
525
-
526
- /**
527
- * Is called once via the constructor
528
- *
529
- * @return {CustomElement}
530
- * @since 1.8.0
531
- */
532
- [initMethodSymbol]() {
533
- return this;
534
- }
535
-
536
- /**
537
- * This method is called once when the object is equipped with update for the dynamic change of the dom.
538
- * The functions returned here can be used as pipe functions in the template.
539
- *
540
- * In the example, the function `my-transformer` is defined. In the template, you can use it as follows:
541
- *
542
- * ```html
543
- * <my-element
544
- * data-monster-option-transformer="path:my-value | call:my-transformer">
545
- * </my-element>
546
- * ```
547
- *
548
- * The function `my-transformer` is called with the value of `my-value` as a parameter.
549
- *
550
- * ```js
551
- * class MyElement extends CustomElement {
552
- * [updaterTransformerMethodsSymbol]() {
553
- * return {
554
- * "my-transformer": (value) => {
555
- * switch (typeof Wert) {
556
- * case "string":
557
- * return value + "!";
558
- * case "Zahl":
559
- * return value + 1;
560
- * default:
561
- * return value;
562
- * }
563
- * }
564
- * };
565
- * };
566
- * }
567
- * ```
568
- *
569
- * @return {object}
570
- * @since 2.43.0
571
- */
572
- [updaterTransformerMethodsSymbol]() {
573
- return {};
574
- }
575
-
576
- /**
577
- * This method is called once when the object is included in the DOM for the first time. It performs the following actions:
578
- *
579
- * <ol>
580
- * <li>Extracts the options from the attributes and the script tag of the element and sets them.</li>
581
- * <li>Initializes the shadow root and its CSS stylesheet (if specified).</li>
582
- * <li>Initializes the HTML content of the element.</li>
583
- * <li>Initializes the custom elements inside the shadow root and the slotted elements.</li>
584
- * <li>Attaches a mutation observer to observe changes to the attributes of the element.</li>
585
- *
586
- * @return {CustomElement} - The updated custom element.
587
- * @since 1.8.0
588
- */
589
- [assembleMethodSymbol]() {
590
- let elements;
591
- let nodeList;
592
- // Extract options from attributes and set them
593
- const AttributeOptions = getOptionsFromAttributes.call(this);
594
- if (
595
- isObject(AttributeOptions) &&
596
- Object.keys(AttributeOptions).length > 0
597
- ) {
598
- this.setOptions(AttributeOptions);
599
- }
600
- // Extract options from script tag and set them
601
- const ScriptOptions = getOptionsFromScriptTag.call(this);
602
- if (isObject(ScriptOptions) && Object.keys(ScriptOptions).length > 0) {
603
- this.setOptions(ScriptOptions);
604
- }
605
- // Initialize the shadow root and its CSS stylesheet
606
- if (this.getOption("shadowMode", false) !== false) {
607
- try {
608
- initShadowRoot.call(this);
609
- elements = this.shadowRoot.childNodes;
610
- } catch (e) {
611
- addErrorAttribute(this, e);
612
- }
613
- try {
614
- initCSSStylesheet.call(this);
615
- } catch (e) {
616
- addErrorAttribute(this, e);
617
- }
618
- }
619
- // If the elements are not found inside the shadow root, initialize the HTML content of the element
620
- if (!(elements instanceof NodeList)) {
621
- initHtmlContent.call(this);
622
- elements = this.childNodes;
623
- }
624
- // Initialize the custom elements inside the shadow root and the slotted elements
625
- initFromCallbackHost.call(this);
626
- try {
627
- nodeList = new Set([...elements, ...getSlottedElements.call(this)]);
628
- } catch (e) {
629
- nodeList = elements;
630
- }
631
- try {
632
- this[updateCloneDataSymbol] = clone(
633
- this[internalSymbol].getRealSubject()["options"],
634
- );
635
- } catch (e) {
636
- addErrorAttribute(this, e);
637
- }
638
- const cfg = {};
639
- if (this.getOption("eventProcessing") === true) {
640
- cfg.eventProcessing = true;
641
- }
642
- addObjectWithUpdaterToElement.call(
643
- this,
644
- nodeList,
645
- customElementUpdaterLinkSymbol,
646
- this[updateCloneDataSymbol],
647
- cfg,
648
- );
649
- // Attach a mutation observer to observe changes to the attributes of the element
650
- attachAttributeChangeMutationObserver.call(this);
651
-
652
- if (isFunction(this[internalSymbol]?.syncDisabledState)) {
653
- this[internalSymbol].syncDisabledState();
654
- }
655
-
656
- return this;
657
- }
658
-
659
- /**
660
- * You know what you are doing? This function is only for advanced users.
661
- * The result is a clone of the internal data.
662
- *
663
- * @return {*}
664
- */
665
- getInternalUpdateCloneData() {
666
- return clone(this[updateCloneDataSymbol]);
667
- }
668
-
669
- /**
670
- * This method is called every time the element is inserted into the DOM. It checks if the custom element
671
- * has already been initialized and if not, calls the assembleMethod to initialize it.
672
- *
673
- * @return {void}
674
- * @since 1.7.0
675
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/connectedCallback
676
- */
677
- connectedCallback() {
678
- // Check if the object has already been initialized
679
- if (!hasObjectLink(this, customElementUpdaterLinkSymbol)) {
680
- // If not, call the assembleMethod to initialize the object
681
- this[assembleMethodSymbol]();
682
- }
683
- }
684
-
685
- /**
686
- * Called every time the element is removed from the DOM. Useful for running clean up code.
687
- *
688
- * @return {void}
689
- * @since 1.7.0
690
- */
691
- disconnectedCallback() {}
692
-
693
- /**
694
- * The custom element has been moved into a new document (e.g. someone called document.adoptNode(el)).
695
- *
696
- * @return {void}
697
- * @since 1.7.0
698
- */
699
- adoptedCallback() {}
700
-
701
- /**
702
- * Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial
703
- * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes
704
- * property will receive this callback.
705
- *
706
- * @param {string} attrName
707
- * @param {string} oldVal
708
- * @param {string} newVal
709
- * @return {void}
710
- * @since 1.15.0
711
- */
712
- attributeChangedCallback(attrName, oldVal, newVal) {
713
- if (attrName.startsWith("data-monster-option-")) {
714
- setOptionFromAttribute(
715
- this,
716
- attrName,
717
- this[internalSymbol].getSubject()["options"],
718
- );
719
- }
720
-
721
- const callback = this[attributeObserverSymbol]?.[attrName];
722
- if (isFunction(callback)) {
723
- try {
724
- callback.call(this, newVal, oldVal);
725
- } catch (e) {
726
- addErrorAttribute(this, e);
727
- }
728
- }
729
- }
730
-
731
- /**
732
- * Checks if the provided node is part of this component's child nodes,
733
- * including those within the shadow root, if present.
734
- *
735
- * @param {Node} node - The node to check for within this component's child nodes.
736
- * @return {boolean} Returns true if the given node is found, otherwise false.
737
- * @throws {TypeError} value is not an instance of
738
- * @since 1.19.0
739
- */
740
- hasNode(node) {
741
- if (containChildNode.call(this, validateInstance(node, Node))) {
742
- return true;
743
- }
744
-
745
- if (!(this.shadowRoot instanceof ShadowRoot)) {
746
- return false;
747
- }
748
-
749
- return containChildNode.call(this.shadowRoot, node);
750
- }
751
-
752
- /**
753
- * Invokes a callback function with the given name and arguments.
754
- *
755
- * @param {string} name - The name of the callback to be executed.
756
- * @param {Array} args - An array of arguments to be passed to the callback function.
757
- * @return {*} The result of the callback function execution.
758
- */
759
- callCallback(name, args) {
760
- return callControlCallback.call(this, name, ...args);
761
- }
188
+ /**
189
+ * A new object is created. First, the `initOptions` method is called. Here the
190
+ * options can be defined in derived classes. Subsequently, the shadowRoot is initialized.
191
+ *
192
+ * IMPORTANT: CustomControls instances are not created via the constructor, but either via a tag in the HTML or via <code>document.createElement()</code>.
193
+ *
194
+ * @throws {Error} the option attribute does not contain a valid JSON definition.
195
+ */
196
+ constructor() {
197
+ super();
198
+
199
+ this[attributeObserverSymbol] = {};
200
+
201
+ const options = initOptionsFromAttributes(this, extend({}, this.defaults));
202
+ if (!isObject(options)) {
203
+ throw new Error(
204
+ `The options are not defined correctly in the ${this.getTag()} element.`,
205
+ );
206
+ }
207
+
208
+ if (this.customization instanceof Map) {
209
+ const pathfinder = new Pathfinder(options);
210
+ this.customization.forEach((value, key) => {
211
+ if (key === undefined || key === null || key === "") {
212
+ return;
213
+ }
214
+ pathfinder.setVia(key, value);
215
+ });
216
+ }
217
+
218
+ this[internalSymbol] = new ProxyObserver({ options });
219
+ this[initMethodSymbol]();
220
+ initOptionObserver.call(this);
221
+ this[scriptHostElementSymbol] = [];
222
+ }
223
+
224
+ /**
225
+ * This method is called by the `instanceof` operator.
226
+ *
227
+ * @return {symbol}
228
+ * @since 2.1.0
229
+ */
230
+ static get [instanceSymbol]() {
231
+ return Symbol.for("@schukai/monster/dom/custom-element@@instance");
232
+ }
233
+
234
+ /**
235
+ * This method determines which attributes are to be
236
+ * monitored by `attributeChangedCallback()`. Unfortunately, this method is static.
237
+ * Therefore, the `observedAttributes` property cannot be changed during runtime.
238
+ *
239
+ * @return {string[]}
240
+ * @since 1.15.0
241
+ */
242
+ static get observedAttributes() {
243
+ return [];
244
+ }
245
+
246
+ /**
247
+ *
248
+ * @param attribute
249
+ * @param callback
250
+ * @return {CustomElement}
251
+ */
252
+ addAttributeObserver(attribute, callback) {
253
+ validateFunction(callback);
254
+ this[attributeObserverSymbol][attribute] = callback;
255
+ return this;
256
+ }
257
+
258
+ /**
259
+ *
260
+ * @param attribute
261
+ * @return {CustomElement}
262
+ */
263
+ removeAttributeObserver(attribute) {
264
+ delete this[attributeObserverSymbol][attribute];
265
+ return this;
266
+ }
267
+
268
+ /**
269
+ * The `customization` property allows overwriting the defaults.
270
+ * Unlike the defaults that expect an object, the customization is a Map.
271
+ * This also allows overwriting individual values in a deeper structure
272
+ * without having to redefine the entire structure and thus changing the defaults.
273
+ * @returns {Map}
274
+ */
275
+ get customization() {
276
+ return new Map();
277
+ }
278
+
279
+ /**
280
+ * The `defaults` property defines the default values for a control. If you want to override these,
281
+ * you can use various methods, which are described in the documentation available at
282
+ * {@link https://monsterjs.orgendocconfigurate-a-monster-control}.
283
+ *
284
+ * The individual configuration values are listed below:
285
+ *
286
+ * More information about the shadowRoot can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow),
287
+ * in the [HTML Standard](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements) or in the [WHATWG Wiki](https://wiki.whatwg.org/wiki/Custom_Elements).
288
+ *
289
+ * More information about the template element can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).
290
+ *
291
+ * More information about the slot element can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot).
292
+ *
293
+ * @property {boolean} disabled=false Specifies whether the control is disabled. When present, it makes the element non-mutable, non-focusable, and non-submittable with the form.
294
+ * @property {string} shadowMode=open Specifies the mode of the shadow root. When set to `open`, elements in the shadow root are accessible from JavaScript outside the root, while setting it to `closed` denies access to the root's nodes from JavaScript outside it.
295
+ * @property {Boolean} delegatesFocus=true Specifies the behavior of the control with respect to focusability. When set to `true`, it mitigates custom element issues around focusability. When a non-focusable part of the shadow DOM is clicked, the first focusable part is given focus, and the shadow host is given any available :focus styling.
296
+ * @property {Object} templates Specifies the templates used by the control.
297
+ * @property {string} templates.main=undefined Specifies the main template used by the control.
298
+ * @property {Object} templateMapping Specifies the mapping of templates.
299
+ * @property {Object} templateFormatter Specifies the formatter for the templates.
300
+ * @property {Object} templateFormatter.marker Specifies the marker for the templates.
301
+ * @property {Function} templateFormatter.marker.open=null Specifies the opening marker for the templates.
302
+ * @property {Function} templateFormatter.marker.close=null Specifies the closing marker for the templates.
303
+ * @property {Boolean} templateFormatter.i18n=false Specifies whether the templates should be formatted with i18n.
304
+ * @property {Boolean} eventProcessing=false Specifies whether the control processes events.
305
+ * @since 1.8.0
306
+ */
307
+ get defaults() {
308
+ return {
309
+ disabled: false,
310
+ shadowMode: "open",
311
+ delegatesFocus: true,
312
+ templates: {
313
+ main: undefined,
314
+ },
315
+ templateMapping: {},
316
+ templateFormatter: {
317
+ marker: {
318
+ open: null,
319
+ close: null,
320
+ },
321
+ i18n: false,
322
+ },
323
+
324
+ eventProcessing: false,
325
+ };
326
+ }
327
+
328
+ /**
329
+ * This method updates the labels of the element.
330
+ * The labels are defined in the option object.
331
+ * The key of the label is used to retrieve the translation from the document.
332
+ * If the translation is different from the label, the label is updated.
333
+ *
334
+ * Before you can use this method, you must have loaded the translations.
335
+ *
336
+ * @return {CustomElement}
337
+ * @throws {Error} Cannot find an element with translations. Add a translation object to the document.
338
+ */
339
+ updateI18n() {
340
+ let translations;
341
+
342
+ try {
343
+ translations = getDocumentTranslations();
344
+ } catch (e) {
345
+ addErrorAttribute(this, e);
346
+ return this;
347
+ }
348
+
349
+ if (!translations) {
350
+ return this;
351
+ }
352
+
353
+ const labels = this.getOption("labels");
354
+ if (!(isObject(labels) || isIterable(labels))) {
355
+ return this;
356
+ }
357
+
358
+ for (const key in labels) {
359
+ const def = labels[key];
360
+
361
+ if (isString(def)) {
362
+ const text = translations.getText(key, def);
363
+ if (text !== def) {
364
+ this.setOption(`labels.${key}`, text);
365
+ }
366
+ continue;
367
+ } else if (isObject(def)) {
368
+ for (const k in def) {
369
+ const d = def[k];
370
+
371
+ const text = translations.getPluralRuleText(key, k, d);
372
+ if (!isString(text)) {
373
+ throw new Error("Invalid labels definition");
374
+ }
375
+ if (text !== d) {
376
+ this.setOption(`labels.${key}.${k}`, text);
377
+ }
378
+ }
379
+ continue;
380
+ }
381
+
382
+ throw new Error("Invalid labels definition");
383
+ }
384
+ return this;
385
+ }
386
+
387
+ /**
388
+ * The `getTag()` method returns the tag name associated with the custom element. This method should be overwritten
389
+ * by the derived class.
390
+ *
391
+ * Note that there is no check on the name of the tag in this class. It is the responsibility of
392
+ * the developer to assign an appropriate tag name. If the name is not valid, the
393
+ * `registerCustomElement()` method will issue an error.
394
+ *
395
+ * @see https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
396
+ * @throws {Error} This method must be overridden by the derived class.
397
+ * @return {string} The tag name associated with the custom element.
398
+ * @since 1.7.0
399
+ */
400
+ static getTag() {
401
+ throw new Error(
402
+ "The method `getTag()` must be overridden by the derived class.",
403
+ );
404
+ }
405
+
406
+ /**
407
+ * The `getCSSStyleSheet()` method returns a `CSSStyleSheet` object that defines the styles for the custom element.
408
+ * If the environment does not support the `CSSStyleSheet` constructor, then an object can be built using the provided detour.
409
+ *
410
+ * If `undefined` is returned, then the shadow root does not receive a stylesheet.
411
+ *
412
+ * Example usage:
413
+ *
414
+ * ```js
415
+ * class MyElement extends CustomElement {
416
+ * static getCSSStyleSheet() {
417
+ * const sheet = new CSSStyleSheet();
418
+ * sheet.replaceSync("p { color: red; }");
419
+ * return sheet;
420
+ * }
421
+ * }
422
+ * ```
423
+ *
424
+ * If the environment does not support the `CSSStyleSheet` constructor,
425
+ * you can use the following workaround to create the stylesheet:
426
+ *
427
+ * ```js
428
+ * const doc = document.implementation.createHTMLDocument('title');
429
+ * let style = doc.createElement("style");
430
+ * style.innerHTML = "p { color: red; }";
431
+ * style.appendChild(document.createTextNode(""));
432
+ * doc.head.appendChild(style);
433
+ * return doc.styleSheets[0];
434
+ * ```
435
+ *
436
+ * @return {CSSStyleSheet|CSSStyleSheet[]|string|undefined} A `CSSStyleSheet` object or an array of such objects that define the styles for the custom element, or `undefined` if no stylesheet should be applied.
437
+ */
438
+ static getCSSStyleSheet() {
439
+ return undefined;
440
+ }
441
+
442
+ /**
443
+ * attach a new observer
444
+ *
445
+ * @param {Observer} observer
446
+ * @return {CustomElement}
447
+ */
448
+ attachObserver(observer) {
449
+ this[internalSymbol].attachObserver(observer);
450
+ return this;
451
+ }
452
+
453
+ /**
454
+ * detach a observer
455
+ *
456
+ * @param {Observer} observer
457
+ * @return {CustomElement}
458
+ */
459
+ detachObserver(observer) {
460
+ this[internalSymbol].detachObserver(observer);
461
+ return this;
462
+ }
463
+
464
+ /**
465
+ * @param {Observer} observer
466
+ * @return {ProxyObserver}
467
+ */
468
+ containsObserver(observer) {
469
+ return this[internalSymbol].containsObserver(observer);
470
+ }
471
+
472
+ /**
473
+ * nested options can be specified by path `a.b.c`
474
+ *
475
+ * @param {string} path
476
+ * @param {*} defaultValue
477
+ * @return {*}
478
+ * @since 1.10.0
479
+ */
480
+ getOption(path, defaultValue = undefined) {
481
+ let value;
482
+
483
+ try {
484
+ value = new Pathfinder(
485
+ this[internalSymbol].getRealSubject()["options"],
486
+ ).getVia(path);
487
+ } catch (e) {}
488
+
489
+ if (value === undefined) return defaultValue;
490
+ return value;
491
+ }
492
+
493
+ /**
494
+ * Set option and inform elements
495
+ *
496
+ * @param {string} path
497
+ * @param {*} value
498
+ * @return {CustomElement}
499
+ * @since 1.14.0
500
+ */
501
+ setOption(path, value) {
502
+ new Pathfinder(this[internalSymbol].getSubject()["options"]).setVia(
503
+ path,
504
+ value,
505
+ );
506
+ return this;
507
+ }
508
+
509
+ /**
510
+ * @since 1.15.0
511
+ * @param {string|object} options
512
+ * @return {CustomElement}
513
+ */
514
+ setOptions(options) {
515
+ if (isString(options)) {
516
+ options = parseOptionsJSON.call(this, options);
517
+ }
518
+ // 2024-01-21: remove this.defaults, otherwise it will overwrite
519
+ // the current settings that have already been made.
520
+ // https://gitlab.schukai.com/oss/libraries/javascript/monster/-/issues/136
521
+ extend(this[internalSymbol].getSubject()["options"], options);
522
+
523
+ return this;
524
+ }
525
+
526
+ /**
527
+ * Is called once via the constructor
528
+ *
529
+ * @return {CustomElement}
530
+ * @since 1.8.0
531
+ */
532
+ [initMethodSymbol]() {
533
+ return this;
534
+ }
535
+
536
+ /**
537
+ * This method is called once when the object is equipped with update for the dynamic change of the dom.
538
+ * The functions returned here can be used as pipe functions in the template.
539
+ *
540
+ * In the example, the function `my-transformer` is defined. In the template, you can use it as follows:
541
+ *
542
+ * ```html
543
+ * <my-element
544
+ * data-monster-option-transformer="path:my-value | call:my-transformer">
545
+ * </my-element>
546
+ * ```
547
+ *
548
+ * The function `my-transformer` is called with the value of `my-value` as a parameter.
549
+ *
550
+ * ```js
551
+ * class MyElement extends CustomElement {
552
+ * [updaterTransformerMethodsSymbol]() {
553
+ * return {
554
+ * "my-transformer": (value) => {
555
+ * switch (typeof Wert) {
556
+ * case "string":
557
+ * return value + "!";
558
+ * case "Zahl":
559
+ * return value + 1;
560
+ * default:
561
+ * return value;
562
+ * }
563
+ * }
564
+ * };
565
+ * };
566
+ * }
567
+ * ```
568
+ *
569
+ * @return {object}
570
+ * @since 2.43.0
571
+ */
572
+ [updaterTransformerMethodsSymbol]() {
573
+ return {};
574
+ }
575
+
576
+ /**
577
+ * This method is called once when the object is included in the DOM for the first time. It performs the following actions:
578
+ *
579
+ * <ol>
580
+ * <li>Extracts the options from the attributes and the script tag of the element and sets them.</li>
581
+ * <li>Initializes the shadow root and its CSS stylesheet (if specified).</li>
582
+ * <li>Initializes the HTML content of the element.</li>
583
+ * <li>Initializes the custom elements inside the shadow root and the slotted elements.</li>
584
+ * <li>Attaches a mutation observer to observe changes to the attributes of the element.</li>
585
+ *
586
+ * @return {CustomElement} - The updated custom element.
587
+ * @since 1.8.0
588
+ */
589
+ [assembleMethodSymbol]() {
590
+ let elements;
591
+ let nodeList;
592
+ // Extract options from attributes and set them
593
+ const AttributeOptions = getOptionsFromAttributes.call(this);
594
+ if (
595
+ isObject(AttributeOptions) &&
596
+ Object.keys(AttributeOptions).length > 0
597
+ ) {
598
+ this.setOptions(AttributeOptions);
599
+ }
600
+ // Extract options from script tag and set them
601
+ const ScriptOptions = getOptionsFromScriptTag.call(this);
602
+ if (isObject(ScriptOptions) && Object.keys(ScriptOptions).length > 0) {
603
+ this.setOptions(ScriptOptions);
604
+ }
605
+ // Initialize the shadow root and its CSS stylesheet
606
+ if (this.getOption("shadowMode", false) !== false) {
607
+ try {
608
+ initShadowRoot.call(this);
609
+ elements = this.shadowRoot.childNodes;
610
+ } catch (e) {
611
+ addErrorAttribute(this, e);
612
+ }
613
+ try {
614
+ initCSSStylesheet.call(this);
615
+ } catch (e) {
616
+ addErrorAttribute(this, e);
617
+ }
618
+ }
619
+ // If the elements are not found inside the shadow root, initialize the HTML content of the element
620
+ if (!(elements instanceof NodeList)) {
621
+ initHtmlContent.call(this);
622
+ elements = this.childNodes;
623
+ }
624
+ // Initialize the custom elements inside the shadow root and the slotted elements
625
+ initFromCallbackHost.call(this);
626
+ try {
627
+ nodeList = new Set([...elements, ...getSlottedElements.call(this)]);
628
+ } catch (e) {
629
+ nodeList = elements;
630
+ }
631
+ try {
632
+ this[updateCloneDataSymbol] = clone(
633
+ this[internalSymbol].getRealSubject()["options"],
634
+ );
635
+ } catch (e) {
636
+ addErrorAttribute(this, e);
637
+ }
638
+ const cfg = {};
639
+ if (this.getOption("eventProcessing") === true) {
640
+ cfg.eventProcessing = true;
641
+ }
642
+ addObjectWithUpdaterToElement.call(
643
+ this,
644
+ nodeList,
645
+ customElementUpdaterLinkSymbol,
646
+ this[updateCloneDataSymbol],
647
+ cfg,
648
+ );
649
+ // Attach a mutation observer to observe changes to the attributes of the element
650
+ attachAttributeChangeMutationObserver.call(this);
651
+
652
+ if (isFunction(this[internalSymbol]?.syncDisabledState)) {
653
+ this[internalSymbol].syncDisabledState();
654
+ }
655
+
656
+ return this;
657
+ }
658
+
659
+ /**
660
+ * You know what you are doing? This function is only for advanced users.
661
+ * The result is a clone of the internal data.
662
+ *
663
+ * @return {*}
664
+ */
665
+ getInternalUpdateCloneData() {
666
+ return clone(this[updateCloneDataSymbol]);
667
+ }
668
+
669
+ /**
670
+ * This method is called every time the element is inserted into the DOM. It checks if the custom element
671
+ * has already been initialized and if not, calls the assembleMethod to initialize it.
672
+ *
673
+ * @return {void}
674
+ * @since 1.7.0
675
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/connectedCallback
676
+ */
677
+ connectedCallback() {
678
+ // Check if the object has already been initialized
679
+ if (!hasObjectLink(this, customElementUpdaterLinkSymbol)) {
680
+ // If not, call the assembleMethod to initialize the object
681
+ this[assembleMethodSymbol]();
682
+ }
683
+ }
684
+
685
+ /**
686
+ * Called every time the element is removed from the DOM. Useful for running clean up code.
687
+ *
688
+ * @return {void}
689
+ * @since 1.7.0
690
+ */
691
+ disconnectedCallback() {}
692
+
693
+ /**
694
+ * The custom element has been moved into a new document (e.g. someone called document.adoptNode(el)).
695
+ *
696
+ * @return {void}
697
+ * @since 1.7.0
698
+ */
699
+ adoptedCallback() {}
700
+
701
+ /**
702
+ * Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial
703
+ * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes
704
+ * property will receive this callback.
705
+ *
706
+ * @param {string} attrName
707
+ * @param {string} oldVal
708
+ * @param {string} newVal
709
+ * @return {void}
710
+ * @since 1.15.0
711
+ */
712
+ attributeChangedCallback(attrName, oldVal, newVal) {
713
+ if (attrName.startsWith("data-monster-option-")) {
714
+ setOptionFromAttribute(
715
+ this,
716
+ attrName,
717
+ this[internalSymbol].getSubject()["options"],
718
+ );
719
+ }
720
+
721
+ const callback = this[attributeObserverSymbol]?.[attrName];
722
+ if (isFunction(callback)) {
723
+ try {
724
+ callback.call(this, newVal, oldVal);
725
+ } catch (e) {
726
+ addErrorAttribute(this, e);
727
+ }
728
+ }
729
+ }
730
+
731
+ /**
732
+ * Checks if the provided node is part of this component's child nodes,
733
+ * including those within the shadow root, if present.
734
+ *
735
+ * @param {Node} node - The node to check for within this component's child nodes.
736
+ * @return {boolean} Returns true if the given node is found, otherwise false.
737
+ * @throws {TypeError} value is not an instance of
738
+ * @since 1.19.0
739
+ */
740
+ hasNode(node) {
741
+ if (containChildNode.call(this, validateInstance(node, Node))) {
742
+ return true;
743
+ }
744
+
745
+ if (!(this.shadowRoot instanceof ShadowRoot)) {
746
+ return false;
747
+ }
748
+
749
+ return containChildNode.call(this.shadowRoot, node);
750
+ }
751
+
752
+ /**
753
+ * Invokes a callback function with the given name and arguments.
754
+ *
755
+ * @param {string} name - The name of the callback to be executed.
756
+ * @param {Array} args - An array of arguments to be passed to the callback function.
757
+ * @return {*} The result of the callback function execution.
758
+ */
759
+ callCallback(name, args) {
760
+ return callControlCallback.call(this, name, ...args);
761
+ }
762
762
  }
763
763
 
764
764
  /**
@@ -767,46 +767,46 @@ class CustomElement extends HTMLElement {
767
767
  * @return {any}
768
768
  */
769
769
  function callControlCallback(callBackFunctionName, ...args) {
770
- if (!isString(callBackFunctionName) || callBackFunctionName === "") {
771
- return;
772
- }
773
-
774
- if (callBackFunctionName in this) {
775
- return this[callBackFunctionName](this, ...args);
776
- }
777
-
778
- if (!this.hasAttribute(ATTRIBUTE_SCRIPT_HOST)) {
779
- return;
780
- }
781
-
782
- if (this[scriptHostElementSymbol].length === 0) {
783
- const targetId = this.getAttribute(ATTRIBUTE_SCRIPT_HOST);
784
- if (!targetId) {
785
- return;
786
- }
787
-
788
- const list = targetId.split(",");
789
- for (const id of list) {
790
- const host = findElementWithIdUpwards(this, targetId);
791
- if (!(host instanceof HTMLElement)) {
792
- continue;
793
- }
794
-
795
- this[scriptHostElementSymbol].push(host);
796
- }
797
- }
798
-
799
- for (const host of this[scriptHostElementSymbol]) {
800
- if (callBackFunctionName in host) {
801
- try {
802
- return host[callBackFunctionName](this, ...args);
803
- } catch (e) {
804
- addErrorAttribute(this, e);
805
- }
806
- }
807
- }
808
-
809
- addErrorAttribute(this, `callback ${callBackFunctionName} not found`);
770
+ if (!isString(callBackFunctionName) || callBackFunctionName === "") {
771
+ return;
772
+ }
773
+
774
+ if (callBackFunctionName in this) {
775
+ return this[callBackFunctionName](this, ...args);
776
+ }
777
+
778
+ if (!this.hasAttribute(ATTRIBUTE_SCRIPT_HOST)) {
779
+ return;
780
+ }
781
+
782
+ if (this[scriptHostElementSymbol].length === 0) {
783
+ const targetId = this.getAttribute(ATTRIBUTE_SCRIPT_HOST);
784
+ if (!targetId) {
785
+ return;
786
+ }
787
+
788
+ const list = targetId.split(",");
789
+ for (const id of list) {
790
+ const host = findElementWithIdUpwards(this, targetId);
791
+ if (!(host instanceof HTMLElement)) {
792
+ continue;
793
+ }
794
+
795
+ this[scriptHostElementSymbol].push(host);
796
+ }
797
+ }
798
+
799
+ for (const host of this[scriptHostElementSymbol]) {
800
+ if (callBackFunctionName in host) {
801
+ try {
802
+ return host[callBackFunctionName](this, ...args);
803
+ } catch (e) {
804
+ addErrorAttribute(this, e);
805
+ }
806
+ }
807
+ }
808
+
809
+ addErrorAttribute(this, `callback ${callBackFunctionName} not found`);
810
810
  }
811
811
 
812
812
  /**
@@ -823,16 +823,16 @@ function callControlCallback(callBackFunctionName, ...args) {
823
823
  * @since 1.8.0
824
824
  */
825
825
  function initFromCallbackHost() {
826
- // Set the default callback function name
827
- let callBackFunctionName = initControlCallbackName;
826
+ // Set the default callback function name
827
+ let callBackFunctionName = initControlCallbackName;
828
828
 
829
- // If the `data-monster-option-callback` attribute is set, use its value as the callback function name
830
- if (this.hasAttribute(ATTRIBUTE_INIT_CALLBACK)) {
831
- callBackFunctionName = this.getAttribute(ATTRIBUTE_INIT_CALLBACK);
832
- }
829
+ // If the `data-monster-option-callback` attribute is set, use its value as the callback function name
830
+ if (this.hasAttribute(ATTRIBUTE_INIT_CALLBACK)) {
831
+ callBackFunctionName = this.getAttribute(ATTRIBUTE_INIT_CALLBACK);
832
+ }
833
833
 
834
- // Call the callback function with the element as a parameter if it exists
835
- callControlCallback.call(this, callBackFunctionName);
834
+ // Call the callback function with the element as a parameter if it exists
835
+ callControlCallback.call(this, callBackFunctionName);
836
836
  }
837
837
 
838
838
  /**
@@ -842,35 +842,34 @@ function initFromCallbackHost() {
842
842
  * @this CustomElement
843
843
  */
844
844
  function attachAttributeChangeMutationObserver() {
845
- const self = this;
846
-
847
- if (typeof self[attributeMutationObserverSymbol] !== "undefined") {
848
- return;
849
- }
850
-
851
- self[attributeMutationObserverSymbol] = new MutationObserver(function (
852
- mutations,
853
- observer,
854
- ) {
855
- for (const mutation of mutations) {
856
- if (mutation.type === "attributes") {
857
- self.attributeChangedCallback(
858
- mutation.attributeName,
859
- mutation.oldValue,
860
- mutation.target.getAttribute(mutation.attributeName),
861
- );
862
- }
863
- }
864
- });
865
-
866
- try {
867
- self[attributeMutationObserverSymbol].observe(self, {
868
- attributes: true,
869
- attributeOldValue: true,
870
- });
871
- } catch (e) {
872
- addErrorAttribute(self, e);
873
- }
845
+ const self = this;
846
+
847
+ if (typeof self[attributeMutationObserverSymbol] !== "undefined") {
848
+ return;
849
+ }
850
+
851
+ self[attributeMutationObserverSymbol] = new MutationObserver(
852
+ function (mutations, observer) {
853
+ for (const mutation of mutations) {
854
+ if (mutation.type === "attributes") {
855
+ self.attributeChangedCallback(
856
+ mutation.attributeName,
857
+ mutation.oldValue,
858
+ mutation.target.getAttribute(mutation.attributeName),
859
+ );
860
+ }
861
+ }
862
+ },
863
+ );
864
+
865
+ try {
866
+ self[attributeMutationObserverSymbol].observe(self, {
867
+ attributes: true,
868
+ attributeOldValue: true,
869
+ });
870
+ } catch (e) {
871
+ addErrorAttribute(self, e);
872
+ }
874
873
  }
875
874
 
876
875
  /**
@@ -880,19 +879,19 @@ function attachAttributeChangeMutationObserver() {
880
879
  * @return {boolean}
881
880
  */
882
881
  function containChildNode(node) {
883
- if (this.contains(node)) {
884
- return true;
885
- }
882
+ if (this.contains(node)) {
883
+ return true;
884
+ }
886
885
 
887
- for (const [, e] of Object.entries(this.childNodes)) {
888
- if (e.contains(node)) {
889
- return true;
890
- }
886
+ for (const [, e] of Object.entries(this.childNodes)) {
887
+ if (e.contains(node)) {
888
+ return true;
889
+ }
891
890
 
892
- containChildNode.call(e, node);
893
- }
891
+ containChildNode.call(e, node);
892
+ }
894
893
 
895
- return false;
894
+ return false;
896
895
  }
897
896
 
898
897
  /**
@@ -902,93 +901,93 @@ function containChildNode(node) {
902
901
  * @this CustomElement
903
902
  */
904
903
  function initOptionObserver() {
905
- const self = this;
906
-
907
- self[internalSymbol].lastDisabledValue = undefined;
908
-
909
- const syncDisabledState = () => {
910
- const flag = self.getOption("disabled", false);
911
-
912
- if (flag === self[internalSymbol].lastDisabledValue) {
913
- return;
914
- }
915
-
916
- if (!(self.shadowRoot instanceof ShadowRoot) && !self.childNodes.length) {
917
- return;
918
- }
919
-
920
- self[internalSymbol].lastDisabledValue = flag;
921
-
922
- const query =
923
- "button, command, fieldset, keygen, optgroup, option, select, textarea, input, [data-monster-objectlink]";
924
-
925
- let elements = [];
926
- if (self.shadowRoot instanceof ShadowRoot) {
927
- elements = self.shadowRoot.querySelectorAll(query);
928
- }
929
-
930
- let nodeList;
931
- try {
932
- const baseElements =
933
- elements.length > 0 ? elements : self.querySelectorAll(query);
934
- nodeList = new Set([
935
- ...baseElements,
936
- ...getSlottedElements.call(self, query),
937
- ]);
938
- } catch (e) {
939
- nodeList = elements;
940
- }
941
-
942
- for (const element of [...nodeList]) {
943
- if (flag === true) {
944
- element.setAttribute(ATTRIBUTE_DISABLED, "");
945
- } else {
946
- element.removeAttribute(ATTRIBUTE_DISABLED);
947
- }
948
- }
949
- };
950
-
951
- self.attachObserver(new Observer(syncDisabledState));
952
-
953
- self[internalSymbol].syncDisabledState = syncDisabledState;
954
-
955
- self.attachObserver(
956
- new Observer(function () {
957
- if (!hasObjectLink(self, customElementUpdaterLinkSymbol)) {
958
- return;
959
- }
960
- const updaters = getLinkedObjects(self, customElementUpdaterLinkSymbol);
961
-
962
- for (const list of updaters) {
963
- for (const updater of list) {
964
- const d = clone(self[internalSymbol].getRealSubject()["options"]);
965
- Object.assign(updater.getSubject(), d);
966
- }
967
- }
968
- }),
969
- );
970
-
971
- self[attributeObserverSymbol][ATTRIBUTE_DISABLED] = () => {
972
- if (self.hasAttribute(ATTRIBUTE_DISABLED)) {
973
- self.setOption(ATTRIBUTE_DISABLED, true);
974
- } else {
975
- self.setOption(ATTRIBUTE_DISABLED, false);
976
- }
977
- };
978
-
979
- self[attributeObserverSymbol][ATTRIBUTE_OPTIONS] = () => {
980
- const options = getOptionsFromAttributes.call(self);
981
- if (isObject(options) && Object.keys(options).length > 0) {
982
- self.setOptions(options);
983
- }
984
- };
985
-
986
- self[attributeObserverSymbol][ATTRIBUTE_OPTIONS_SELECTOR] = () => {
987
- const options = getOptionsFromScriptTag.call(self);
988
- if (isObject(options) && Object.keys(options).length > 0) {
989
- self.setOptions(options);
990
- }
991
- };
904
+ const self = this;
905
+
906
+ self[internalSymbol].lastDisabledValue = undefined;
907
+
908
+ const syncDisabledState = () => {
909
+ const flag = self.getOption("disabled", false);
910
+
911
+ if (flag === self[internalSymbol].lastDisabledValue) {
912
+ return;
913
+ }
914
+
915
+ if (!(self.shadowRoot instanceof ShadowRoot) && !self.childNodes.length) {
916
+ return;
917
+ }
918
+
919
+ self[internalSymbol].lastDisabledValue = flag;
920
+
921
+ const query =
922
+ "button, command, fieldset, keygen, optgroup, option, select, textarea, input, [data-monster-objectlink]";
923
+
924
+ let elements = [];
925
+ if (self.shadowRoot instanceof ShadowRoot) {
926
+ elements = self.shadowRoot.querySelectorAll(query);
927
+ }
928
+
929
+ let nodeList;
930
+ try {
931
+ const baseElements =
932
+ elements.length > 0 ? elements : self.querySelectorAll(query);
933
+ nodeList = new Set([
934
+ ...baseElements,
935
+ ...getSlottedElements.call(self, query),
936
+ ]);
937
+ } catch (e) {
938
+ nodeList = elements;
939
+ }
940
+
941
+ for (const element of [...nodeList]) {
942
+ if (flag === true) {
943
+ element.setAttribute(ATTRIBUTE_DISABLED, "");
944
+ } else {
945
+ element.removeAttribute(ATTRIBUTE_DISABLED);
946
+ }
947
+ }
948
+ };
949
+
950
+ self.attachObserver(new Observer(syncDisabledState));
951
+
952
+ self[internalSymbol].syncDisabledState = syncDisabledState;
953
+
954
+ self.attachObserver(
955
+ new Observer(function () {
956
+ if (!hasObjectLink(self, customElementUpdaterLinkSymbol)) {
957
+ return;
958
+ }
959
+ const updaters = getLinkedObjects(self, customElementUpdaterLinkSymbol);
960
+
961
+ for (const list of updaters) {
962
+ for (const updater of list) {
963
+ const d = clone(self[internalSymbol].getRealSubject()["options"]);
964
+ Object.assign(updater.getSubject(), d);
965
+ }
966
+ }
967
+ }),
968
+ );
969
+
970
+ self[attributeObserverSymbol][ATTRIBUTE_DISABLED] = () => {
971
+ if (self.hasAttribute(ATTRIBUTE_DISABLED)) {
972
+ self.setOption(ATTRIBUTE_DISABLED, true);
973
+ } else {
974
+ self.setOption(ATTRIBUTE_DISABLED, false);
975
+ }
976
+ };
977
+
978
+ self[attributeObserverSymbol][ATTRIBUTE_OPTIONS] = () => {
979
+ const options = getOptionsFromAttributes.call(self);
980
+ if (isObject(options) && Object.keys(options).length > 0) {
981
+ self.setOptions(options);
982
+ }
983
+ };
984
+
985
+ self[attributeObserverSymbol][ATTRIBUTE_OPTIONS_SELECTOR] = () => {
986
+ const options = getOptionsFromScriptTag.call(self);
987
+ if (isObject(options) && Object.keys(options).length > 0) {
988
+ self.setOptions(options);
989
+ }
990
+ };
992
991
  }
993
992
 
994
993
  /**
@@ -997,35 +996,35 @@ function initOptionObserver() {
997
996
  * @throws {TypeError} value is not an object
998
997
  */
999
998
  function getOptionsFromScriptTag() {
1000
- if (!this.hasAttribute(ATTRIBUTE_OPTIONS_SELECTOR)) {
1001
- return {};
1002
- }
1003
-
1004
- const node = document.querySelector(
1005
- this.getAttribute(ATTRIBUTE_OPTIONS_SELECTOR),
1006
- );
1007
- if (!(node instanceof HTMLScriptElement)) {
1008
- addErrorAttribute(
1009
- this,
1010
- `the selector ${ATTRIBUTE_OPTIONS_SELECTOR} for options was specified (${this.getAttribute(
1011
- ATTRIBUTE_OPTIONS_SELECTOR,
1012
- )}) but not found.`,
1013
- );
1014
- return {};
1015
- }
1016
-
1017
- let obj = {};
1018
-
1019
- try {
1020
- obj = parseOptionsJSON.call(this, node.textContent.trim());
1021
- } catch (e) {
1022
- addErrorAttribute(
1023
- this,
1024
- `when analyzing the configuration from the script tag there was an error. ${e}`,
1025
- );
1026
- }
1027
-
1028
- return obj;
999
+ if (!this.hasAttribute(ATTRIBUTE_OPTIONS_SELECTOR)) {
1000
+ return {};
1001
+ }
1002
+
1003
+ const node = document.querySelector(
1004
+ this.getAttribute(ATTRIBUTE_OPTIONS_SELECTOR),
1005
+ );
1006
+ if (!(node instanceof HTMLScriptElement)) {
1007
+ addErrorAttribute(
1008
+ this,
1009
+ `the selector ${ATTRIBUTE_OPTIONS_SELECTOR} for options was specified (${this.getAttribute(
1010
+ ATTRIBUTE_OPTIONS_SELECTOR,
1011
+ )}) but not found.`,
1012
+ );
1013
+ return {};
1014
+ }
1015
+
1016
+ let obj = {};
1017
+
1018
+ try {
1019
+ obj = parseOptionsJSON.call(this, node.textContent.trim());
1020
+ } catch (e) {
1021
+ addErrorAttribute(
1022
+ this,
1023
+ `when analyzing the configuration from the script tag there was an error. ${e}`,
1024
+ );
1025
+ }
1026
+
1027
+ return obj;
1029
1028
  }
1030
1029
 
1031
1030
  /**
@@ -1033,29 +1032,29 @@ function getOptionsFromScriptTag() {
1033
1032
  * @return {object}
1034
1033
  */
1035
1034
  function getOptionsFromAttributes() {
1036
- if (
1037
- this.hasAttribute(ATTRIBUTE_DISABLED) &&
1038
- this.getAttribute(ATTRIBUTE_DISABLED) !== null
1039
- ) {
1040
- this.setOption(ATTRIBUTE_DISABLED, true);
1041
- } else {
1042
- this.setOption(ATTRIBUTE_DISABLED, undefined);
1043
- }
1044
-
1045
- if (this.hasAttribute(ATTRIBUTE_OPTIONS)) {
1046
- try {
1047
- return parseOptionsJSON.call(this, this.getAttribute(ATTRIBUTE_OPTIONS));
1048
- } catch (e) {
1049
- addErrorAttribute(
1050
- this,
1051
- `the options attribute ${ATTRIBUTE_OPTIONS} does not contain a valid json definition (actual: ${this.getAttribute(
1052
- ATTRIBUTE_OPTIONS,
1053
- )}).${e}`,
1054
- );
1055
- }
1056
- }
1057
-
1058
- return {};
1035
+ if (
1036
+ this.hasAttribute(ATTRIBUTE_DISABLED) &&
1037
+ this.getAttribute(ATTRIBUTE_DISABLED) !== null
1038
+ ) {
1039
+ this.setOption(ATTRIBUTE_DISABLED, true);
1040
+ } else {
1041
+ this.setOption(ATTRIBUTE_DISABLED, undefined);
1042
+ }
1043
+
1044
+ if (this.hasAttribute(ATTRIBUTE_OPTIONS)) {
1045
+ try {
1046
+ return parseOptionsJSON.call(this, this.getAttribute(ATTRIBUTE_OPTIONS));
1047
+ } catch (e) {
1048
+ addErrorAttribute(
1049
+ this,
1050
+ `the options attribute ${ATTRIBUTE_OPTIONS} does not contain a valid json definition (actual: ${this.getAttribute(
1051
+ ATTRIBUTE_OPTIONS,
1052
+ )}).${e}`,
1053
+ );
1054
+ }
1055
+ }
1056
+
1057
+ return {};
1059
1058
  }
1060
1059
 
1061
1060
  /**
@@ -1067,25 +1066,25 @@ function getOptionsFromAttributes() {
1067
1066
  * @throws {error} Throws an error if the JSON data is not valid.
1068
1067
  */
1069
1068
  function parseOptionsJSON(data) {
1070
- let obj = {};
1069
+ let obj = {};
1071
1070
 
1072
- if (!isString(data)) {
1073
- return obj;
1074
- }
1071
+ if (!isString(data)) {
1072
+ return obj;
1073
+ }
1075
1074
 
1076
- // the configuration can be specified as a data url.
1077
- try {
1078
- const dataUrl = parseDataURL(data);
1079
- data = dataUrl.content;
1080
- } catch (e) {}
1075
+ // the configuration can be specified as a data url.
1076
+ try {
1077
+ const dataUrl = parseDataURL(data);
1078
+ data = dataUrl.content;
1079
+ } catch (e) {}
1081
1080
 
1082
- try {
1083
- obj = JSON.parse(data);
1084
- } catch (e) {
1085
- throw e;
1086
- }
1081
+ try {
1082
+ obj = JSON.parse(data);
1083
+ } catch (e) {
1084
+ throw e;
1085
+ }
1087
1086
 
1088
- return validateObject(obj);
1087
+ return validateObject(obj);
1089
1088
  }
1090
1089
 
1091
1090
  /**
@@ -1094,18 +1093,18 @@ function parseOptionsJSON(data) {
1094
1093
  * @returns {*|string}
1095
1094
  */
1096
1095
  function substituteI18n(html) {
1097
- if (!this.getOption("templateFormatter.i18n", false)) {
1098
- return html;
1099
- }
1100
-
1101
- const labels = this.getOption("labels", {});
1102
- if (!(isObject(labels) || isIterable(labels))) {
1103
- return html;
1104
- }
1105
-
1106
- const formatter = new Formatter(labels, {});
1107
- formatter.setMarker("i18n{", "}");
1108
- return formatter.format(html);
1096
+ if (!this.getOption("templateFormatter.i18n", false)) {
1097
+ return html;
1098
+ }
1099
+
1100
+ const labels = this.getOption("labels", {});
1101
+ if (!(isObject(labels) || isIterable(labels))) {
1102
+ return html;
1103
+ }
1104
+
1105
+ const formatter = new Formatter(labels, {});
1106
+ formatter.setMarker("i18n{", "}");
1107
+ return formatter.format(html);
1109
1108
  }
1110
1109
 
1111
1110
  /**
@@ -1113,21 +1112,21 @@ function substituteI18n(html) {
1113
1112
  * @return {initHtmlContent}
1114
1113
  */
1115
1114
  function initHtmlContent() {
1116
- try {
1117
- const template = findDocumentTemplate(this.constructor.getTag());
1118
- this.appendChild(template.createDocumentFragment());
1119
- } catch (e) {
1120
- let html = this.getOption("templates.main", "");
1121
- if (isString(html) && html.length > 0) {
1122
- const mapping = this.getOption("templateMapping", {});
1123
- if (isObject(mapping)) {
1124
- html = new Formatter(mapping, {}).format(html);
1125
- }
1126
- this.innerHTML = substituteI18n.call(this, html);
1127
- }
1128
- }
1129
-
1130
- return this;
1115
+ try {
1116
+ const template = findDocumentTemplate(this.constructor.getTag());
1117
+ this.appendChild(template.createDocumentFragment());
1118
+ } catch (e) {
1119
+ let html = this.getOption("templates.main", "");
1120
+ if (isString(html) && html.length > 0) {
1121
+ const mapping = this.getOption("templateMapping", {});
1122
+ if (isObject(mapping)) {
1123
+ html = new Formatter(mapping, {}).format(html);
1124
+ }
1125
+ this.innerHTML = substituteI18n.call(this, html);
1126
+ }
1127
+ }
1128
+
1129
+ return this;
1131
1130
  }
1132
1131
 
1133
1132
  /**
@@ -1139,49 +1138,49 @@ function initHtmlContent() {
1139
1138
  * @throws {TypeError} value is not an instance of
1140
1139
  */
1141
1140
  function initCSSStylesheet() {
1142
- if (!(this.shadowRoot instanceof ShadowRoot)) {
1143
- return this;
1144
- }
1145
-
1146
- const styleSheet = this.constructor.getCSSStyleSheet();
1147
-
1148
- if (styleSheet instanceof CSSStyleSheet) {
1149
- if (styleSheet.cssRules.length > 0) {
1150
- this.shadowRoot.adoptedStyleSheets = [styleSheet];
1151
- }
1152
- } else if (isArray(styleSheet)) {
1153
- const assign = [];
1154
- for (const s of styleSheet) {
1155
- if (isString(s)) {
1156
- const trimedStyleSheet = s.trim();
1157
- if (trimedStyleSheet !== "") {
1158
- const style = document.createElement("style");
1159
- style.innerHTML = trimedStyleSheet;
1160
- this.shadowRoot.prepend(style);
1161
- }
1162
- continue;
1163
- }
1164
-
1165
- validateInstance(s, CSSStyleSheet);
1166
-
1167
- if (s.cssRules.length > 0) {
1168
- assign.push(s);
1169
- }
1170
- }
1171
-
1172
- if (assign.length > 0) {
1173
- this.shadowRoot.adoptedStyleSheets = assign;
1174
- }
1175
- } else if (isString(styleSheet)) {
1176
- const trimedStyleSheet = styleSheet.trim();
1177
- if (trimedStyleSheet !== "") {
1178
- const style = document.createElement("style");
1179
- style.innerHTML = styleSheet;
1180
- this.shadowRoot.prepend(style);
1181
- }
1182
- }
1183
-
1184
- return this;
1141
+ if (!(this.shadowRoot instanceof ShadowRoot)) {
1142
+ return this;
1143
+ }
1144
+
1145
+ const styleSheet = this.constructor.getCSSStyleSheet();
1146
+
1147
+ if (styleSheet instanceof CSSStyleSheet) {
1148
+ if (styleSheet.cssRules.length > 0) {
1149
+ this.shadowRoot.adoptedStyleSheets = [styleSheet];
1150
+ }
1151
+ } else if (isArray(styleSheet)) {
1152
+ const assign = [];
1153
+ for (const s of styleSheet) {
1154
+ if (isString(s)) {
1155
+ const trimedStyleSheet = s.trim();
1156
+ if (trimedStyleSheet !== "") {
1157
+ const style = document.createElement("style");
1158
+ style.innerHTML = trimedStyleSheet;
1159
+ this.shadowRoot.prepend(style);
1160
+ }
1161
+ continue;
1162
+ }
1163
+
1164
+ validateInstance(s, CSSStyleSheet);
1165
+
1166
+ if (s.cssRules.length > 0) {
1167
+ assign.push(s);
1168
+ }
1169
+ }
1170
+
1171
+ if (assign.length > 0) {
1172
+ this.shadowRoot.adoptedStyleSheets = assign;
1173
+ }
1174
+ } else if (isString(styleSheet)) {
1175
+ const trimedStyleSheet = styleSheet.trim();
1176
+ if (trimedStyleSheet !== "") {
1177
+ const style = document.createElement("style");
1178
+ style.innerHTML = styleSheet;
1179
+ this.shadowRoot.prepend(style);
1180
+ }
1181
+ }
1182
+
1183
+ return this;
1185
1184
  }
1186
1185
 
1187
1186
  /**
@@ -1193,42 +1192,42 @@ function initCSSStylesheet() {
1193
1192
  * @since 1.8.0
1194
1193
  */
1195
1194
  function initShadowRoot() {
1196
- let template;
1197
- let html;
1198
-
1199
- try {
1200
- template = findDocumentTemplate(this.constructor.getTag());
1201
- } catch (e) {
1202
- html = this.getOption("templates.main", "");
1203
- if (!isString(html) || html === undefined || html === "") {
1204
- throw new Error("html is not set.");
1205
- }
1206
- }
1207
-
1208
- this.attachShadow({
1209
- mode: this.getOption("shadowMode", "open"),
1210
- delegatesFocus: this.getOption("delegatesFocus", true),
1211
- });
1212
-
1213
- if (template instanceof Template) {
1214
- this.shadowRoot.appendChild(template.createDocumentFragment());
1215
- return this;
1216
- }
1217
-
1218
- const mapping = this.getOption("templateMapping", {});
1219
- if (isObject(mapping)) {
1220
- const formatter = new Formatter(mapping);
1221
- if (this.getOption("templateFormatter.marker.open") !== null) {
1222
- formatter.setMarker(
1223
- this.getOption("templateFormatter.marker.open"),
1224
- this.getOption("templateFormatter.marker.close"),
1225
- );
1226
- }
1227
- html = formatter.format(html);
1228
- }
1229
-
1230
- this.shadowRoot.innerHTML = substituteI18n.call(this, html);
1231
- return this;
1195
+ let template;
1196
+ let html;
1197
+
1198
+ try {
1199
+ template = findDocumentTemplate(this.constructor.getTag());
1200
+ } catch (e) {
1201
+ html = this.getOption("templates.main", "");
1202
+ if (!isString(html) || html === undefined || html === "") {
1203
+ throw new Error("html is not set.");
1204
+ }
1205
+ }
1206
+
1207
+ this.attachShadow({
1208
+ mode: this.getOption("shadowMode", "open"),
1209
+ delegatesFocus: this.getOption("delegatesFocus", true),
1210
+ });
1211
+
1212
+ if (template instanceof Template) {
1213
+ this.shadowRoot.appendChild(template.createDocumentFragment());
1214
+ return this;
1215
+ }
1216
+
1217
+ const mapping = this.getOption("templateMapping", {});
1218
+ if (isObject(mapping)) {
1219
+ const formatter = new Formatter(mapping);
1220
+ if (this.getOption("templateFormatter.marker.open") !== null) {
1221
+ formatter.setMarker(
1222
+ this.getOption("templateFormatter.marker.open"),
1223
+ this.getOption("templateFormatter.marker.close"),
1224
+ );
1225
+ }
1226
+ html = formatter.format(html);
1227
+ }
1228
+
1229
+ this.shadowRoot.innerHTML = substituteI18n.call(this, html);
1230
+ return this;
1232
1231
  }
1233
1232
 
1234
1233
  /**
@@ -1242,20 +1241,20 @@ function initShadowRoot() {
1242
1241
  * @throws {DOMException} Failed to execute 'define' on 'CustomElementRegistry': is not a valid custom element name
1243
1242
  */
1244
1243
  function registerCustomElement(element) {
1245
- validateFunction(element);
1246
- const customElements = getGlobalObject("customElements");
1247
- if (customElements === undefined) {
1248
- throw new Error("customElements is not supported.");
1249
- }
1250
-
1251
- const tag = element?.getTag();
1252
- if (!isString(tag) || tag === "") {
1253
- throw new Error("tag is not set.");
1254
- }
1255
-
1256
- if (customElements.get(tag) !== undefined) {
1257
- return;
1258
- }
1259
-
1260
- customElements.define(tag, element);
1244
+ validateFunction(element);
1245
+ const customElements = getGlobalObject("customElements");
1246
+ if (customElements === undefined) {
1247
+ throw new Error("customElements is not supported.");
1248
+ }
1249
+
1250
+ const tag = element?.getTag();
1251
+ if (!isString(tag) || tag === "") {
1252
+ throw new Error("tag is not set.");
1253
+ }
1254
+
1255
+ if (customElements.get(tag) !== undefined) {
1256
+ return;
1257
+ }
1258
+
1259
+ customElements.define(tag, element);
1261
1260
  }