@schukai/monster 3.53.0 → 3.55.0

Sign up to get free protection for your applications and to get access to all the features.
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