@schukai/monster 4.137.9 → 4.139.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,144 +13,11 @@
13
13
  */
14
14
 
15
15
  import { instanceSymbol } from "../../constants.mjs";
16
- import { Pathfinder } from "../../data/pathfinder.mjs";
17
- import {
18
- addAttributeToken,
19
- removeAttributeToken,
20
- } from "../../dom/attributes.mjs";
21
- import {
22
- ATTRIBUTE_ERRORMESSAGE,
23
- ATTRIBUTE_ROLE,
24
- } from "../../dom/constants.mjs";
25
- import {
26
- assembleMethodSymbol,
27
- getSlottedElements,
28
- registerCustomElement,
29
- } from "../../dom/customelement.mjs";
30
- import {
31
- CustomElement,
32
- attributeObserverSymbol,
33
- } from "../../dom/customelement.mjs";
34
- import { findTargetElementFromEvent } from "../../dom/events.mjs";
35
- import { getDocument } from "../../dom/util.mjs";
36
- import { getGlobal } from "../../types/global.mjs";
37
- import { ID } from "../../types/id.mjs";
38
- import { Observer } from "../../types/observer.mjs";
39
- import { STYLE_DISPLAY_MODE_BLOCK } from "./constants.mjs";
16
+ import { registerCustomElement } from "../../dom/customelement.mjs";
40
17
  import { ButtonBarStyleSheet } from "./stylesheet/button-bar.mjs";
41
- import { positionPopper } from "./util/floating-ui.mjs";
42
- import { convertToPixels } from "../../dom/dimension.mjs";
43
- import { addErrorAttribute } from "../../dom/error.mjs";
44
- import { Processing } from "../../util/processing.mjs";
45
- export { ButtonBar };
46
-
47
- /**
48
- * @private
49
- * @type {symbol}
50
- */
51
- /**
52
- * local symbol
53
- * @private
54
- * @type {symbol}
55
- */
56
- const resizeObserverSymbol = Symbol("windowResizeObserver");
57
-
58
- /**
59
- * @private
60
- * @type {symbol}
61
- */
62
- const dimensionsSymbol = Symbol("dimensions");
63
-
64
- /**
65
- * @private
66
- * @type {symbol}
67
- */
68
- const controlElementSymbol = Symbol("controlElement");
69
-
70
- /**
71
- * @private
72
- * @type {symbol}
73
- */
74
- const buttonBarSlotElementSymbol = Symbol("buttonBarSlotElement");
75
-
76
- /**
77
- * @private
78
- * @type {symbol}
79
- */
80
- const popperSlotElementSymbol = Symbol("popperSlotElement");
81
-
82
- /**
83
- * @private
84
- * @type {symbol}
85
- */
86
- const buttonBarElementSymbol = Symbol("buttonBarElement");
87
-
88
- /**
89
- * @private
90
- * @type {symbol}
91
- */
92
- const popperElementSymbol = Symbol("popperElement");
93
-
94
- /**
95
- * local symbol
96
- * @private
97
- * @type {symbol}
98
- */
99
- const closeEventHandler = Symbol("closeEventHandler");
100
-
101
- /**
102
- * @private
103
- * @type {symbol}
104
- */
105
- const popperSwitchEventHandler = Symbol("popperSwitchEventHandler");
106
-
107
- /**
108
- * @private
109
- * @type {symbol}
110
- */
111
- const popperNavElementSymbol = Symbol("popperNavElement");
112
-
113
- /**
114
- * @private
115
- * @type {symbol}
116
- */
117
- const mutationObserverSymbol = Symbol("mutationObserver");
118
-
119
- /**
120
- * @private
121
- * @type {symbol}
122
- */
123
- const switchElementSymbol = Symbol("switchElement");
18
+ import { ControlBar } from "./control-bar.mjs";
124
19
 
125
- /**
126
- * @private
127
- * @type {symbol}
128
- */
129
- const layoutStateSymbol = Symbol("layoutState");
130
- const layoutFrameSymbol = Symbol("layoutFrame");
131
- const layoutTokenSymbol = Symbol("layoutToken");
132
- const observedLayoutNodesSignatureSymbol = Symbol(
133
- "observedLayoutNodesSignature",
134
- );
135
-
136
- /**
137
- * @private
138
- * @type {WeakMap<HTMLElement, number>}
139
- */
140
- const layoutNodeIds = new WeakMap();
141
- let layoutNodeId = 0;
142
-
143
- /**
144
- * @private
145
- * @type {string}
146
- */
147
- const ATTRIBUTE_POPPER_POSITION = "data-monster-popper-position";
148
-
149
- /**
150
- * @private
151
- * @type {string}
152
- */
153
- const ATTRIBUTE_LAYOUT_ALIGNMENT = "data-monster-layout-alignment";
20
+ export { ButtonBar };
154
21
 
155
22
  /**
156
23
  * A button bar control.
@@ -163,7 +30,7 @@ const ATTRIBUTE_LAYOUT_ALIGNMENT = "data-monster-layout-alignment";
163
30
  * @summary A responsive button bar that groups multiple actions and moves overflowed buttons into a menu.
164
31
  * @fires monster-fetched
165
32
  */
166
- class ButtonBar extends CustomElement {
33
+ class ButtonBar extends ControlBar {
167
34
  /**
168
35
  * This method is called by the `instanceof` operator.
169
36
  * @return {symbol}
@@ -174,66 +41,15 @@ class ButtonBar extends CustomElement {
174
41
 
175
42
  /**
176
43
  * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
177
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
178
- *
179
- * The individual configuration values can be found in the table.
180
44
  *
181
- * @property {Object} templates Template definitions
182
- * @property {string} templates.main Main template
183
- * @property {Object} labels
184
- * @property {Object} popper FloatingUI popper configuration
185
- * @property {string} popper.placement=top Placement of the popper
186
- * @property {Array<string>} popper.middleware Middleware for the popper
45
+ * @return {Object}
187
46
  */
188
47
  get defaults() {
189
- const obj = Object.assign({}, super.defaults, {
48
+ return Object.assign({}, super.defaults, {
190
49
  templates: {
191
50
  main: getTemplate(),
192
51
  },
193
- labels: {},
194
- layout: {
195
- alignment: "left",
196
- },
197
- popper: {
198
- placement: "left",
199
- middleware: ["flip", "shift", "offset:5"],
200
- },
201
52
  });
202
-
203
- initDefaultsFromAttributes.call(this, obj);
204
-
205
- return obj;
206
- }
207
-
208
- /**
209
- * This method is called internal and should not be called directly.
210
- */
211
- [assembleMethodSymbol]() {
212
- super[assembleMethodSymbol]();
213
-
214
- this[dimensionsSymbol] = new Pathfinder({ data: {} });
215
- this[layoutStateSymbol] = {
216
- scheduled: false,
217
- running: false,
218
- needsMeasure: true,
219
- needsLayout: true,
220
- needsObserve: true,
221
- suppressSlotChange: false,
222
- suppressMutation: false,
223
- };
224
-
225
- initControlReferences.call(this);
226
- initEventHandler.call(this);
227
-
228
- // setup structure
229
- initButtonBar.call(this);
230
- initPopperSwitch.call(this);
231
- applyLayoutAlignment.call(this);
232
- this.attachObserver(
233
- new Observer(() => {
234
- applyLayoutAlignment.call(this);
235
- }),
236
- );
237
53
  }
238
54
 
239
55
  /**
@@ -242,7 +58,7 @@ class ButtonBar extends CustomElement {
242
58
  * @return {CSSStyleSheet[]}
243
59
  */
244
60
  static getCSSStyleSheet() {
245
- return [ButtonBarStyleSheet];
61
+ return [...super.getCSSStyleSheet(), ButtonBarStyleSheet];
246
62
  }
247
63
 
248
64
  /**
@@ -253,871 +69,6 @@ class ButtonBar extends CustomElement {
253
69
  static getTag() {
254
70
  return "monster-button-bar";
255
71
  }
256
-
257
- /**
258
- * This method is called by the dom and should not be called directly.
259
- *
260
- * @return {void}
261
- */
262
- connectedCallback() {
263
- super.connectedCallback();
264
-
265
- const document = getDocument();
266
-
267
- for (const [, type] of Object.entries(["click", "touch"])) {
268
- // close on outside ui-events
269
- document.addEventListener(type, this[closeEventHandler]);
270
- }
271
-
272
- scheduleLayout.call(this, { measure: true, layout: true, observe: true });
273
- }
274
-
275
- /**
276
- * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
277
- *
278
- * @return {string[]}
279
- */
280
- static get observedAttributes() {
281
- const attributes = super.observedAttributes;
282
- attributes.push(ATTRIBUTE_POPPER_POSITION);
283
- return attributes;
284
- }
285
-
286
- /**
287
- * This method is called by the dom and should not be called directly.
288
- *
289
- * @return {void}
290
- */
291
- disconnectedCallback() {
292
- super.disconnectedCallback();
293
-
294
- const document = getDocument();
295
-
296
- // close on outside ui-events
297
- for (const [, type] of Object.entries(["click", "touch"])) {
298
- document.removeEventListener(type, this[closeEventHandler]);
299
- }
300
-
301
- if (typeof this[layoutFrameSymbol] === "number") {
302
- cancelAnimationFrame(this[layoutFrameSymbol]);
303
- }
304
- delete this[layoutFrameSymbol];
305
- this[layoutTokenSymbol] = (this[layoutTokenSymbol] || 0) + 1;
306
-
307
- disconnectResizeObserver.call(this);
308
- if (this[mutationObserverSymbol]) {
309
- this[mutationObserverSymbol].disconnect();
310
- }
311
- }
312
-
313
- /**
314
- * Close the slotted dialog.
315
- * @return {ButtonBar}
316
- */
317
- hideDialog() {
318
- hide.call(this);
319
- return this;
320
- }
321
-
322
- /**
323
- * Open the slotted dialog.
324
- * @return {ButtonBar}
325
- */
326
- showDialog() {
327
- show.call(this);
328
- return this;
329
- }
330
-
331
- /**
332
- * Toggle the slotted dialog.
333
- * @return {ButtonBar}
334
- */
335
- toggleDialog() {
336
- toggle.call(this);
337
- return this;
338
- }
339
- }
340
-
341
- /**
342
- * @private
343
- * @param obj
344
- * @return {*}
345
- */
346
- function initDefaultsFromAttributes(obj) {
347
- if (this.hasAttribute(ATTRIBUTE_POPPER_POSITION)) {
348
- obj.popper.placement = this.getAttribute(ATTRIBUTE_POPPER_POSITION);
349
- }
350
-
351
- return obj;
352
- }
353
-
354
- /**
355
- * @private
356
- * @param {HTMLElement} element
357
- * @return {boolean}
358
- */
359
- function isElementTrulyVisible(element) {
360
- if (!(element instanceof HTMLElement)) {
361
- return false;
362
- }
363
- const computedStyle = getComputedStyle(element);
364
- return (
365
- computedStyle.display !== "none" &&
366
- computedStyle.visibility !== "hidden" &&
367
- computedStyle.opacity !== "0" &&
368
- element.offsetWidth > 0 &&
369
- element.offsetHeight > 0
370
- );
371
- }
372
-
373
- /**
374
- * @private
375
- * @param {HTMLElement} element
376
- * @return {boolean}
377
- */
378
- function isElementSelfHidden(element) {
379
- if (!(element instanceof HTMLElement)) {
380
- return true;
381
- }
382
-
383
- const computedStyle = getComputedStyle(element);
384
- return (
385
- element.hidden === true ||
386
- element.hasAttribute("hidden") ||
387
- computedStyle.display === "none" ||
388
- computedStyle.visibility === "hidden"
389
- );
390
- }
391
-
392
- /**
393
- * @private
394
- */
395
- function initEventHandler() {
396
- const self = this;
397
-
398
- const mutationCallback = (mutationList) => {
399
- if (self[layoutStateSymbol]?.suppressMutation) {
400
- return;
401
- }
402
-
403
- let needsRecalc = false;
404
- for (const mutation of mutationList) {
405
- if (mutation.type === "attributes") {
406
- const target = mutation.target;
407
- if (target instanceof HTMLElement) {
408
- const ref = target.getAttribute("data-monster-reference");
409
- if (ref) {
410
- if (!isElementTrulyVisible(target)) {
411
- self[dimensionsSymbol].setVia(`data.button.${ref}`, 0);
412
- }
413
- needsRecalc = true;
414
- }
415
- }
416
- }
417
- }
418
- if (needsRecalc) {
419
- scheduleLayout.call(self, { measure: true, layout: true });
420
- }
421
- };
422
-
423
- /**
424
- * @param {Event} event
425
- */
426
- self[closeEventHandler] = (event) => {
427
- const path = event.composedPath();
428
- for (const element of path) {
429
- if (element === self) return;
430
- }
431
- hide.call(self);
432
- };
433
-
434
- if (self[buttonBarSlotElementSymbol]) {
435
- self[buttonBarSlotElementSymbol].addEventListener("slotchange", () => {
436
- if (self[layoutStateSymbol]?.suppressSlotChange) {
437
- return;
438
- }
439
- scheduleLayout.call(self, {
440
- measure: true,
441
- layout: true,
442
- observe: true,
443
- });
444
- });
445
- }
446
-
447
- if (self[popperElementSymbol]) {
448
- self[popperElementSymbol].addEventListener("slotchange", () => {
449
- if (self[layoutStateSymbol]?.suppressSlotChange) {
450
- return;
451
- }
452
- scheduleLayout.call(self, {
453
- measure: true,
454
- layout: true,
455
- observe: true,
456
- });
457
- });
458
- }
459
-
460
- self[attributeObserverSymbol][ATTRIBUTE_POPPER_POSITION] = function (value) {
461
- self.setOption("classes.button", value);
462
- };
463
-
464
- self[resizeObserverSymbol] = new ResizeObserver(() => {
465
- scheduleLayout.call(self, { measure: true, layout: true });
466
- });
467
- self[mutationObserverSymbol] = new MutationObserver(mutationCallback);
468
-
469
- initSlotChangedHandler.call(self);
470
- }
471
-
472
- function initSlotChangedHandler() {
473
- this[buttonBarElementSymbol].addEventListener("slotchange", () => {
474
- if (this[layoutStateSymbol]?.suppressSlotChange) {
475
- return;
476
- }
477
- scheduleLayout.call(this, { observe: true });
478
- });
479
- }
480
-
481
- function scheduleLayout(options = {}) {
482
- if (!this[layoutStateSymbol]) {
483
- return;
484
- }
485
-
486
- const state = this[layoutStateSymbol];
487
- state.needsMeasure = state.needsMeasure || options.measure === true;
488
- state.needsLayout = state.needsLayout || options.layout === true;
489
- state.needsObserve = state.needsObserve || options.observe === true;
490
-
491
- if (state.scheduled || state.running) {
492
- return;
493
- }
494
-
495
- scheduleLayoutFrame.call(this);
496
- }
497
-
498
- function scheduleLayoutFrame() {
499
- const state = this[layoutStateSymbol];
500
- if (!state || state.scheduled || state.running) {
501
- return;
502
- }
503
-
504
- state.scheduled = true;
505
- const token = (this[layoutTokenSymbol] || 0) + 1;
506
- this[layoutTokenSymbol] = token;
507
- this[layoutFrameSymbol] = requestAnimationFrame(() => {
508
- if (this[layoutTokenSymbol] !== token) {
509
- return;
510
- }
511
- delete this[layoutFrameSymbol];
512
- runLayout.call(this);
513
- });
514
- }
515
-
516
- function runLayout() {
517
- const state = this[layoutStateSymbol];
518
- if (!state) {
519
- return;
520
- }
521
-
522
- state.scheduled = false;
523
- if (!this.isConnected) {
524
- return;
525
- }
526
-
527
- if (state.running) {
528
- return;
529
- }
530
-
531
- const needsObserve = state.needsObserve;
532
- const needsMeasure = state.needsMeasure;
533
- const needsLayout = state.needsLayout;
534
-
535
- state.needsObserve = false;
536
- state.needsMeasure = false;
537
- state.needsLayout = false;
538
- state.running = true;
539
-
540
- new Processing(() => {
541
- if (needsObserve) {
542
- updateResizeObserverObservation.call(this);
543
- }
544
-
545
- if (needsMeasure) {
546
- try {
547
- calculateButtonBarDimensions.call(this);
548
- } catch (error) {
549
- addErrorAttribute(
550
- this,
551
- error?.message || "An error occurred while calculating dimensions",
552
- );
553
- }
554
- }
555
-
556
- if (needsLayout) {
557
- try {
558
- rearrangeButtons.call(this);
559
- } catch (error) {
560
- addErrorAttribute(
561
- this,
562
- error?.message || "An error occurred while rearranging the buttons",
563
- );
564
- }
565
- }
566
-
567
- return updatePopper.call(this);
568
- })
569
- .run()
570
- .catch((error) => {
571
- addErrorAttribute(
572
- this,
573
- error?.message ||
574
- "An error occurred while running the button bar layout",
575
- );
576
- })
577
- .finally(() => {
578
- state.running = false;
579
- if (state.needsObserve || state.needsMeasure || state.needsLayout) {
580
- scheduleLayoutFrame.call(this);
581
- }
582
- });
583
- }
584
-
585
- /**
586
- * @private
587
- * @return {Object}
588
- */
589
- function rearrangeButtons() {
590
- let space = 0;
591
- try {
592
- space = this[dimensionsSymbol].getVia("data.space");
593
- } catch {}
594
-
595
- const buttonReferences = this[dimensionsSymbol].getVia(
596
- "data.buttonReferences",
597
- [],
598
- );
599
- const hasButtons = buttonReferences.length > 0;
600
-
601
- const buttonEntries = [];
602
-
603
- for (const ref of buttonReferences) {
604
- let elements = getSlottedElements.call(
605
- this,
606
- '[data-monster-reference="' + ref + '"]',
607
- null,
608
- ); // null ↦ o
609
- if (elements.size === 0) {
610
- elements = getSlottedElements.call(
611
- this,
612
- '[data-monster-reference="' + ref + '"]',
613
- "popper",
614
- ); // null ↦ o
615
- }
616
-
617
- const nextValue = elements.values().next();
618
- if (!nextValue) {
619
- continue;
620
- }
621
-
622
- const element = nextValue?.value;
623
- if (!(element instanceof HTMLElement)) {
624
- continue;
625
- }
626
-
627
- let buttonWidth = 0;
628
- try {
629
- buttonWidth = this[dimensionsSymbol].getVia(`data.button.${ref}`);
630
- } catch (e) {
631
- // If the path does not exist, pathfinder throws an error.
632
- // In this case, we assume the width is 0.
633
- // This can happen for buttons that have never been visible.
634
- }
635
- buttonEntries.push({
636
- element,
637
- width: buttonWidth,
638
- hidden: isElementSelfHidden(element),
639
- });
640
- }
641
-
642
- const switchWidth = this[dimensionsSymbol].getVia("data.switchWidth") || 2;
643
-
644
- const layoutButtons = (availableSpace) => {
645
- if (availableSpace < 0) {
646
- availableSpace = 0;
647
- }
648
- let sum = 0;
649
- const visibleButtonsInMainSlot = [];
650
- const buttonsToMoveToPopper = [];
651
-
652
- for (const entry of buttonEntries) {
653
- if (entry.hidden) {
654
- visibleButtonsInMainSlot.push(entry.element);
655
- continue;
656
- }
657
-
658
- if (sum + entry.width > availableSpace) {
659
- buttonsToMoveToPopper.push(entry.element);
660
- } else {
661
- sum += entry.width;
662
- visibleButtonsInMainSlot.push(entry.element);
663
- }
664
- }
665
-
666
- return { visibleButtonsInMainSlot, buttonsToMoveToPopper };
667
- };
668
-
669
- let layout = layoutButtons(space);
670
- if (layout.buttonsToMoveToPopper.length > 0) {
671
- layout = layoutButtons(space - switchWidth);
672
- }
673
-
674
- const shouldShowSwitch =
675
- layout.buttonsToMoveToPopper.length > 0 && hasButtons;
676
-
677
- suppressLayoutFeedback.call(this);
678
-
679
- for (const button of layout.buttonsToMoveToPopper) {
680
- if (button.getAttribute("slot") !== "popper") {
681
- button.setAttribute("slot", "popper");
682
- }
683
- }
684
-
685
- for (const button of layout.visibleButtonsInMainSlot) {
686
- if (button.hasAttribute("slot")) {
687
- button.removeAttribute("slot");
688
- }
689
- }
690
-
691
- setSwitchVisible.call(this, shouldShowSwitch);
692
- if (!shouldShowSwitch) {
693
- hide.call(this);
694
- }
695
- }
696
-
697
- /**
698
- * @private
699
- * @param {HTMLElement} node
700
- * @return {number}
701
- */
702
- function calcBoxWidth(node) {
703
- const dim = getGlobal()?.getComputedStyle(node);
704
- if (dim === null) {
705
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "no computed style");
706
- throw new Error("no computed style");
707
- }
708
- const bounding = node.getBoundingClientRect();
709
-
710
- return (
711
- convertToPixels(dim["border-left-width"]) +
712
- convertToPixels(dim["padding-left"]) +
713
- convertToPixels(dim["margin-left"]) +
714
- bounding["width"] +
715
- convertToPixels(dim["border-right-width"]) +
716
- convertToPixels(dim["margin-right"]) +
717
- convertToPixels(dim["padding-left"])
718
- );
719
- }
720
-
721
- /**
722
- * @private
723
- * @return {Object}
724
- */
725
- function calculateButtonBarDimensions() {
726
- if (!(this.parentElement instanceof HTMLElement)) {
727
- this[dimensionsSymbol].setVia("data.space", 0);
728
- this[dimensionsSymbol].setVia("data.visible", false);
729
- this[dimensionsSymbol].setVia("data.calculated", true);
730
- this[dimensionsSymbol].setVia("data.buttonReferences", []);
731
- return;
732
- }
733
-
734
- const computedStyle = getComputedStyle(this.parentElement);
735
-
736
- if (computedStyle === null) {
737
- throw new Error("no computed style");
738
- }
739
-
740
- let width = this.parentElement.clientWidth;
741
- if (computedStyle.getPropertyValue("box-sizing") !== "border-box") {
742
- width = computedStyle.getPropertyValue("width");
743
-
744
- let pixel = 0;
745
- try {
746
- pixel = convertToPixels(width);
747
- } catch (e) {
748
- addErrorAttribute(
749
- this,
750
- e?.message || "An error occurred while calculating the dimensions",
751
- );
752
- }
753
-
754
- this[dimensionsSymbol].setVia("data.space", pixel);
755
- } else {
756
- let borderWidth = getComputedStyle(this).getPropertyValue(
757
- "--monster-border-width",
758
- );
759
- if (borderWidth === null || borderWidth === "") {
760
- borderWidth = "0px";
761
- }
762
-
763
- let borderWidthWithoutUnit = 0;
764
- try {
765
- borderWidthWithoutUnit = convertToPixels(borderWidth);
766
- } catch (e) {
767
- addErrorAttribute(
768
- this,
769
- e?.message || "An error occurred while calculating the dimensions",
770
- );
771
- }
772
-
773
- // space to be allocated
774
- this[dimensionsSymbol].setVia(
775
- "data.space",
776
- width - 2 * borderWidthWithoutUnit,
777
- );
778
- }
779
-
780
- this[dimensionsSymbol].setVia("data.visible", !(width === 0));
781
-
782
- const buttonReferences = [];
783
-
784
- // Get all buttons, regardless of their current slot
785
- const allButtons = Array.from(getSlottedElements.call(this, ":scope", null));
786
- const popperButtons = Array.from(
787
- getSlottedElements.call(this, ":scope", "popper"),
788
- );
789
-
790
- const combinedButtons = [...allButtons, ...popperButtons].filter(
791
- (button, index, self) => {
792
- // Filter out duplicates based on data-monster-reference if present, or element itself
793
- return (
794
- self.findIndex(
795
- (b) =>
796
- b.dataset.monsterReference === button.dataset.monsterReference ||
797
- b === button,
798
- ) === index
799
- );
800
- },
801
- );
802
-
803
- for (const button of combinedButtons) {
804
- if (!(button instanceof HTMLElement)) {
805
- continue;
806
- }
807
-
808
- if (!button.hasAttribute("data-monster-reference")) {
809
- button.setAttribute("data-monster-reference", new ID("btn").toString());
810
- }
811
-
812
- const ref = button.getAttribute("data-monster-reference");
813
- if (ref === null) continue;
814
-
815
- buttonReferences.push(ref);
816
-
817
- // Only calculate width for visible buttons. Assume invisible ones
818
- // (e.g. in popper) have their width calculated previously and stored.
819
- if (isElementTrulyVisible(button)) {
820
- this[dimensionsSymbol].setVia(
821
- `data.button.${ref}`,
822
- calcBoxWidth.call(this, button),
823
- );
824
- }
825
- }
826
-
827
- if (this[switchElementSymbol]) {
828
- this[dimensionsSymbol].setVia(
829
- "data.switchWidth",
830
- this[switchElementSymbol].offsetWidth,
831
- );
832
- }
833
-
834
- this[dimensionsSymbol].setVia("data.calculated", true);
835
- this[dimensionsSymbol].setVia("data.buttonReferences", buttonReferences);
836
- }
837
-
838
- /**
839
- * @private
840
- */
841
- function updateResizeObserverObservation() {
842
- const observedNodes = getLayoutObservedNodes.call(this);
843
- const signature = getLayoutObservedNodesSignature(observedNodes);
844
- if (this[observedLayoutNodesSignatureSymbol] === signature) {
845
- return;
846
- }
847
- this[observedLayoutNodesSignatureSymbol] = signature;
848
-
849
- this[resizeObserverSymbol].disconnect();
850
- if (this[mutationObserverSymbol]) {
851
- this[mutationObserverSymbol].disconnect();
852
- }
853
-
854
- observedNodes.forEach((node) => {
855
- this[resizeObserverSymbol].observe(node);
856
- if (node !== this.parentElement && this[mutationObserverSymbol]) {
857
- this[mutationObserverSymbol].observe(node, {
858
- attributes: true,
859
- attributeFilter: ["style", "class", "hidden"],
860
- });
861
- }
862
- });
863
- }
864
-
865
- /**
866
- * @private
867
- * @return {HTMLElement[]}
868
- */
869
- function getLayoutObservedNodes() {
870
- const observedNodes = [];
871
- const slottedNodes = getSlottedElements.call(this);
872
- slottedNodes.forEach((node) => {
873
- if (node instanceof HTMLElement) {
874
- observedNodes.push(node);
875
- }
876
- });
877
-
878
- let parent = this.parentNode;
879
- while (!(parent instanceof HTMLElement) && parent !== null) {
880
- parent = parent.parentNode;
881
- }
882
-
883
- if (parent instanceof HTMLElement) {
884
- observedNodes.push(parent);
885
- }
886
-
887
- return observedNodes;
888
- }
889
-
890
- /**
891
- * @private
892
- * @param {HTMLElement[]} nodes
893
- * @return {string}
894
- */
895
- function getLayoutObservedNodesSignature(nodes) {
896
- return nodes.map(getLayoutNodeId).join("|");
897
- }
898
-
899
- /**
900
- * @private
901
- * @param {HTMLElement} node
902
- * @return {number}
903
- */
904
- function getLayoutNodeId(node) {
905
- let id = layoutNodeIds.get(node);
906
- if (id === undefined) {
907
- id = ++layoutNodeId;
908
- layoutNodeIds.set(node, id);
909
- }
910
- return id;
911
- }
912
-
913
- /**
914
- * @private
915
- * @return {void}
916
- */
917
- function suppressLayoutFeedback() {
918
- const state = this[layoutStateSymbol];
919
- if (!state) {
920
- return;
921
- }
922
-
923
- state.suppressSlotChange = true;
924
- state.suppressMutation = true;
925
- queueMicrotask(() => {
926
- state.suppressSlotChange = false;
927
- state.suppressMutation = false;
928
- });
929
- }
930
-
931
- /**
932
- * @private
933
- * @param {boolean} visible
934
- * @return {void}
935
- */
936
- function setSwitchVisible(visible) {
937
- if (!(this[switchElementSymbol] instanceof HTMLElement)) {
938
- return;
939
- }
940
-
941
- if (visible) {
942
- if (this[switchElementSymbol].hasAttribute("hidden")) {
943
- this[switchElementSymbol].removeAttribute("hidden");
944
- }
945
- if (this[switchElementSymbol].classList.contains("hidden")) {
946
- this[switchElementSymbol].classList.remove("hidden");
947
- }
948
- return;
949
- }
950
-
951
- if (!this[switchElementSymbol].hasAttribute("hidden")) {
952
- this[switchElementSymbol].setAttribute("hidden", "");
953
- }
954
- if (!this[switchElementSymbol].classList.contains("hidden")) {
955
- this[switchElementSymbol].classList.add("hidden");
956
- }
957
- }
958
-
959
- /**
960
- * @private
961
- */
962
- function disconnectResizeObserver() {
963
- if (this[resizeObserverSymbol] instanceof ResizeObserver) {
964
- this[resizeObserverSymbol].disconnect();
965
- }
966
- this[observedLayoutNodesSignatureSymbol] = null;
967
- }
968
-
969
- /**
970
- * @private
971
- */
972
- function toggle() {
973
- if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
974
- hide.call(this);
975
- } else {
976
- show.call(this);
977
- }
978
- }
979
-
980
- /**
981
- * @private
982
- */
983
- function hide() {
984
- this[popperElementSymbol].style.display = "none";
985
- removeAttributeToken(this[controlElementSymbol], "class", "open");
986
- }
987
-
988
- /**
989
- * @private
990
- * @this PopperButton
991
- */
992
- function show() {
993
- if (this.getOption("disabled", false) === true) {
994
- return;
995
- }
996
-
997
- if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
998
- return;
999
- }
1000
-
1001
- this[popperElementSymbol].style.visibility = "hidden";
1002
- this[popperElementSymbol].style.display = STYLE_DISPLAY_MODE_BLOCK;
1003
-
1004
- addAttributeToken(this[controlElementSymbol], "class", "open");
1005
-
1006
- updatePopper.call(this);
1007
- }
1008
-
1009
- /**
1010
- * @private
1011
- */
1012
- function updatePopper() {
1013
- if (this[popperElementSymbol].style.display !== STYLE_DISPLAY_MODE_BLOCK) {
1014
- return;
1015
- }
1016
-
1017
- if (this.getOption("disabled", false) === true) {
1018
- return;
1019
- }
1020
-
1021
- positionPopper.call(
1022
- this,
1023
- this[switchElementSymbol],
1024
- this[popperElementSymbol],
1025
- this.getOption("popper", {}),
1026
- );
1027
- }
1028
-
1029
- /**
1030
- * @private
1031
- */
1032
- function applyLayoutAlignment() {
1033
- if (!(this[buttonBarElementSymbol] instanceof HTMLElement)) {
1034
- return;
1035
- }
1036
-
1037
- const alignment = this.getOption("layout.alignment", "left");
1038
-
1039
- if (alignment === "right") {
1040
- this[buttonBarElementSymbol].setAttribute(
1041
- ATTRIBUTE_LAYOUT_ALIGNMENT,
1042
- "right",
1043
- );
1044
- return;
1045
- }
1046
-
1047
- this[buttonBarElementSymbol].setAttribute(ATTRIBUTE_LAYOUT_ALIGNMENT, "left");
1048
- }
1049
-
1050
- /**
1051
- * @private
1052
- * @return {Select}
1053
- * @throws {Error} no shadow-root is defined
1054
- */
1055
- function initControlReferences() {
1056
- if (!this.shadowRoot) {
1057
- throw new Error("no shadow-root is defined");
1058
- }
1059
-
1060
- this[controlElementSymbol] = this.shadowRoot.querySelector(
1061
- `[${ATTRIBUTE_ROLE}=control]`,
1062
- );
1063
- this[buttonBarElementSymbol] = this.shadowRoot.querySelector(
1064
- `[${ATTRIBUTE_ROLE}=button-bar]`,
1065
- );
1066
- this[popperElementSymbol] = this.shadowRoot.querySelector(
1067
- `[${ATTRIBUTE_ROLE}=popper]`,
1068
- );
1069
- this[popperNavElementSymbol] = this.shadowRoot.querySelector(
1070
- `[${ATTRIBUTE_ROLE}=popper-nav]`,
1071
- );
1072
- this[switchElementSymbol] = this.shadowRoot.querySelector(
1073
- `[${ATTRIBUTE_ROLE}=switch]`,
1074
- );
1075
-
1076
- this[buttonBarSlotElementSymbol] = null;
1077
- if (this[buttonBarElementSymbol])
1078
- this[buttonBarSlotElementSymbol] =
1079
- this[buttonBarElementSymbol].querySelector(`slot`);
1080
- this[popperSlotElementSymbol] = null;
1081
- if (this[popperElementSymbol])
1082
- this[popperSlotElementSymbol] =
1083
- this[popperElementSymbol].querySelector(`slot`);
1084
- }
1085
-
1086
- /**
1087
- * @private
1088
- * @return {Promise<unknown>}
1089
- * @throws {Error} no shadow-root is defined
1090
- *
1091
- */
1092
- function initButtonBar() {
1093
- if (!this.shadowRoot) {
1094
- throw new Error("no shadow-root is defined");
1095
- }
1096
-
1097
- scheduleLayout.call(this, { measure: true, layout: true, observe: true });
1098
- }
1099
-
1100
- /**
1101
- * @private
1102
- */
1103
- function initPopperSwitch() {
1104
- /**
1105
- * @param {Event} event
1106
- */
1107
- this[popperSwitchEventHandler] = (event) => {
1108
- const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "switch");
1109
-
1110
- if (element instanceof HTMLButtonElement) {
1111
- toggle.call(this);
1112
- }
1113
- };
1114
-
1115
- for (const type of ["click", "touch"]) {
1116
- this[switchElementSymbol].addEventListener(
1117
- type,
1118
- this[popperSwitchEventHandler],
1119
- );
1120
- }
1121
72
  }
1122
73
 
1123
74
  /**