@schukai/monster 3.95.2 → 3.96.1

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