@schukai/monster 3.53.0 → 3.55.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 (72) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/package.json +1 -1
  3. package/source/components/datatable/datasource/rest.mjs +358 -309
  4. package/source/components/datatable/datatable/header.mjs +8 -0
  5. package/source/components/datatable/datatable.mjs +606 -557
  6. package/source/components/datatable/embedded-pagination.mjs +50 -62
  7. package/source/components/datatable/filter/util.mjs +122 -0
  8. package/source/components/datatable/filter.mjs +893 -708
  9. package/source/components/datatable/pagination.mjs +335 -310
  10. package/source/components/datatable/status.mjs +248 -0
  11. package/source/components/datatable/style/datatable.pcss +1 -0
  12. package/source/components/datatable/style/embedded-pagination.pcss +59 -2
  13. package/source/components/datatable/style/filter.pcss +4 -0
  14. package/source/components/datatable/style/pagination.pcss +28 -4
  15. package/source/components/datatable/style/status.pcss +42 -0
  16. package/source/components/datatable/stylesheet/column-bar.mjs +1 -1
  17. package/source/components/datatable/stylesheet/datatable.mjs +1 -1
  18. package/source/components/datatable/stylesheet/filter-button.mjs +1 -1
  19. package/source/components/datatable/stylesheet/filter.mjs +1 -1
  20. package/source/components/datatable/stylesheet/pagination.mjs +1 -1
  21. package/source/components/datatable/stylesheet/status.mjs +27 -0
  22. package/source/components/form/action-button.mjs +1 -1
  23. package/source/components/form/api-button.mjs +1 -1
  24. package/source/components/form/button-bar.mjs +1 -1
  25. package/source/components/form/button.mjs +1 -1
  26. package/source/components/form/confirm-button.mjs +1 -1
  27. package/source/components/form/context-error.mjs +275 -0
  28. package/source/components/form/context-help.mjs +5 -5
  29. package/source/components/form/form.mjs +2 -2
  30. package/source/components/form/message-state-button.mjs +2 -2
  31. package/source/components/form/popper-button.mjs +7 -4
  32. package/source/components/form/popper.mjs +317 -309
  33. package/source/components/form/reload.mjs +1 -1
  34. package/source/components/form/select.mjs +9 -3
  35. package/source/components/form/shadow-reload.mjs +1 -1
  36. package/source/components/form/state-button.mjs +2 -1
  37. package/source/components/form/style/context-error.pcss +32 -0
  38. package/source/components/form/style/context-help.pcss +22 -5
  39. package/source/components/form/stylesheet/context-error.mjs +27 -0
  40. package/source/components/form/stylesheet/context-help.mjs +1 -1
  41. package/source/components/form/stylesheet/select.mjs +1 -1
  42. package/source/components/form/stylesheet/tabs.mjs +1 -1
  43. package/source/components/form/tabs.mjs +757 -707
  44. package/source/components/form/template.mjs +1 -1
  45. package/source/components/form/tree-select.mjs +1 -1
  46. package/source/components/host/collapse.mjs +22 -5
  47. package/source/components/host/config-manager.mjs +39 -2
  48. package/source/components/host/host.mjs +14 -0
  49. package/source/components/host/stylesheet/call-button.mjs +1 -1
  50. package/source/components/host/stylesheet/overlay.mjs +1 -1
  51. package/source/components/host/stylesheet/toggle-button.mjs +1 -1
  52. package/source/components/host/util.mjs +6 -1
  53. package/source/components/notify/stylesheet/message.mjs +1 -1
  54. package/source/components/stylesheet/icons.mjs +1 -1
  55. package/source/data/transformer.mjs +39 -42
  56. package/source/dom/customelement.mjs +1 -1
  57. package/source/dom/updater.mjs +700 -688
  58. package/source/dom/util.mjs +42 -0
  59. package/source/i18n/providers/embed.mjs +3 -3
  60. package/source/monster.mjs +6 -0
  61. package/source/text/formatter.mjs +2 -2
  62. package/source/types/observer.mjs +1 -1
  63. package/source/types/version.mjs +1 -1
  64. package/source/util/sleep.mjs +18 -0
  65. package/test/cases/components/form/button.mjs +2 -1
  66. package/test/cases/components/form/select.mjs +1 -1
  67. package/test/cases/components/form/tree-select.mjs +1 -1
  68. package/test/cases/data/transformer.mjs +2 -2
  69. package/test/cases/dom/updater.mjs +67 -46
  70. package/test/cases/monster.mjs +1 -1
  71. package/test/web/test.html +2 -2
  72. package/test/web/tests.js +18 -13
@@ -4,51 +4,52 @@
4
4
  * This file is licensed under the AGPLv3 License.
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
- import { instanceSymbol } from "../../constants.mjs";
8
- import { createPopper } from "@popperjs/core";
9
- import { extend } from "../../data/extend.mjs";
10
- import { Pathfinder } from "../../data/pathfinder.mjs";
7
+ import {instanceSymbol} from "../../constants.mjs";
8
+ import {createPopper} from "@popperjs/core";
9
+ import {extend} from "../../data/extend.mjs";
10
+ import {Pathfinder} from "../../data/pathfinder.mjs";
11
11
  import {
12
- addAttributeToken,
13
- addToObjectLink,
14
- hasObjectLink,
12
+ addAttributeToken,
13
+ addToObjectLink,
14
+ hasObjectLink,
15
15
  } from "../../dom/attributes.mjs";
16
16
  import {
17
- ATTRIBUTE_ERRORMESSAGE,
18
- ATTRIBUTE_PREFIX,
19
- ATTRIBUTE_ROLE,
17
+ ATTRIBUTE_ERRORMESSAGE,
18
+ ATTRIBUTE_PREFIX,
19
+ ATTRIBUTE_ROLE,
20
20
  } from "../../dom/constants.mjs";
21
21
  import {
22
- assembleMethodSymbol,
23
- CustomElement,
24
- getSlottedElements,
25
- registerCustomElement,
22
+ assembleMethodSymbol,
23
+ CustomElement,
24
+ getSlottedElements,
25
+ registerCustomElement,
26
26
  } from "../../dom/customelement.mjs";
27
- import { findTargetElementFromEvent } from "../../dom/events.mjs";
28
- import { getDocument } from "../../dom/util.mjs";
29
- import { random } from "../../math/random.mjs";
30
- import { getGlobal } from "../../types/global.mjs";
31
- import { ID } from "../../types/id.mjs";
32
- import { isArray, isString } from "../../types/is.mjs";
33
- import { TokenList } from "../../types/tokenlist.mjs";
34
- import { clone } from "../../util/clone.mjs";
35
- import { DeadMansSwitch } from "../../util/deadmansswitch.mjs";
36
- import { Processing } from "../../util/processing.mjs";
27
+ import {findTargetElementFromEvent, fireCustomEvent} from "../../dom/events.mjs";
28
+ import {getDocument} from "../../dom/util.mjs";
29
+ import {random} from "../../math/random.mjs";
30
+ import {getGlobal} from "../../types/global.mjs";
31
+ import {ID} from "../../types/id.mjs";
32
+ import {isArray, isString} from "../../types/is.mjs";
33
+ import {TokenList} from "../../types/tokenlist.mjs";
34
+ import {clone} from "../../util/clone.mjs";
35
+ import {DeadMansSwitch} from "../../util/deadmansswitch.mjs";
36
+ import {Processing} from "../../util/processing.mjs";
37
37
  import {
38
- ATTRIBUTE_BUTTON_LABEL,
39
- ATTRIBUTE_FORM_RELOAD,
40
- ATTRIBUTE_FORM_URL,
41
- STYLE_DISPLAY_MODE_BLOCK,
38
+ ATTRIBUTE_BUTTON_LABEL,
39
+ ATTRIBUTE_FORM_RELOAD,
40
+ ATTRIBUTE_FORM_URL,
41
+ STYLE_DISPLAY_MODE_BLOCK,
42
42
  } from "./constants.mjs";
43
43
 
44
- import { TabsStyleSheet } from "./stylesheet/tabs.mjs";
45
- import { loadAndAssignContent } from "./util/fetch.mjs";
44
+ import {TabsStyleSheet} from "./stylesheet/tabs.mjs";
45
+ import {loadAndAssignContent} from "./util/fetch.mjs";
46
+ import {ThemeStyleSheet} from "../stylesheet/theme.mjs";
46
47
  import {
47
- popperInstanceSymbol,
48
- setEventListenersModifiers,
48
+ popperInstanceSymbol,
49
+ setEventListenersModifiers,
49
50
  } from "./util/popper.mjs";
50
51
 
51
- export { Tabs };
52
+ export {Tabs};
52
53
 
53
54
  /**
54
55
  * @private
@@ -168,283 +169,289 @@ const resizeObserverSymbol = Symbol("resizeObserver");
168
169
  * @fires Monster.Components.Form.event:monster-fetched
169
170
  */
170
171
  class Tabs extends CustomElement {
171
- /**
172
- * This method is called by the `instanceof` operator.
173
- * @returns {symbol}
174
- * @since 2.1.0
175
- */
176
- static get [instanceSymbol]() {
177
- return Symbol.for("@schukai/component-form/tabs");
178
- }
179
-
180
- /**
181
- * To set the options via the html tag the attribute `data-monster-options` must be used.
182
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
183
- *
184
- * The individual configuration values can be found in the table.
185
- *
186
- * @property {Object} templates Template definitions
187
- * @property {string} templates.main Main template
188
- * @property {Object} labels
189
- * @property {string} labels.new-tab-label="New Tab"
190
- * @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
191
- * @property {String} fetch.redirect=error
192
- * @property {String} fetch.method=GET
193
- * @property {String} fetch.mode=same-origin
194
- * @property {String} fetch.credentials=same-origin
195
- * @property {Object} fetch.headers={"accept":"text/html"}}
196
- * @property {Object} popper [PopperJS Options](https://popper.js.org/docs/v2/)
197
- * @property {string} popper.placement=bottom PopperJS placement
198
- * @property {Object[]} modifiers={name:offset} PopperJS placement
199
- */
200
- get defaults() {
201
- return Object.assign({}, super.defaults, {
202
- templates: {
203
- main: getTemplate(),
204
- },
205
- labels: {
206
- "new-tab-label": "New Tab",
207
- },
208
- buttons: {
209
- standard: [],
210
- popper: [],
211
- },
212
- fetch: {
213
- redirect: "error",
214
- method: "GET",
215
- mode: "same-origin",
216
- credentials: "same-origin",
217
- headers: {
218
- accept: "text/html",
219
- },
220
- },
221
- popper: {
222
- placement: "bottom",
223
- modifiers: [
224
- {
225
- name: "offset",
226
- options: {
227
- offset: [0, 2],
228
- },
229
- },
230
-
231
- {
232
- name: "eventListeners",
233
- enabled: false,
234
- },
235
- ],
236
- },
237
- });
238
- }
239
-
240
- /**
241
- * This method is called internal and should not be called directly.
242
- */
243
- [assembleMethodSymbol]() {
244
- super[assembleMethodSymbol]();
245
-
246
- initControlReferences.call(this);
247
-
248
- this[dimensionsSymbol] = new Pathfinder({ data: {} });
249
- // change and remove Tabs
250
- initEventHandler.call(this);
251
-
252
- // setup structure
253
- initTabButtons.call(this).then(() => {
254
- initPopperSwitch.call(this);
255
- initPopper.call(this);
256
- attachResizeObserver.call(this);
257
- attachTabChangeObserver.call(this);
258
- });
259
- }
260
-
261
- /**
262
- * This method is called internal and should not be called directly.
263
- *
264
- * @return {CSSStyleSheet[]}
265
- */
266
- static getCSSStyleSheet() {
267
- return [TabsStyleSheet];
268
- }
269
-
270
- /**
271
- * This method is called internal and should not be called directly.
272
- *
273
- * @return {string}
274
- */
275
- static getTag() {
276
- return "monster-tabs";
277
- }
278
-
279
- /**
280
- * This method is called by the dom and should not be called directly.
281
- *
282
- * @return {void}
283
- */
284
- connectedCallback() {
285
- super.connectedCallback();
286
-
287
- const document = getDocument();
288
-
289
- for (const [, type] of Object.entries(["click", "touch"])) {
290
- // close on outside ui-events
291
- document.addEventListener(type, this[closeEventHandler]);
292
- }
293
- }
294
-
295
- /**
296
- * This method is called by the dom and should not be called directly.
297
- *
298
- * @return {void}
299
- */
300
- disconnectedCallback() {
301
- super.disconnectedCallback();
302
-
303
- const document = getDocument();
304
-
305
- // close on outside ui-events
306
- for (const [, type] of Object.entries(["click", "touch"])) {
307
- document.removeEventListener(type, this[closeEventHandler]);
308
- }
309
- }
172
+ /**
173
+ * This method is called by the `instanceof` operator.
174
+ * @returns {symbol}
175
+ * @since 2.1.0
176
+ */
177
+ static get [instanceSymbol]() {
178
+ return Symbol.for("@schukai/monster/components/form/tabs");
179
+ }
180
+
181
+ /**
182
+ * To set the options via the html tag the attribute `data-monster-options` must be used.
183
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
184
+ *
185
+ * The individual configuration values can be found in the table.
186
+ *
187
+ * @property {Object} templates Template definitions
188
+ * @property {string} templates.main Main template
189
+ * @property {Object} labels
190
+ * @property {string} labels.new-tab-label="New Tab"
191
+ * @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
192
+ * @property {String} fetch.redirect=error
193
+ * @property {String} fetch.method=GET
194
+ * @property {String} fetch.mode=same-origin
195
+ * @property {String} fetch.credentials=same-origin
196
+ * @property {Object} fetch.headers={"accept":"text/html"}}
197
+ * @property {Object} popper [PopperJS Options](https://popper.js.org/docs/v2/)
198
+ * @property {string} popper.placement=bottom PopperJS placement
199
+ * @property {Object[]} modifiers={name:offset} PopperJS placement
200
+ */
201
+ get defaults() {
202
+ return Object.assign({}, super.defaults, {
203
+ templates: {
204
+ main: getTemplate(),
205
+ },
206
+ labels: {
207
+ "new-tab-label": "New Tab",
208
+ },
209
+ buttons: {
210
+ standard: [],
211
+ popper: [],
212
+ },
213
+ fetch: {
214
+ redirect: "error",
215
+ method: "GET",
216
+ mode: "same-origin",
217
+ credentials: "same-origin",
218
+ headers: {
219
+ accept: "text/html",
220
+ },
221
+ },
222
+
223
+ classes: {
224
+ button: "monster-theme-primary-1",
225
+ },
226
+
227
+ popper: {
228
+ placement: "bottom",
229
+ modifiers: [
230
+ {
231
+ name: "offset",
232
+ options: {
233
+ offset: [0, 2],
234
+ },
235
+ },
236
+
237
+ {
238
+ name: "eventListeners",
239
+ enabled: false,
240
+ },
241
+ ],
242
+ },
243
+ });
244
+ }
245
+
246
+ /**
247
+ * This method is called internal and should not be called directly.
248
+ */
249
+ [assembleMethodSymbol]() {
250
+ super[assembleMethodSymbol]();
251
+
252
+ initControlReferences.call(this);
253
+
254
+ this[dimensionsSymbol] = new Pathfinder({data: {}});
255
+
256
+ initEventHandler.call(this);
257
+
258
+ // setup structure
259
+ initTabButtons.call(this).then(() => {
260
+ initPopperSwitch.call(this);
261
+ initPopper.call(this);
262
+ attachResizeObserver.call(this);
263
+ attachTabChangeObserver.call(this);
264
+ });
265
+ }
266
+
267
+ /**
268
+ * This method is called internal and should not be called directly.
269
+ *
270
+ * @return {CSSStyleSheet[]}
271
+ */
272
+ static getCSSStyleSheet() {
273
+ return [TabsStyleSheet, ThemeStyleSheet];
274
+ }
275
+
276
+ /**
277
+ * This method is called internal and should not be called directly.
278
+ *
279
+ * @return {string}
280
+ */
281
+ static getTag() {
282
+ return "monster-tabs";
283
+ }
284
+
285
+ /**
286
+ * This method is called by the dom and should not be called directly.
287
+ *
288
+ * @return {void}
289
+ */
290
+ connectedCallback() {
291
+ super.connectedCallback();
292
+
293
+ const document = getDocument();
294
+
295
+ for (const [, type] of Object.entries(["click", "touch"])) {
296
+ // close on outside ui-events
297
+ document.addEventListener(type, this[closeEventHandler]);
298
+ }
299
+ }
300
+
301
+ /**
302
+ * This method is called by the dom and should not be called directly.
303
+ *
304
+ * @return {void}
305
+ */
306
+ disconnectedCallback() {
307
+ super.disconnectedCallback();
308
+
309
+ const document = getDocument();
310
+
311
+ // close on outside ui-events
312
+ for (const [, type] of Object.entries(["click", "touch"])) {
313
+ document.removeEventListener(type, this[closeEventHandler]);
314
+ }
315
+ }
310
316
  }
311
317
 
312
318
  /**
313
319
  * @private
314
320
  */
315
321
  function initPopperSwitch() {
316
- const nodes = getSlottedElements.call(this, `[${ATTRIBUTE_ROLE}="switch"]`); // null ↦ only unnamed slots
317
- let switchButton;
318
- if (nodes.size === 0) {
319
- switchButton = document.createElement("button");
320
- switchButton.setAttribute(ATTRIBUTE_ROLE, "switch");
321
- switchButton.setAttribute("part", "switch");
322
- switchButton.classList.add("hidden");
323
- switchButton.innerHTML =
324
- '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/></svg>';
325
- this[navElementSymbol].prepend(switchButton);
326
- } else {
327
- switchButton = nodes.next();
328
- }
329
-
330
- /**
331
- * @param {Event} event
332
- */
333
- this[popperSwitchEventHandler] = (event) => {
334
- const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "switch");
335
-
336
- if (element instanceof HTMLButtonElement) {
337
- togglePopper.call(this);
338
- }
339
- };
340
-
341
- for (const type of ["click", "touch"]) {
342
- switchButton.addEventListener(type, this[popperSwitchEventHandler]);
343
- }
344
-
345
- this[switchElementSymbol] = switchButton;
322
+ const nodes = getSlottedElements.call(this, `[${ATTRIBUTE_ROLE}="switch"]`); // null ↦ only unnamed slots
323
+ let switchButton;
324
+ if (nodes.size === 0) {
325
+ switchButton = document.createElement("button");
326
+ switchButton.setAttribute(ATTRIBUTE_ROLE, "switch");
327
+ switchButton.setAttribute("part", "switch");
328
+ switchButton.classList.add("hidden");
329
+ switchButton.innerHTML =
330
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/></svg>';
331
+ this[navElementSymbol].prepend(switchButton);
332
+ } else {
333
+ switchButton = nodes.next();
334
+ }
335
+
336
+ /**
337
+ * @param {Event} event
338
+ */
339
+ this[popperSwitchEventHandler] = (event) => {
340
+ const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "switch");
341
+
342
+ if (element instanceof HTMLButtonElement) {
343
+ togglePopper.call(this);
344
+ }
345
+ };
346
+
347
+ for (const type of ["click", "touch"]) {
348
+ switchButton.addEventListener(type, this[popperSwitchEventHandler]);
349
+ }
350
+
351
+ this[switchElementSymbol] = switchButton;
346
352
  }
347
353
 
348
354
  /**
349
355
  * @private
350
356
  */
351
357
  function hidePopper() {
352
- if (!this[popperInstanceSymbol]) {
353
- return;
354
- }
358
+ if (!this[popperInstanceSymbol]) {
359
+ return;
360
+ }
355
361
 
356
- this[popperElementSymbol].style.display = "none";
357
- // performance https://popper.js.org/docs/v2/tutorial/#performance
358
- setEventListenersModifiers.call(this, false);
362
+ this[popperElementSymbol].style.display = "none";
363
+ // performance https://popper.js.org/docs/v2/tutorial/#performance
364
+ setEventListenersModifiers.call(this, false);
359
365
  }
360
366
 
361
367
  /**
362
368
  * @private
363
369
  */
364
370
  function showPopper() {
365
- if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
366
- return;
367
- }
368
-
369
- this[popperElementSymbol].style.visibility = "hidden";
370
- this[popperElementSymbol].style.display = STYLE_DISPLAY_MODE_BLOCK;
371
- // performance https://popper.js.org/docs/v2/tutorial/#performance
372
- setEventListenersModifiers.call(this, true);
373
-
374
- this[popperInstanceSymbol].update();
375
-
376
- new Processing(() => {
377
- this[popperElementSymbol].style.removeProperty("visibility");
378
- })
379
- .run(undefined)
380
- .then(() => {})
381
- .catch((e) => {
382
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
383
- });
371
+ if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
372
+ return;
373
+ }
374
+
375
+ this[popperElementSymbol].style.visibility = "hidden";
376
+ this[popperElementSymbol].style.display = STYLE_DISPLAY_MODE_BLOCK;
377
+ // performance https://popper.js.org/docs/v2/tutorial/#performance
378
+ setEventListenersModifiers.call(this, true);
379
+
380
+ this[popperInstanceSymbol].update();
381
+
382
+ new Processing(() => {
383
+ this[popperElementSymbol].style.removeProperty("visibility");
384
+ })
385
+ .run(undefined)
386
+ .then(() => {
387
+ })
388
+ .catch((e) => {
389
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
390
+ });
384
391
  }
385
392
 
386
393
  /**
387
394
  * @private
388
395
  */
389
396
  function togglePopper() {
390
- if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
391
- hidePopper.call(this);
392
- } else {
393
- showPopper.call(this);
394
- }
397
+ if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
398
+ hidePopper.call(this);
399
+ } else {
400
+ showPopper.call(this);
401
+ }
395
402
  }
396
403
 
397
404
  /**
398
405
  * @private
399
406
  */
400
407
  function attachResizeObserver() {
401
- // against flickering
402
- this[resizeObserverSymbol] = new ResizeObserver((entries) => {
403
- if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
404
- try {
405
- this[timerCallbackSymbol].touch();
406
- return;
407
- } catch (e) {
408
- delete this[timerCallbackSymbol];
409
- }
410
- }
411
-
412
- this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
413
- this[dimensionsSymbol].setVia("data.calculated", false);
414
- checkAndRearrangeButtons.call(this);
415
- });
416
- });
417
-
418
- this[resizeObserverSymbol].observe(this[navElementSymbol]);
408
+ // against flickering
409
+ this[resizeObserverSymbol] = new ResizeObserver((entries) => {
410
+ if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
411
+ try {
412
+ this[timerCallbackSymbol].touch();
413
+ return;
414
+ } catch (e) {
415
+ delete this[timerCallbackSymbol];
416
+ }
417
+ }
418
+
419
+ this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
420
+ this[dimensionsSymbol].setVia("data.calculated", false);
421
+ checkAndRearrangeButtons.call(this);
422
+ });
423
+ });
424
+
425
+ this[resizeObserverSymbol].observe(this[navElementSymbol]);
419
426
  }
420
427
 
421
428
  /**
422
429
  * @private
423
430
  */
424
431
  function attachTabChangeObserver() {
425
- // against flickering
426
- new MutationObserver((mutations) => {
427
- let runUpdate = false;
428
-
429
- for (const mutation of mutations) {
430
- if (mutation.type === "childList") {
431
- if (
432
- mutation.addedNodes.length > 0 ||
433
- mutation.removedNodes.length > 0
434
- ) {
435
- runUpdate = true;
436
- break;
437
- }
438
- }
439
- }
440
-
441
- if (runUpdate === true) {
442
- this[dimensionsSymbol].setVia("data.calculated", false);
443
- initTabButtons.call(this);
444
- }
445
- }).observe(this, {
446
- childList: true,
447
- });
432
+ // against flickering
433
+ new MutationObserver((mutations) => {
434
+ let runUpdate = false;
435
+
436
+ for (const mutation of mutations) {
437
+ if (mutation.type === "childList") {
438
+ if (
439
+ mutation.addedNodes.length > 0 ||
440
+ mutation.removedNodes.length > 0
441
+ ) {
442
+ runUpdate = true;
443
+ break;
444
+ }
445
+ }
446
+ }
447
+
448
+ if (runUpdate === true) {
449
+ this[dimensionsSymbol].setVia("data.calculated", false);
450
+ initTabButtons.call(this);
451
+ }
452
+ }).observe(this, {
453
+ childList: true,
454
+ });
448
455
  }
449
456
 
450
457
  /**
@@ -454,42 +461,42 @@ function attachTabChangeObserver() {
454
461
  * @see {@link Plugins}
455
462
  */
456
463
  function initPopper() {
457
- const self = this;
458
-
459
- const options = extend({}, self.getOption("popper"));
460
-
461
- self[popperInstanceSymbol] = createPopper(
462
- self[switchElementSymbol],
463
- self[popperElementSymbol],
464
- options,
465
- );
466
-
467
- const observer1 = new MutationObserver(function (mutations) {
468
- let runUpdate = false;
469
-
470
- for (const mutation of mutations) {
471
- if (mutation.type === "childList") {
472
- if (
473
- mutation.addedNodes.length > 0 ||
474
- mutation.removedNodes.length > 0
475
- ) {
476
- runUpdate = true;
477
- break;
478
- }
479
- }
480
- }
481
-
482
- if (runUpdate === true) {
483
- self[popperInstanceSymbol].update();
484
- }
485
- });
486
-
487
- observer1.observe(self[popperNavElementSymbol], {
488
- childList: true,
489
- subtree: true,
490
- });
491
-
492
- return self;
464
+ const self = this;
465
+
466
+ const options = extend({}, self.getOption("popper"));
467
+
468
+ self[popperInstanceSymbol] = createPopper(
469
+ self[switchElementSymbol],
470
+ self[popperElementSymbol],
471
+ options,
472
+ );
473
+
474
+ const observer1 = new MutationObserver(function (mutations) {
475
+ let runUpdate = false;
476
+
477
+ for (const mutation of mutations) {
478
+ if (mutation.type === "childList") {
479
+ if (
480
+ mutation.addedNodes.length > 0 ||
481
+ mutation.removedNodes.length > 0
482
+ ) {
483
+ runUpdate = true;
484
+ break;
485
+ }
486
+ }
487
+ }
488
+
489
+ if (runUpdate === true) {
490
+ self[popperInstanceSymbol].update();
491
+ }
492
+ });
493
+
494
+ observer1.observe(self[popperNavElementSymbol], {
495
+ childList: true,
496
+ subtree: true,
497
+ });
498
+
499
+ return self;
493
500
  }
494
501
 
495
502
  /**
@@ -497,132 +504,173 @@ function initPopper() {
497
504
  * @param {HTMLElement} element
498
505
  */
499
506
  function show(element) {
500
- if (!this.shadowRoot) {
501
- throw new Error("no shadow-root is defined");
502
- }
503
-
504
- const reference = element.getAttribute(`${ATTRIBUTE_PREFIX}tab-reference`);
505
-
506
- const nodes = getSlottedElements.call(this);
507
- for (const node of nodes) {
508
- const id = node.getAttribute("id");
509
-
510
- if (id === reference) {
511
- node.classList.add("active");
512
-
513
- if (node.hasAttribute(ATTRIBUTE_FORM_URL)) {
514
- const url = node.getAttribute(ATTRIBUTE_FORM_URL);
515
-
516
- if (
517
- !node.hasAttribute(ATTRIBUTE_FORM_RELOAD) ||
518
- node.getAttribute(ATTRIBUTE_FORM_RELOAD).toLowerCase() === "onshow"
519
- ) {
520
- node.removeAttribute(ATTRIBUTE_FORM_URL);
521
- }
522
-
523
- const options = this.getOption("fetch", {});
524
- const filter = undefined;
525
- loadAndAssignContent(node, url, options, filter)
526
- .then(() => {})
527
- .catch((e) => {
528
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
529
- });
530
- }
531
- } else {
532
- node.classList.remove("active");
533
- }
534
- }
535
-
536
- const standardButtons = this.getOption("buttons.standard");
537
- for (const index in standardButtons) {
538
- const button = standardButtons[index];
539
- const state = button["reference"] === reference ? "active" : "inactive";
540
- this.setOption(`buttons.standard.${index}.state`, state);
541
- }
542
-
543
- const popperButton = this.getOption("buttons.popper");
544
- for (const index in popperButton) {
545
- const button = popperButton[index];
546
- const state = button["reference"] === reference ? "active" : "inactive";
547
- this.setOption(`buttons.popper.${index}.state`, state);
548
- }
549
-
550
- hidePopper.call(this);
507
+ const self = this;
508
+ if (!this.shadowRoot) {
509
+ throw new Error("no shadow-root is defined");
510
+ }
511
+
512
+ const reference = element.getAttribute(`${ATTRIBUTE_PREFIX}tab-reference`);
513
+
514
+
515
+
516
+
517
+ const nodes = getSlottedElements.call(this);
518
+ for (const node of nodes) {
519
+ const id = node.getAttribute("id");
520
+
521
+ if (id === reference) {
522
+ node.classList.add("active");
523
+
524
+ // get all data- from button and filter out data-monster-attributes and data-monster-insert
525
+ const data = {};
526
+ const mask = ["data-monster-attributes",
527
+ "data-monster-insert-reference",
528
+ "data-monster-state",
529
+ "data-monster-button-label",
530
+ "data-monster-objectlink",
531
+ "data-monster-role"];
532
+
533
+ for (const [, attr] of Object.entries(node.attributes)) {
534
+ if (attr.name.startsWith("data-") && mask.indexOf(attr.name) === -1) {
535
+ data[attr.name] = attr.value;
536
+ }
537
+ }
538
+
539
+ if (node.hasAttribute(ATTRIBUTE_FORM_URL)) {
540
+ const url = node.getAttribute(ATTRIBUTE_FORM_URL);
541
+
542
+ if (
543
+ !node.hasAttribute(ATTRIBUTE_FORM_RELOAD) ||
544
+ node.getAttribute(ATTRIBUTE_FORM_RELOAD).toLowerCase() === "onshow"
545
+ ) {
546
+ node.removeAttribute(ATTRIBUTE_FORM_URL);
547
+ }
548
+
549
+ const options = this.getOption("fetch", {});
550
+ const filter = undefined;
551
+ loadAndAssignContent(node, url, options, filter)
552
+ .then(() => {
553
+ fireCustomEvent(self, "monster-tab-changed", {
554
+ reference,
555
+ });
556
+ })
557
+ .catch((e) => {
558
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
559
+ });
560
+ } else {
561
+ fireCustomEvent(self, "monster-tab-changed", {
562
+ reference,
563
+ data
564
+ });
565
+ }
566
+ } else {
567
+ node.classList.remove("active");
568
+ }
569
+ }
570
+
571
+ const standardButtons = this.getOption("buttons.standard");
572
+ for (const index in standardButtons) {
573
+ const button = standardButtons[index];
574
+ const state = button["reference"] === reference ? "active" : "inactive";
575
+ this.setOption(`buttons.standard.${index}.state`, state);
576
+ }
577
+
578
+ const popperButton = this.getOption("buttons.popper");
579
+ for (const index in popperButton) {
580
+ const button = popperButton[index];
581
+ const state = button["reference"] === reference ? "active" : "inactive";
582
+ this.setOption(`buttons.popper.${index}.state`, state);
583
+ }
584
+
585
+ hidePopper.call(this);
551
586
  }
552
587
 
553
588
  /**
554
589
  * @private
555
590
  */
556
591
  function initEventHandler() {
557
- if (!this.shadowRoot) {
558
- throw new Error("no shadow-root is defined");
559
- }
560
-
561
- /**
562
- * @param {Event} event
563
- */
564
- this[changeTabEventHandler] = (event) => {
565
- const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "button");
566
-
567
- if (element instanceof HTMLButtonElement && element.disabled !== true) {
568
- show.call(this, element);
569
- }
570
- };
571
-
572
- /**
573
- * @param {Event} event
574
- */
575
- this[removeTabEventHandler] = (event) => {
576
- const element = findTargetElementFromEvent(
577
- event,
578
- ATTRIBUTE_ROLE,
579
- "remove-tab",
580
- );
581
-
582
- if (element instanceof HTMLElement) {
583
- const button = findTargetElementFromEvent(
584
- event,
585
- ATTRIBUTE_ROLE,
586
- "button",
587
- );
588
-
589
- if (button instanceof HTMLButtonElement && button.disabled !== true) {
590
- const reference = button.getAttribute(
591
- `${ATTRIBUTE_PREFIX}tab-reference`,
592
- );
593
- if (reference) {
594
- const container = this.querySelector(`[id=${reference}]`);
595
- if (container instanceof HTMLElement) {
596
- container.remove();
597
- initTabButtons.call(this);
598
- }
599
- }
600
- }
601
- }
602
- };
603
-
604
- this[navElementSymbol].addEventListener("touch", this[changeTabEventHandler]);
605
- this[navElementSymbol].addEventListener("click", this[changeTabEventHandler]);
606
-
607
- this[navElementSymbol].addEventListener("touch", this[removeTabEventHandler]);
608
- this[navElementSymbol].addEventListener("click", this[removeTabEventHandler]);
609
-
610
- /**
611
- * @param {Event} event
612
- */
613
- this[closeEventHandler] = (event) => {
614
- const path = event.composedPath();
615
-
616
- for (const [, element] of Object.entries(path)) {
617
- if (element === this) {
618
- return;
619
- }
620
- }
621
-
622
- hidePopper.call(this);
623
- };
624
-
625
- return this;
592
+
593
+ const self=this;
594
+
595
+ if (!this.shadowRoot) {
596
+ throw new Error("no shadow-root is defined");
597
+ }
598
+
599
+ /**
600
+ * @param {Event} event
601
+ */
602
+ this[changeTabEventHandler] = (event) => {
603
+ const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "button");
604
+
605
+ if (element instanceof HTMLButtonElement && element.disabled !== true) {
606
+ show.call(this, element);
607
+ }
608
+ };
609
+
610
+ /**
611
+ * event:monster-tab-remove
612
+ * @event Monster.Components.Form.event:monster-tab-remove
613
+ */
614
+
615
+ /**
616
+ * @param {Event} event
617
+ * @fires Monster.Components.Form.event:monster-tab-remove
618
+ */
619
+ this[removeTabEventHandler] = (event) => {
620
+
621
+ const element = findTargetElementFromEvent(
622
+ event,
623
+ ATTRIBUTE_ROLE,
624
+ "remove-tab",
625
+ );
626
+
627
+ if (element instanceof HTMLElement) {
628
+ const button = findTargetElementFromEvent(
629
+ event,
630
+ ATTRIBUTE_ROLE,
631
+ "button",
632
+ );
633
+
634
+ if (button instanceof HTMLButtonElement && button.disabled !== true) {
635
+ const reference = button.getAttribute(
636
+ `${ATTRIBUTE_PREFIX}tab-reference`,
637
+ );
638
+ if (reference) {
639
+ const container = this.querySelector(`[id=${reference}]`);
640
+ if (container instanceof HTMLElement) {
641
+ container.remove();
642
+ initTabButtons.call(this);
643
+ fireCustomEvent(self, "monster-tab-remove", {
644
+ reference,
645
+ });
646
+ }
647
+ }
648
+ }
649
+ }
650
+ };
651
+
652
+ this[navElementSymbol].addEventListener("touch", this[changeTabEventHandler]);
653
+ this[navElementSymbol].addEventListener("click", this[changeTabEventHandler]);
654
+
655
+ this[navElementSymbol].addEventListener("touch", this[removeTabEventHandler]);
656
+ this[navElementSymbol].addEventListener("click", this[removeTabEventHandler]);
657
+
658
+ /**
659
+ * @param {Event} event
660
+ */
661
+ this[closeEventHandler] = (event) => {
662
+ const path = event.composedPath();
663
+
664
+ for (const [, element] of Object.entries(path)) {
665
+ if (element === this) {
666
+ return;
667
+ }
668
+ }
669
+
670
+ hidePopper.call(this);
671
+ };
672
+
673
+ return this;
626
674
  }
627
675
 
628
676
  /**
@@ -630,37 +678,37 @@ function initEventHandler() {
630
678
  * @param observedNode
631
679
  */
632
680
  function attachTabMutationObserver(observedNode) {
633
- const self = this;
634
-
635
- if (hasObjectLink(observedNode, mutationObserverSymbol)) {
636
- return;
637
- }
638
-
639
- /**
640
- * this construct monitors a node whether it is disabled or modified
641
- * @type {MutationObserver}
642
- */
643
- const observer = new MutationObserver(function (mutations) {
644
- if (isArray(mutations)) {
645
- const mutation = mutations.pop();
646
- if (mutation instanceof MutationRecord) {
647
- initTabButtons.call(self);
648
- }
649
- }
650
- });
651
-
652
- observer.observe(observedNode, {
653
- childList: false,
654
- attributes: true,
655
- subtree: false,
656
- attributeFilter: [
657
- "disabled",
658
- ATTRIBUTE_BUTTON_LABEL,
659
- `${ATTRIBUTE_PREFIX}button-icon`,
660
- ],
661
- });
662
-
663
- addToObjectLink(observedNode, mutationObserverSymbol, observer);
681
+ const self = this;
682
+
683
+ if (hasObjectLink(observedNode, mutationObserverSymbol)) {
684
+ return;
685
+ }
686
+
687
+ /**
688
+ * this construct monitors a node whether it is disabled or modified
689
+ * @type {MutationObserver}
690
+ */
691
+ const observer = new MutationObserver(function (mutations) {
692
+ if (isArray(mutations)) {
693
+ const mutation = mutations.pop();
694
+ if (mutation instanceof MutationRecord) {
695
+ initTabButtons.call(self);
696
+ }
697
+ }
698
+ });
699
+
700
+ observer.observe(observedNode, {
701
+ childList: false,
702
+ attributes: true,
703
+ subtree: false,
704
+ attributeFilter: [
705
+ "disabled",
706
+ ATTRIBUTE_BUTTON_LABEL,
707
+ `${ATTRIBUTE_PREFIX}button-icon`,
708
+ ],
709
+ });
710
+
711
+ addToObjectLink(observedNode, mutationObserverSymbol, observer);
664
712
  }
665
713
 
666
714
  /**
@@ -669,22 +717,22 @@ function attachTabMutationObserver(observedNode) {
669
717
  * @throws {Error} no shadow-root is defined
670
718
  */
671
719
  function initControlReferences() {
672
- if (!this.shadowRoot) {
673
- throw new Error("no shadow-root is defined");
674
- }
675
-
676
- this[controlElementSymbol] = this.shadowRoot.querySelector(
677
- `[${ATTRIBUTE_ROLE}=control]`,
678
- );
679
- this[navElementSymbol] = this.shadowRoot.querySelector(
680
- `nav[${ATTRIBUTE_ROLE}=nav]`,
681
- );
682
- this[popperElementSymbol] = this.shadowRoot.querySelector(
683
- `[${ATTRIBUTE_ROLE}=popper]`,
684
- );
685
- this[popperNavElementSymbol] = this.shadowRoot.querySelector(
686
- `[${ATTRIBUTE_ROLE}=popper-nav]`,
687
- );
720
+ if (!this.shadowRoot) {
721
+ throw new Error("no shadow-root is defined");
722
+ }
723
+
724
+ this[controlElementSymbol] = this.shadowRoot.querySelector(
725
+ `[${ATTRIBUTE_ROLE}=control]`,
726
+ );
727
+ this[navElementSymbol] = this.shadowRoot.querySelector(
728
+ `nav[${ATTRIBUTE_ROLE}=nav]`,
729
+ );
730
+ this[popperElementSymbol] = this.shadowRoot.querySelector(
731
+ `[${ATTRIBUTE_ROLE}=popper]`,
732
+ );
733
+ this[popperNavElementSymbol] = this.shadowRoot.querySelector(
734
+ `[${ATTRIBUTE_ROLE}=popper-nav]`,
735
+ );
688
736
  }
689
737
 
690
738
  /**
@@ -694,101 +742,102 @@ function initControlReferences() {
694
742
  *
695
743
  */
696
744
  function initTabButtons() {
697
- if (!this.shadowRoot) {
698
- throw new Error("no shadow-root is defined");
699
- }
700
-
701
- let activeReference;
702
-
703
- const dimensionsCalculated = this[dimensionsSymbol].getVia(
704
- "data.calculated",
705
- false,
706
- );
707
-
708
- const buttons = [];
709
- const nodes = getSlottedElements.call(this, undefined, null); // null ↦ only unnamed slots
710
-
711
- for (const node of nodes) {
712
- if (!(node instanceof HTMLElement)) continue;
713
- let label = getButtonLabel.call(this, node);
714
-
715
- let reference;
716
- if (node.hasAttribute("id")) {
717
- reference = node.getAttribute("id");
718
- }
719
-
720
- let disabled;
721
- if (node.hasAttribute("disabled") || node.disabled === true) {
722
- disabled = true;
723
- }
724
-
725
- if (!reference) {
726
- reference = new ID("tab").toString();
727
- node.setAttribute("id", reference);
728
- }
729
-
730
- if (node.hasAttribute(`${ATTRIBUTE_PREFIX}button-icon`)) {
731
- label = `<span part="label">${label}</span><img part="icon" src="${node.getAttribute(
732
- `${ATTRIBUTE_PREFIX}button-icon`,
733
- )}">`;
734
- }
735
-
736
- let remove = false;
737
- if (node.hasAttribute(`${ATTRIBUTE_PREFIX}removable`)) {
738
- remove = true;
739
- }
740
-
741
- if (node.matches(".active") === true && disabled !== true) {
742
- node.classList.remove("active");
743
- activeReference = reference;
744
- }
745
-
746
- const state = "";
747
- const classes = dimensionsCalculated ? "" : "invisible";
748
-
749
- buttons.push({
750
- reference,
751
- label,
752
- state,
753
- class: classes,
754
- disabled,
755
- remove,
756
- });
757
-
758
- attachTabMutationObserver.call(this, node);
759
- }
760
-
761
- this.setOption("buttons.standard", clone(buttons));
762
- this.setOption("buttons.popper", []);
763
- this.setOption("marker", random());
764
-
765
- return adjustButtonVisibility.call(this).then(() => {
766
- if (activeReference) {
767
- return new Processing(() => {
768
- const button = this.shadowRoot.querySelector(
769
- `[${ATTRIBUTE_PREFIX}tab-reference="${activeReference}"]`,
770
- );
771
- if (button instanceof HTMLButtonElement && button.disabled !== true) {
772
- show.call(this, button);
773
- }
774
- })
775
- .run(undefined)
776
- .then(() => {})
777
- .catch((e) => {
778
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
779
- });
780
- }
781
-
782
- return Promise.resolve();
783
- });
745
+ if (!this.shadowRoot) {
746
+ throw new Error("no shadow-root is defined");
747
+ }
748
+
749
+ let activeReference;
750
+
751
+ const dimensionsCalculated = this[dimensionsSymbol].getVia(
752
+ "data.calculated",
753
+ false,
754
+ );
755
+
756
+ const buttons = [];
757
+ const nodes = getSlottedElements.call(this, undefined, null); // null ↦ only unnamed slots
758
+
759
+ for (const node of nodes) {
760
+ if (!(node instanceof HTMLElement)) continue;
761
+ let label = getButtonLabel.call(this, node);
762
+
763
+ let reference;
764
+ if (node.hasAttribute("id")) {
765
+ reference = node.getAttribute("id");
766
+ }
767
+
768
+ let disabled;
769
+ if (node.hasAttribute("disabled") || node.disabled === true) {
770
+ disabled = true;
771
+ }
772
+
773
+ if (!reference) {
774
+ reference = new ID("tab").toString();
775
+ node.setAttribute("id", reference);
776
+ }
777
+
778
+ if (node.hasAttribute(`${ATTRIBUTE_PREFIX}button-icon`)) {
779
+ label = `<span part="label">${label}</span><img part="icon" src="${node.getAttribute(
780
+ `${ATTRIBUTE_PREFIX}button-icon`,
781
+ )}">`;
782
+ }
783
+
784
+ let remove = false;
785
+ if (node.hasAttribute(`${ATTRIBUTE_PREFIX}removable`)) {
786
+ remove = true;
787
+ }
788
+
789
+ if (node.matches(".active") === true && disabled !== true) {
790
+ node.classList.remove("active");
791
+ activeReference = reference;
792
+ }
793
+
794
+ const state = "";
795
+ const classes = dimensionsCalculated ? "" : "invisible";
796
+
797
+ buttons.push({
798
+ reference,
799
+ label,
800
+ state,
801
+ class: classes,
802
+ disabled,
803
+ remove,
804
+ });
805
+
806
+ attachTabMutationObserver.call(this, node);
807
+ }
808
+
809
+ this.setOption("buttons.standard", clone(buttons));
810
+ this.setOption("buttons.popper", []);
811
+ this.setOption("marker", random());
812
+
813
+ return adjustButtonVisibility.call(this).then(() => {
814
+ if (activeReference) {
815
+ return new Processing(() => {
816
+ const button = this.shadowRoot.querySelector(
817
+ `[${ATTRIBUTE_PREFIX}tab-reference="${activeReference}"]`,
818
+ );
819
+ if (button instanceof HTMLButtonElement && button.disabled !== true) {
820
+ show.call(this, button);
821
+ }
822
+ })
823
+ .run(undefined)
824
+ .then(() => {
825
+ })
826
+ .catch((e) => {
827
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
828
+ });
829
+ }
830
+
831
+ return Promise.resolve();
832
+ });
784
833
  }
785
834
 
786
835
  function checkAndRearrangeButtons() {
787
- if (this[dimensionsSymbol].getVia("data.calculated", false) !== true) {
788
- calculateNavigationButtonsDimensions.call(this);
789
- }
836
+ if (this[dimensionsSymbol].getVia("data.calculated", false) !== true) {
837
+ calculateNavigationButtonsDimensions.call(this);
838
+ }
790
839
 
791
- rearrangeButtons.call(this);
840
+ rearrangeButtons.call(this);
792
841
  }
793
842
 
794
843
  /**
@@ -796,29 +845,29 @@ function checkAndRearrangeButtons() {
796
845
  * @return {Promise<unknown>}
797
846
  */
798
847
  function adjustButtonVisibility() {
799
- const self = this;
848
+ const self = this;
800
849
 
801
- return new Promise((resolve) => {
802
- const observer = new MutationObserver(function (mutations) {
803
- const defCount = self.getOption("buttons.standard").length;
804
- const domCount = self[navElementSymbol].querySelectorAll(
805
- 'button[data-monster-role="button"]',
806
- ).length;
850
+ return new Promise((resolve) => {
851
+ const observer = new MutationObserver(function (mutations) {
852
+ const defCount = self.getOption("buttons.standard").length;
853
+ const domCount = self[navElementSymbol].querySelectorAll(
854
+ 'button[data-monster-role="button"]',
855
+ ).length;
807
856
 
808
- // in drawing
809
- if (defCount !== domCount) return;
857
+ // in drawing
858
+ if (defCount !== domCount) return;
810
859
 
811
- observer.disconnect();
860
+ observer.disconnect();
812
861
 
813
- checkAndRearrangeButtons.call(self);
862
+ checkAndRearrangeButtons.call(self);
814
863
 
815
- resolve();
816
- });
864
+ resolve();
865
+ });
817
866
 
818
- observer.observe(self[navElementSymbol], {
819
- attributes: true,
820
- });
821
- });
867
+ observer.observe(self[navElementSymbol], {
868
+ attributes: true,
869
+ });
870
+ });
822
871
  }
823
872
 
824
873
  /**
@@ -827,17 +876,17 @@ function adjustButtonVisibility() {
827
876
  * @return {number}
828
877
  */
829
878
  function getDimValue(value) {
830
- if ([undefined, null].indexOf(value) !== -1) {
831
- return 0;
832
- }
879
+ if ([undefined, null].indexOf(value) !== -1) {
880
+ return 0;
881
+ }
833
882
 
834
- const valueAsInt = parseInt(value, 10);
883
+ const valueAsInt = parseInt(value, 10);
835
884
 
836
- if (isNaN(valueAsInt)) {
837
- return 0;
838
- }
885
+ if (isNaN(valueAsInt)) {
886
+ return 0;
887
+ }
839
888
 
840
- return valueAsInt;
889
+ return valueAsInt;
841
890
  }
842
891
 
843
892
  /**
@@ -846,18 +895,18 @@ function getDimValue(value) {
846
895
  * @return {number}
847
896
  */
848
897
  function calcBoxWidth(node) {
849
- const dim = getGlobal("window").getComputedStyle(node);
850
- const bounding = node.getBoundingClientRect();
851
-
852
- return (
853
- getDimValue(dim["border-left-width"]) +
854
- getDimValue(dim["padding-left"]) +
855
- getDimValue(dim["margin-left"]) +
856
- getDimValue(bounding["width"]) +
857
- getDimValue(dim["border-right-width"]) +
858
- getDimValue(dim["margin-right"]) +
859
- getDimValue(dim["padding-left"])
860
- );
898
+ const dim = getGlobal("window").getComputedStyle(node);
899
+ const bounding = node.getBoundingClientRect();
900
+
901
+ return (
902
+ getDimValue(dim["border-left-width"]) +
903
+ getDimValue(dim["padding-left"]) +
904
+ getDimValue(dim["margin-left"]) +
905
+ getDimValue(bounding["width"]) +
906
+ getDimValue(dim["border-right-width"]) +
907
+ getDimValue(dim["margin-right"]) +
908
+ getDimValue(dim["padding-left"])
909
+ );
861
910
  }
862
911
 
863
912
  /**
@@ -865,35 +914,35 @@ function calcBoxWidth(node) {
865
914
  * @return {Object}
866
915
  */
867
916
  function rearrangeButtons() {
868
- const standardButtons = [];
869
- const popperButtons = [];
870
-
871
- let sum = 0;
872
- const space = this[dimensionsSymbol].getVia("data.space");
873
-
874
- const buttons = this.getOption("buttons.standard");
875
- for (const [, button] of buttons.entries()) {
876
- const ref = button?.reference;
877
-
878
- sum += this[dimensionsSymbol].getVia(`data.button.${ref}`);
879
-
880
- if (sum > space) {
881
- popperButtons.push(clone(button));
882
- } else {
883
- standardButtons.push(clone(button));
884
- }
885
- }
886
-
887
- this.setOption("buttons.standard", standardButtons);
888
- this.setOption("buttons.popper", popperButtons);
889
-
890
- if (this[switchElementSymbol]) {
891
- if (popperButtons.length > 0) {
892
- this[switchElementSymbol].classList.remove("hidden");
893
- } else {
894
- this[switchElementSymbol].classList.add("hidden");
895
- }
896
- }
917
+ const standardButtons = [];
918
+ const popperButtons = [];
919
+
920
+ let sum = 0;
921
+ const space = this[dimensionsSymbol].getVia("data.space");
922
+
923
+ const buttons = this.getOption("buttons.standard");
924
+ for (const [, button] of buttons.entries()) {
925
+ const ref = button?.reference;
926
+
927
+ sum += this[dimensionsSymbol].getVia(`data.button.${ref}`);
928
+
929
+ if (sum > space) {
930
+ popperButtons.push(clone(button));
931
+ } else {
932
+ standardButtons.push(clone(button));
933
+ }
934
+ }
935
+
936
+ this.setOption("buttons.standard", standardButtons);
937
+ this.setOption("buttons.popper", popperButtons);
938
+
939
+ if (this[switchElementSymbol]) {
940
+ if (popperButtons.length > 0) {
941
+ this[switchElementSymbol].classList.remove("hidden");
942
+ } else {
943
+ this[switchElementSymbol].classList.add("hidden");
944
+ }
945
+ }
897
946
  }
898
947
 
899
948
  /**
@@ -901,50 +950,50 @@ function rearrangeButtons() {
901
950
  * @return {Object}
902
951
  */
903
952
  function calculateNavigationButtonsDimensions() {
904
- const width = this[navElementSymbol].getBoundingClientRect().width;
905
-
906
- let startEndWidth = 0;
907
-
908
- getSlottedElements.call(this, undefined, "start").forEach((node) => {
909
- startEndWidth += calcBoxWidth.call(this, node);
910
- });
911
-
912
- getSlottedElements.call(this, undefined, "end").forEach((node) => {
913
- startEndWidth += calcBoxWidth.call(this, node);
914
- });
915
-
916
- this[dimensionsSymbol].setVia("data.space", width - startEndWidth - 2);
917
- this[dimensionsSymbol].setVia("data.visible", !(width === 0));
918
-
919
- const buttons = this.getOption("buttons.standard").concat(
920
- this.getOption("buttons.popper"),
921
- );
922
-
923
- for (const [i, button] of buttons.entries()) {
924
- const ref = button?.reference;
925
- const element = this[navElementSymbol].querySelector(
926
- `:scope > [${ATTRIBUTE_PREFIX}tab-reference="${ref}"]`,
927
- );
928
- if (!(element instanceof HTMLButtonElement)) continue;
929
-
930
- this[dimensionsSymbol].setVia(
931
- `data.button.${ref}`,
932
- calcBoxWidth.call(this, element),
933
- );
934
- button["class"] = new TokenList(button["class"])
935
- .remove("invisible")
936
- .toString();
937
- }
938
-
939
- const slots = this[controlElementSymbol].querySelectorAll(
940
- `nav[${ATTRIBUTE_PREFIX}role=nav] > slot.invisible, slot[${ATTRIBUTE_PREFIX}role=slot].invisible`,
941
- );
942
- for (const [, slot] of slots.entries()) {
943
- slot.classList.remove("invisible");
944
- }
945
-
946
- this[dimensionsSymbol].setVia("data.calculated", true);
947
- this.setOption("buttons.standard", clone(buttons));
953
+ const width = this[navElementSymbol].getBoundingClientRect().width;
954
+
955
+ let startEndWidth = 0;
956
+
957
+ getSlottedElements.call(this, undefined, "start").forEach((node) => {
958
+ startEndWidth += calcBoxWidth.call(this, node);
959
+ });
960
+
961
+ getSlottedElements.call(this, undefined, "end").forEach((node) => {
962
+ startEndWidth += calcBoxWidth.call(this, node);
963
+ });
964
+
965
+ this[dimensionsSymbol].setVia("data.space", width - startEndWidth - 2);
966
+ this[dimensionsSymbol].setVia("data.visible", !(width === 0));
967
+
968
+ const buttons = this.getOption("buttons.standard").concat(
969
+ this.getOption("buttons.popper"),
970
+ );
971
+
972
+ for (const [i, button] of buttons.entries()) {
973
+ const ref = button?.reference;
974
+ const element = this[navElementSymbol].querySelector(
975
+ `:scope > [${ATTRIBUTE_PREFIX}tab-reference="${ref}"]`,
976
+ );
977
+ if (!(element instanceof HTMLButtonElement)) continue;
978
+
979
+ this[dimensionsSymbol].setVia(
980
+ `data.button.${ref}`,
981
+ calcBoxWidth.call(this, element),
982
+ );
983
+ button["class"] = new TokenList(button["class"])
984
+ .remove("invisible")
985
+ .toString();
986
+ }
987
+
988
+ const slots = this[controlElementSymbol].querySelectorAll(
989
+ `nav[${ATTRIBUTE_PREFIX}role=nav] > slot.invisible, slot[${ATTRIBUTE_PREFIX}role=slot].invisible`,
990
+ );
991
+ for (const [, slot] of slots.entries()) {
992
+ slot.classList.remove("invisible");
993
+ }
994
+
995
+ this[dimensionsSymbol].setVia("data.calculated", true);
996
+ this.setOption("buttons.standard", clone(buttons));
948
997
  }
949
998
 
950
999
  /**
@@ -953,34 +1002,34 @@ function calculateNavigationButtonsDimensions() {
953
1002
  * @return {string}
954
1003
  */
955
1004
  function getButtonLabel(node) {
956
- let label;
957
- let setLabel = false;
958
- if (node.hasAttribute(ATTRIBUTE_BUTTON_LABEL)) {
959
- label = node.getAttribute(ATTRIBUTE_BUTTON_LABEL);
960
- } else {
961
- label = node.innerText;
962
- setLabel = true;
963
- }
964
-
965
- if (!isString(label)) {
966
- label = "";
967
- }
968
-
969
- label = label.trim();
970
-
971
- if (label === "") {
972
- label = this.getOption("labels.new-tab-label", "New Tab");
973
- }
974
-
975
- if (label.length > 100) {
976
- label = `${label.substring(0, 99)}…`;
977
- }
978
-
979
- if (setLabel === true) {
980
- node.setAttribute(ATTRIBUTE_BUTTON_LABEL, label);
981
- }
982
-
983
- return label;
1005
+ let label;
1006
+ let setLabel = false;
1007
+ if (node.hasAttribute(ATTRIBUTE_BUTTON_LABEL)) {
1008
+ label = node.getAttribute(ATTRIBUTE_BUTTON_LABEL);
1009
+ } else {
1010
+ label = node.innerText;
1011
+ setLabel = true;
1012
+ }
1013
+
1014
+ if (!isString(label)) {
1015
+ label = "";
1016
+ }
1017
+
1018
+ label = label.trim();
1019
+
1020
+ if (label === "") {
1021
+ label = this.getOption("labels.new-tab-label", "New Tab");
1022
+ }
1023
+
1024
+ if (label.length > 100) {
1025
+ label = `${label.substring(0, 99)}…`;
1026
+ }
1027
+
1028
+ if (setLabel === true) {
1029
+ node.setAttribute(ATTRIBUTE_BUTTON_LABEL, label);
1030
+ }
1031
+
1032
+ return label;
984
1033
  }
985
1034
 
986
1035
  /**
@@ -988,12 +1037,13 @@ function getButtonLabel(node) {
988
1037
  * @return {string}
989
1038
  */
990
1039
  function getTemplate() {
991
- // language=HTML
992
- return `
1040
+ // language=HTML
1041
+ return `
993
1042
  <template id="buttons">
994
1043
  <button part="button"
995
1044
  data-monster-role="button"
996
1045
  data-monster-attributes="
1046
+ class path:classes.button,
997
1047
  data-monster-state path:buttons.state,
998
1048
  disabled path:buttons.disabled | if:true,
999
1049
  data-monster-tab-reference path:buttons.reference"><span