@expressivecss/expressive 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +48 -1
  2. package/README.md +69 -26
  3. package/dist/css/expressive.css +657 -85
  4. package/dist/css/expressive.css.map +1 -1
  5. package/dist/css/expressive.min.css +1 -1
  6. package/dist/css/expressive.min.css.map +1 -1
  7. package/dist/fonts/LICENSE-material-symbols +93 -0
  8. package/dist/fonts/LICENSE-noto-sans +93 -0
  9. package/dist/fonts/LICENSE-roboto +93 -0
  10. package/dist/fonts/material-symbols-outlined.woff2 +0 -0
  11. package/dist/fonts/material-symbols-rounded.woff2 +0 -0
  12. package/dist/fonts/material-symbols-sharp.woff2 +0 -0
  13. package/dist/fonts/noto-sans-latin-400.woff2 +0 -0
  14. package/dist/fonts/noto-sans-latin-500.woff2 +0 -0
  15. package/dist/fonts/roboto-latin-400.woff2 +0 -0
  16. package/dist/fonts/roboto-latin-500.woff2 +0 -0
  17. package/dist/js/expressive.cjs +501 -144
  18. package/dist/js/expressive.cjs.map +4 -4
  19. package/dist/js/expressive.js +501 -144
  20. package/dist/js/expressive.js.map +4 -4
  21. package/dist/js/expressive.min.js +10 -10
  22. package/dist/js/expressive.min.js.map +4 -4
  23. package/dist/js/expressive.mjs +501 -144
  24. package/dist/js/expressive.mjs.map +4 -4
  25. package/dist/types/components/appBar.d.ts +26 -0
  26. package/dist/types/components/buttonGroup.d.ts +39 -0
  27. package/dist/types/components/cards.d.ts +11 -13
  28. package/dist/types/components/expandingCard.d.ts +1 -1
  29. package/dist/types/components/index.d.ts +2 -0
  30. package/dist/types/components/menu.d.ts +4 -0
  31. package/dist/types/components/registry.d.ts +10 -0
  32. package/dist/types/components/timepicker.d.ts +0 -1
  33. package/dist/types/components/tooltip.d.ts +1 -0
  34. package/dist/types/index.d.ts +1 -1
  35. package/package.json +25 -3
  36. package/src/sass/abstracts/_mixins.scss +52 -0
  37. package/src/sass/abstracts/_variables.scss +19 -0
  38. package/src/sass/base/_fonts.scss +63 -0
  39. package/src/sass/components/_badges.scss +1 -2
  40. package/src/sass/components/_button-groups.scss +252 -80
  41. package/src/sass/components/_cards.scss +108 -93
  42. package/src/sass/components/_expanding-card.scss +1 -35
  43. package/src/sass/components/_icon-buttons.scss +2 -24
  44. package/src/sass/components/_icons-material-design.scss +6 -6
  45. package/src/sass/components/_navbar.scss +180 -27
  46. package/src/sass/components/_navigation-bar.scss +9 -1
  47. package/src/sass/components/_navigation-rail.scss +9 -1
  48. package/src/sass/components/_transitions.scss +8 -1
  49. package/src/sass/components/forms/_select.scss +38 -0
  50. package/src/sass/expressive.scss +5 -0
@@ -380,103 +380,120 @@ var _defaults = {
380
380
  onOpen: null,
381
381
  onClose: null
382
382
  };
383
- var CARDS_SELECTOR = "article:has(> aside)";
383
+ var CARDS_SELECTOR = 'article:has(> aside[id]:not([id=""])):not(:has(> aside ~ aside)):has(> button.card-reveal-trigger[type="button"], > :not(aside) button.card-reveal-trigger[type="button"])';
384
+ var REVEAL_INITIALIZED_CLASS = "card-reveal-initialized";
385
+ function hasAccessibleName(trigger) {
386
+ const label = trigger.getAttribute("aria-label");
387
+ if (label?.trim()) return true;
388
+ const labelledBy = trigger.getAttribute("aria-labelledby");
389
+ if (labelledBy) {
390
+ const referencedText = labelledBy.trim().split(/\s+/).map((id) => trigger.ownerDocument.getElementById(id)?.textContent ?? "").join(" ").trim();
391
+ if (referencedText) return true;
392
+ }
393
+ const content = trigger.cloneNode(true);
394
+ content.querySelectorAll('[aria-hidden="true"]').forEach((node) => node.remove());
395
+ return Boolean(content.textContent?.trim());
396
+ }
397
+ function isUsableCardTrigger(trigger, card, panel) {
398
+ return trigger.closest("article") === card && !panel.contains(trigger) && !trigger.disabled && trigger.getAttribute("aria-disabled") !== "true" && hasAccessibleName(trigger);
399
+ }
400
+ function isCardReveal(el) {
401
+ if (el.tagName !== "ARTICLE") return false;
402
+ const panels = el.querySelectorAll(":scope > aside");
403
+ if (panels.length !== 1 || !panels[0].id) return false;
404
+ return Array.from(
405
+ el.querySelectorAll('button.card-reveal-trigger[type="button"]')
406
+ ).some((trigger) => isUsableCardTrigger(trigger, el, panels[0]));
407
+ }
384
408
  var Cards = class _Cards extends Component {
385
- constructor(el, options) {
409
+ constructor(el, options = {}) {
386
410
  super(el, options, _Cards);
387
411
  this.isOpen = false;
412
+ this._ownsRevealInitializedClass = false;
413
+ this._initialAriaControls = /* @__PURE__ */ new Map();
414
+ this._lastActivator = null;
388
415
  this._setupEventHandlers = () => {
389
- this._activators.forEach((el) => {
390
- el.addEventListener("click", this._handleClickInteraction);
391
- el.addEventListener("keypress", this._handleKeypressEvent);
416
+ this._activators.forEach((activator) => {
417
+ activator.addEventListener("click", this._handleClickInteraction);
392
418
  });
419
+ this.el.addEventListener("keydown", this._handleKeydownEvent);
393
420
  };
394
421
  this._removeEventHandlers = () => {
395
- this._activators.forEach((el) => {
396
- el.removeEventListener("click", this._handleClickInteraction);
397
- el.removeEventListener("keypress", this._handleKeypressEvent);
422
+ this._activators.forEach((activator) => {
423
+ activator.removeEventListener("click", this._handleClickInteraction);
398
424
  });
425
+ this.el.removeEventListener("keydown", this._handleKeydownEvent);
399
426
  };
400
- this._handleClickInteraction = () => {
427
+ this._handleClickInteraction = (event) => {
428
+ this._lastActivator = event.currentTarget;
401
429
  this._handleRevealEvent();
402
430
  };
403
- this._handleKeypressEvent = (e) => {
404
- if (e.key === Utils.keys.ENTER || e.key === " ") {
405
- e.preventDefault();
406
- this._handleRevealEvent();
407
- }
431
+ this._handleKeydownEvent = (event) => {
432
+ const target = event.target instanceof Element ? event.target.closest("article") : null;
433
+ if (target !== this.el || event.key !== "Escape" || !this.isOpen) return;
434
+ event.preventDefault();
435
+ this.close();
408
436
  };
409
437
  this._handleRevealEvent = () => {
410
438
  if (this.isOpen) this.close();
411
439
  else this.open();
412
440
  };
413
- this._setupRevealCloseEventHandlers = () => {
414
- this.cardRevealClose.addEventListener("click", this.close);
415
- this.cardRevealClose.addEventListener("keypress", this._handleKeypressCloseEvent);
416
- };
417
- this._removeRevealCloseEventHandlers = () => {
418
- this.cardRevealClose.removeEventListener("click", this.close);
419
- this.cardRevealClose.removeEventListener("keypress", this._handleKeypressCloseEvent);
420
- };
421
- this._handleKeypressCloseEvent = (e) => {
422
- if (e.key === Utils.keys.ENTER) {
423
- this.close();
424
- }
425
- };
426
441
  /**
427
442
  * Show card reveal.
428
443
  */
429
444
  this.open = () => {
430
445
  if (this.isOpen || !this.cardReveal) return;
431
446
  this.isOpen = true;
432
- this.cardReveal.ariaExpanded = "true";
433
- this._activators.forEach((el) => el.ariaExpanded = "true");
434
- if (this.cardRevealClose) this.cardRevealClose.tabIndex = 0;
447
+ this.cardReveal.classList.add("open");
448
+ this.cardReveal.inert = false;
449
+ this._activators.forEach((activator) => activator.ariaExpanded = "true");
435
450
  if (typeof this.options.onOpen === "function") {
436
- this.options.onOpen.call(this);
451
+ this.options.onOpen.call(this, this.el);
437
452
  }
438
- if (this.cardRevealClose) this._setupRevealCloseEventHandlers();
439
453
  };
440
454
  /**
441
455
  * Hide card reveal.
442
456
  */
443
457
  this.close = () => {
444
458
  if (!this.isOpen || !this.cardReveal) return;
459
+ const focusWasInside = this.cardReveal.contains(document.activeElement);
445
460
  this.isOpen = false;
446
- this.cardReveal.ariaExpanded = "false";
447
- this._activators.forEach((el) => el.ariaExpanded = "false");
448
- if (this.cardRevealClose) this.cardRevealClose.tabIndex = -1;
461
+ this.cardReveal.classList.remove("open");
462
+ this.cardReveal.inert = true;
463
+ this._activators.forEach((activator) => activator.ariaExpanded = "false");
449
464
  if (typeof this.options.onClose === "function") {
450
- this.options.onClose.call(this);
465
+ this.options.onClose.call(this, this.el);
466
+ }
467
+ if (focusWasInside) {
468
+ (this._lastActivator ?? this._activators[0])?.focus();
451
469
  }
452
- if (this.cardRevealClose) this._removeRevealCloseEventHandlers();
453
470
  };
454
471
  this.el["Expressive_Cards"] = this;
455
472
  this.options = {
456
473
  ..._Cards.defaults,
457
474
  ...options
458
475
  };
459
- this._activators = [];
460
- this.cardReveal = this.el.querySelector(":scope > aside");
476
+ const cardReveals = this.el.querySelectorAll(":scope > aside");
477
+ const cardReveal = cardReveals.length === 1 ? cardReveals[0] : null;
478
+ const activators = cardReveal ? Array.from(
479
+ this.el.querySelectorAll(
480
+ 'button.card-reveal-trigger[type="button"]'
481
+ )
482
+ ).filter(
483
+ (activator) => isUsableCardTrigger(activator, this.el, cardReveal)
484
+ ) : [];
485
+ this.cardReveal = cardReveal?.id && activators.length > 0 ? cardReveal : null;
486
+ this._activators = this.cardReveal ? activators : [];
461
487
  if (this.cardReveal) {
462
- this._activators = Array.from(
463
- this.el.querySelectorAll(".activator")
464
- ).filter(
465
- (activator) => !this.cardReveal.contains(activator)
466
- );
467
- this._activators.forEach((el2) => {
468
- if (!el2) return;
469
- el2.tabIndex = 0;
470
- el2.ariaExpanded = "false";
471
- if (!el2.matches("a[href], button, input, select, textarea")) {
472
- el2.setAttribute("role", "button");
473
- }
488
+ this._ownsRevealInitializedClass = !this.el.classList.contains(REVEAL_INITIALIZED_CLASS);
489
+ this.el.classList.add(REVEAL_INITIALIZED_CLASS);
490
+ this._activators.forEach((activator) => {
491
+ this._initialAriaControls.set(activator, activator.getAttribute("aria-controls"));
492
+ activator.ariaExpanded = "false";
493
+ activator.setAttribute("aria-controls", this.cardReveal.id);
474
494
  });
475
- this.cardRevealClose = this.cardReveal.querySelector(
476
- ":scope > :is(h1, h2, h3, h4, h5, h6)"
477
- );
478
- if (this.cardRevealClose) this.cardRevealClose.tabIndex = -1;
479
- this.cardReveal.ariaExpanded = "false";
495
+ this.cardReveal.classList.remove("open");
496
+ this.cardReveal.inert = true;
480
497
  this._setupEventHandlers();
481
498
  }
482
499
  }
@@ -499,13 +516,28 @@ var Cards = class _Cards extends Component {
499
516
  */
500
517
  destroy() {
501
518
  this._removeEventHandlers();
502
- if (this.cardRevealClose) this._removeRevealCloseEventHandlers();
519
+ if (this.cardReveal) {
520
+ this.cardReveal.classList.remove("open");
521
+ this.cardReveal.inert = false;
522
+ if (this._ownsRevealInitializedClass) this.el.classList.remove(REVEAL_INITIALIZED_CLASS);
523
+ }
524
+ this._activators.forEach((activator) => {
525
+ activator.removeAttribute("aria-expanded");
526
+ const initialAriaControls = this._initialAriaControls.get(activator);
527
+ if (initialAriaControls === null) activator.removeAttribute("aria-controls");
528
+ else if (initialAriaControls !== void 0) {
529
+ activator.setAttribute("aria-controls", initialAriaControls);
530
+ }
531
+ });
532
+ this.isOpen = false;
503
533
  this._activators = [];
534
+ this._initialAriaControls.clear();
535
+ this._lastActivator = null;
504
536
  this.el["Expressive_Cards"] = void 0;
505
537
  }
506
538
  static Init() {
507
539
  Utils.onDocumentReady(() => {
508
- const cards = document.querySelectorAll(CARDS_SELECTOR);
540
+ const cards = Array.from(document.querySelectorAll(CARDS_SELECTOR)).filter(isCardReveal);
509
541
  cards.forEach((el) => {
510
542
  if (el && el["Expressive_Cards"] == void 0) this.init(el);
511
543
  });
@@ -518,13 +550,12 @@ var _defaults2 = {
518
550
  onOpen: null,
519
551
  onClose: null
520
552
  };
521
- var MOTION_DURATION = 500;
522
553
  var EXPANDING_CARD_SELECTOR = "article.expanding-card:has(> dialog.expanding-card-dialog)";
523
554
  var ExpandingCard = class _ExpandingCard extends Component {
524
555
  constructor(el, options) {
525
556
  super(el, options, _ExpandingCard);
526
557
  this.isOpen = false;
527
- this.closeTimer = null;
558
+ this.closeGeneration = 0;
528
559
  this._setupEventHandlers = () => {
529
560
  this.trigger?.addEventListener("click", this.open);
530
561
  this.trigger?.addEventListener("keypress", this._handleTriggerKeypress);
@@ -550,7 +581,8 @@ var ExpandingCard = class _ExpandingCard extends Component {
550
581
  this.close();
551
582
  };
552
583
  this._handleNativeClose = () => {
553
- if (!this.isOpen) return;
584
+ if (this.dialog.open) return;
585
+ this.closeGeneration++;
554
586
  this.isOpen = false;
555
587
  this.trigger.ariaExpanded = "false";
556
588
  this.dialog.ariaExpanded = "false";
@@ -586,10 +618,7 @@ var ExpandingCard = class _ExpandingCard extends Component {
586
618
  };
587
619
  this.open = () => {
588
620
  if (this.isOpen || !this.dialog || !this.trigger) return;
589
- if (this.closeTimer !== null) {
590
- window.clearTimeout(this.closeTimer);
591
- this.closeTimer = null;
592
- }
621
+ this.closeGeneration++;
593
622
  this._setTransitionOrigin();
594
623
  this.isOpen = true;
595
624
  this.trigger.ariaExpanded = "true";
@@ -604,6 +633,7 @@ var ExpandingCard = class _ExpandingCard extends Component {
604
633
  };
605
634
  this.close = () => {
606
635
  if (!this.isOpen || !this.dialog || !this.trigger) return;
636
+ const generation = ++this.closeGeneration;
607
637
  this._setTransitionOrigin();
608
638
  this.isOpen = false;
609
639
  this.trigger.ariaExpanded = "false";
@@ -613,15 +643,16 @@ var ExpandingCard = class _ExpandingCard extends Component {
613
643
  this.options.onClose.call(this, this.el);
614
644
  }
615
645
  const finish = () => {
616
- this.closeTimer = null;
617
- if (this.dialog.open) this.dialog.close();
618
- this.trigger.focus();
646
+ if (generation !== this.closeGeneration || this.isOpen || !this.dialog.open) return;
647
+ this.dialog.close();
648
+ if (this.dialog.isConnected && this.trigger.isConnected) this.trigger.focus();
619
649
  };
620
650
  const reducedMotion = window.matchMedia(
621
651
  "(prefers-reduced-motion: reduce)"
622
652
  ).matches;
623
- if (reducedMotion) finish();
624
- else this.closeTimer = window.setTimeout(finish, MOTION_DURATION);
653
+ const transitions = reducedMotion ? [] : (this.dialog.getAnimations?.() ?? []).filter((animation) => animation.transitionProperty === "clip-path");
654
+ if (transitions.length === 0) finish();
655
+ else void Promise.allSettled(transitions.map((animation) => animation.finished)).then(finish);
625
656
  };
626
657
  this.el["Expressive_ExpandingCard"] = this;
627
658
  this.options = {
@@ -658,7 +689,10 @@ var ExpandingCard = class _ExpandingCard extends Component {
658
689
  }
659
690
  destroy() {
660
691
  this._removeEventHandlers();
661
- if (this.closeTimer !== null) window.clearTimeout(this.closeTimer);
692
+ this.closeGeneration++;
693
+ this.isOpen = false;
694
+ if (this.trigger) this.trigger.ariaExpanded = "false";
695
+ if (this.dialog) this.dialog.ariaExpanded = "false";
662
696
  this.dialog?.classList.remove("expanded");
663
697
  if (this.dialog?.open) this.dialog.close();
664
698
  this.el["Expressive_ExpandingCard"] = void 0;
@@ -697,6 +731,8 @@ var SPACE = " ";
697
731
  var _Menu = class _Menu extends Component {
698
732
  constructor(el, options) {
699
733
  super(el, options, _Menu);
734
+ this._pendingTimers = /* @__PURE__ */ new Set();
735
+ this._transition = 0;
700
736
  this._handleClick = (e) => {
701
737
  e.preventDefault();
702
738
  if (this.isOpen) {
@@ -730,7 +766,7 @@ var _Menu = class _Menu extends Component {
730
766
  if (this.options.closeOnClick && this.menuEl?.contains(target) && !this.isTouchMoving) {
731
767
  this.close();
732
768
  } else if (!this.menuEl?.contains(target)) {
733
- setTimeout(() => {
769
+ this._schedule(() => {
734
770
  if (this.isOpen) {
735
771
  this.close();
736
772
  }
@@ -884,16 +920,18 @@ var _Menu = class _Menu extends Component {
884
920
  * Open menu.
885
921
  */
886
922
  this.open = () => {
887
- if (this.isOpen) return;
923
+ if (this.isOpen || this.el["Expressive_Menu"] !== this) return;
924
+ const transition = this._clearPendingTimers();
888
925
  this.isOpen = true;
889
926
  if (typeof this.options.onOpenStart === "function") {
890
927
  this.options.onOpenStart.call(this, this.el);
891
928
  }
929
+ if (transition !== this._transition) return;
892
930
  this._resetMenuStyles();
893
931
  this.menuEl.style.display = "block";
894
932
  this._placeMenu();
933
+ this._schedule(() => this._setupTemporaryEventHandlers(), 0);
895
934
  this._animateIn();
896
- setTimeout(() => this._setupTemporaryEventHandlers(), 0);
897
935
  this.el.ariaExpanded = "true";
898
936
  };
899
937
  /**
@@ -901,18 +939,20 @@ var _Menu = class _Menu extends Component {
901
939
  */
902
940
  this.close = () => {
903
941
  if (!this.isOpen) return;
942
+ const transition = this._clearPendingTimers();
904
943
  this.isOpen = false;
905
944
  this.focusedIndex = -1;
906
945
  this._closeSubmenus();
907
946
  if (typeof this.options.onCloseStart === "function") {
908
947
  this.options.onCloseStart.call(this, this.el);
909
948
  }
949
+ if (transition !== this._transition) return;
910
950
  this._animateOut();
911
951
  this._removeTemporaryEventHandlers();
952
+ this.el.ariaExpanded = "false";
912
953
  if (this.options.autoFocus) {
913
954
  this.el.focus();
914
955
  }
915
- this.el.ariaExpanded = "false";
916
956
  };
917
957
  /**
918
958
  * While menu is open, you can recalculate its dimensions if its contents have changed.
@@ -961,6 +1001,9 @@ var _Menu = class _Menu extends Component {
961
1001
  return el["Expressive_Menu"];
962
1002
  }
963
1003
  destroy() {
1004
+ this._clearPendingTimers();
1005
+ this.isOpen = false;
1006
+ this.el.ariaExpanded = "false";
964
1007
  clearTimeout(this.filterTimeout);
965
1008
  this._resetMenuStyles();
966
1009
  this._removeEventHandlers();
@@ -1223,18 +1266,32 @@ var _Menu = class _Menu extends Component {
1223
1266
  width: idealWidth
1224
1267
  };
1225
1268
  }
1269
+ _schedule(callback, delay) {
1270
+ const timer = setTimeout(() => {
1271
+ this._pendingTimers.delete(timer);
1272
+ callback();
1273
+ }, delay);
1274
+ this._pendingTimers.add(timer);
1275
+ }
1276
+ _clearPendingTimers() {
1277
+ for (const timer of this._pendingTimers) clearTimeout(timer);
1278
+ this._pendingTimers.clear();
1279
+ return ++this._transition;
1280
+ }
1226
1281
  _animateIn() {
1282
+ const transition = this._transition;
1227
1283
  const duration = this.options.inDuration;
1228
1284
  this.menuEl.style.transition = "none";
1229
1285
  this.menuEl.style.opacity = "0";
1230
1286
  this.menuEl.style.transform = "scale(0.85)";
1231
- setTimeout(() => {
1287
+ this._schedule(() => {
1232
1288
  this.menuEl.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
1233
1289
  this.menuEl.style.opacity = "1";
1234
1290
  this.menuEl.style.transform = "scale(1)";
1235
1291
  }, 1);
1236
- setTimeout(() => {
1292
+ this._schedule(() => {
1237
1293
  this._focusInitialItem();
1294
+ if (transition !== this._transition) return;
1238
1295
  if (typeof this.options.onOpenEnd === "function") this.options.onOpenEnd.call(this, this.el);
1239
1296
  }, duration);
1240
1297
  }
@@ -1243,7 +1300,7 @@ var _Menu = class _Menu extends Component {
1243
1300
  this.menuEl.style.transition = `opacity ${duration}ms ease, transform ${duration}ms ease`;
1244
1301
  this.menuEl.style.opacity = "0";
1245
1302
  this.menuEl.style.transform = "scale(0.85)";
1246
- setTimeout(() => {
1303
+ this._schedule(() => {
1247
1304
  this._resetMenuStyles();
1248
1305
  if (typeof this.options.onCloseEnd === "function")
1249
1306
  this.options.onCloseEnd.call(this, this.el);
@@ -2512,8 +2569,89 @@ var Forms = class _Forms {
2512
2569
  }
2513
2570
  };
2514
2571
 
2572
+ // src/ts/components/appBar.ts
2573
+ var _defaults7 = {};
2574
+ var AppBar = class _AppBar extends Component {
2575
+ constructor(el, options) {
2576
+ super(el, options, _AppBar);
2577
+ this._observer = null;
2578
+ this._sentinel = null;
2579
+ this._input = null;
2580
+ this._view = null;
2581
+ this._suppressSearchOpen = false;
2582
+ this._onIntersect = (entries) => {
2583
+ const entry = entries[0];
2584
+ if (!entry) return;
2585
+ this.el.classList.toggle("collapsed", !entry.isIntersecting);
2586
+ };
2587
+ this._onSearchViewClose = () => {
2588
+ this._suppressSearchOpen = true;
2589
+ };
2590
+ this._onSearchFocus = () => {
2591
+ if (!this._view) return;
2592
+ if (this._suppressSearchOpen) {
2593
+ this._suppressSearchOpen = false;
2594
+ return;
2595
+ }
2596
+ if (this._view instanceof HTMLDialogElement) {
2597
+ if (!this._view.open) this._view.showModal();
2598
+ return;
2599
+ }
2600
+ this._view.hidden = false;
2601
+ this._input?.setAttribute("aria-expanded", "true");
2602
+ };
2603
+ this.el["Expressive_AppBar"] = this;
2604
+ this.options = { ..._AppBar.defaults, ...options };
2605
+ this._setupCollapse();
2606
+ this._setupSearch();
2607
+ }
2608
+ static get defaults() {
2609
+ return _defaults7;
2610
+ }
2611
+ static init(els, options = {}) {
2612
+ return super.init(els, options, _AppBar);
2613
+ }
2614
+ static getInstance(el) {
2615
+ return el["Expressive_AppBar"];
2616
+ }
2617
+ destroy() {
2618
+ this._observer?.disconnect();
2619
+ this._observer = null;
2620
+ this._sentinel?.remove();
2621
+ this._sentinel = null;
2622
+ this._input?.removeEventListener("focus", this._onSearchFocus);
2623
+ this._view?.removeEventListener("close", this._onSearchViewClose);
2624
+ this.el.classList.remove("collapsed");
2625
+ this.el["Expressive_AppBar"] = void 0;
2626
+ }
2627
+ _setupCollapse() {
2628
+ if (!this.el.classList.contains("medium") && !this.el.classList.contains("large")) {
2629
+ return;
2630
+ }
2631
+ if (typeof IntersectionObserver === "undefined") return;
2632
+ this._sentinel = document.createElement("span");
2633
+ this._sentinel.setAttribute("aria-hidden", "true");
2634
+ this._sentinel.style.cssText = "display:block;width:100%;height:1px;margin-top:-1px;pointer-events:none;visibility:hidden";
2635
+ this.el.insertAdjacentElement("beforebegin", this._sentinel);
2636
+ this._observer = new IntersectionObserver(this._onIntersect);
2637
+ this._observer.observe(this._sentinel);
2638
+ }
2639
+ _setupSearch() {
2640
+ this._input = this.el.querySelector('input[type="search"]');
2641
+ if (!this._input) return;
2642
+ const id = this._input.getAttribute("aria-controls");
2643
+ if (id) this._view = document.getElementById(id);
2644
+ if (!this._view) this._view = this.el.querySelector(".search-view");
2645
+ if (!this._view) return;
2646
+ this._input.addEventListener("focus", this._onSearchFocus);
2647
+ if (this._view instanceof HTMLDialogElement) {
2648
+ this._view.addEventListener("close", this._onSearchViewClose);
2649
+ }
2650
+ }
2651
+ };
2652
+
2515
2653
  // src/ts/components/buttons.ts
2516
- var _defaults7 = {
2654
+ var _defaults8 = {
2517
2655
  direction: "top",
2518
2656
  hoverEnabled: true,
2519
2657
  toolbarEnabled: false
@@ -2586,7 +2724,7 @@ var FloatingActionButton = class _FloatingActionButton extends Component {
2586
2724
  this._setupEventHandlers();
2587
2725
  }
2588
2726
  static get defaults() {
2589
- return _defaults7;
2727
+ return _defaults8;
2590
2728
  }
2591
2729
  static init(els, options = {}) {
2592
2730
  return super.init(els, options, _FloatingActionButton);
@@ -2623,8 +2761,226 @@ var FloatingActionButton = class _FloatingActionButton extends Component {
2623
2761
  }
2624
2762
  };
2625
2763
 
2764
+ // src/ts/components/buttonGroup.ts
2765
+ var _defaults9 = {};
2766
+ var VALID_SELECTION_MODES = /* @__PURE__ */ new Set(["single", "multiple"]);
2767
+ var PRESSED_CLASS = "button-group-pressed";
2768
+ var MAX_ICON_COMPRESSION = 0.15;
2769
+ var ButtonGroup = class _ButtonGroup extends Component {
2770
+ constructor(el, options = {}) {
2771
+ super(el, options, _ButtonGroup);
2772
+ this._pressedStyles = /* @__PURE__ */ new Map();
2773
+ this._releaseStyles = /* @__PURE__ */ new Map();
2774
+ this._releaseTimer = null;
2775
+ this._originalPressed = /* @__PURE__ */ new Map();
2776
+ this._activeItem = null;
2777
+ this._handleClick = (event) => {
2778
+ if (!this._selectionMode) return;
2779
+ const item = this._itemFromEvent(event);
2780
+ if (!(item instanceof HTMLButtonElement) || this._isDisabled(item)) return;
2781
+ this._rememberPressed(item);
2782
+ const willSelect = item.getAttribute("aria-pressed") !== "true";
2783
+ const selectedCount = this._toggleItems.filter(
2784
+ (button) => button.getAttribute("aria-pressed") === "true"
2785
+ ).length;
2786
+ if (!willSelect && this.el.hasAttribute("data-selection-required") && selectedCount === 1) {
2787
+ return;
2788
+ }
2789
+ if (this._selectionMode === "single" && willSelect) {
2790
+ this._toggleItems.forEach((button) => {
2791
+ this._rememberPressed(button);
2792
+ button.setAttribute("aria-pressed", "false");
2793
+ });
2794
+ }
2795
+ item.setAttribute("aria-pressed", willSelect ? "true" : "false");
2796
+ };
2797
+ this._handlePointerDown = (event) => {
2798
+ if (event.button !== 0) return;
2799
+ const item = this._itemFromEvent(event);
2800
+ if (item && !this._isDisabled(item)) this._startPress(item);
2801
+ };
2802
+ this._handleKeyDown = (event) => {
2803
+ if (event.repeat || event.key !== " " && event.key !== "Enter") return;
2804
+ const item = this._itemFromEvent(event);
2805
+ if (item && !this._isDisabled(item)) this._startPress(item);
2806
+ };
2807
+ this._handleKeyUp = (event) => {
2808
+ if (event.key === " " || event.key === "Enter") this._resetPress();
2809
+ };
2810
+ this._handleFocusOut = (event) => {
2811
+ if (event.target === this._activeItem) this._resetPress();
2812
+ };
2813
+ this._resetPress = () => {
2814
+ this._activeItem?.classList.remove(PRESSED_CLASS);
2815
+ this._activeItem = null;
2816
+ if (!this._pressedStyles.size) return;
2817
+ this._finishRelease();
2818
+ this._releaseStyles = new Map(this._pressedStyles);
2819
+ for (const [item, style] of this._releaseStyles) {
2820
+ item.style.width = `${style.baseWidth}px`;
2821
+ }
2822
+ this._pressedStyles.clear();
2823
+ this._releaseTimer = window.setTimeout(this._finishRelease, 200);
2824
+ };
2825
+ this._finishRelease = () => {
2826
+ if (this._releaseTimer !== null) window.clearTimeout(this._releaseTimer);
2827
+ this._releaseTimer = null;
2828
+ for (const [item, style] of this._releaseStyles) item.style.width = style.width;
2829
+ this._releaseStyles.clear();
2830
+ };
2831
+ this.el["Expressive_ButtonGroup"] = this;
2832
+ this.options = { ..._ButtonGroup.defaults, ...options };
2833
+ if (this._selectionMode) {
2834
+ this._normalizeSelection();
2835
+ this.el.addEventListener("click", this._handleClick, true);
2836
+ }
2837
+ this.el.addEventListener("pointerdown", this._handlePointerDown);
2838
+ this.el.addEventListener("keydown", this._handleKeyDown);
2839
+ this.el.addEventListener("focusout", this._handleFocusOut);
2840
+ document.addEventListener("pointerup", this._resetPress);
2841
+ document.addEventListener("pointercancel", this._resetPress);
2842
+ document.addEventListener("keyup", this._handleKeyUp);
2843
+ window.addEventListener("blur", this._resetPress);
2844
+ }
2845
+ static get defaults() {
2846
+ return _defaults9;
2847
+ }
2848
+ static init(els, options = {}) {
2849
+ return super.init(els, options, _ButtonGroup);
2850
+ }
2851
+ static getInstance(el) {
2852
+ return el["Expressive_ButtonGroup"];
2853
+ }
2854
+ destroy() {
2855
+ this._resetPress();
2856
+ this._finishRelease();
2857
+ this.el.removeEventListener("click", this._handleClick, true);
2858
+ this.el.removeEventListener("pointerdown", this._handlePointerDown);
2859
+ this.el.removeEventListener("keydown", this._handleKeyDown);
2860
+ this.el.removeEventListener("focusout", this._handleFocusOut);
2861
+ document.removeEventListener("pointerup", this._resetPress);
2862
+ document.removeEventListener("pointercancel", this._resetPress);
2863
+ document.removeEventListener("keyup", this._handleKeyUp);
2864
+ window.removeEventListener("blur", this._resetPress);
2865
+ for (const [item, value] of this._originalPressed) {
2866
+ if (value === null) item.removeAttribute("aria-pressed");
2867
+ else item.setAttribute("aria-pressed", value);
2868
+ }
2869
+ this._originalPressed.clear();
2870
+ this.el["Expressive_ButtonGroup"] = void 0;
2871
+ }
2872
+ get _selectionMode() {
2873
+ const mode = this.el.dataset.selection;
2874
+ return VALID_SELECTION_MODES.has(mode) ? mode : null;
2875
+ }
2876
+ get _items() {
2877
+ return Array.from(this.el.children).filter(
2878
+ (child) => child instanceof HTMLButtonElement || child instanceof HTMLAnchorElement && child.classList.contains("button")
2879
+ );
2880
+ }
2881
+ get _toggleItems() {
2882
+ return this._items.filter(
2883
+ (item) => item instanceof HTMLButtonElement
2884
+ );
2885
+ }
2886
+ _normalizeSelection() {
2887
+ const items = this._toggleItems;
2888
+ items.forEach((item) => {
2889
+ this._rememberPressed(item);
2890
+ if (!["true", "false"].includes(item.getAttribute("aria-pressed") || "")) {
2891
+ item.setAttribute("aria-pressed", "false");
2892
+ }
2893
+ });
2894
+ if (this._selectionMode === "single") {
2895
+ const selected = items.filter((item) => item.getAttribute("aria-pressed") === "true");
2896
+ selected.slice(1).forEach((item) => item.setAttribute("aria-pressed", "false"));
2897
+ }
2898
+ if (this.el.hasAttribute("data-selection-required") && !items.some((item) => item.getAttribute("aria-pressed") === "true")) {
2899
+ items.find((item) => !this._isDisabled(item))?.setAttribute("aria-pressed", "true");
2900
+ }
2901
+ }
2902
+ _itemFromEvent(event) {
2903
+ if (!(event.target instanceof Element)) return null;
2904
+ const item = event.target.closest("button, a.button");
2905
+ return item instanceof HTMLElement && item.parentElement === this.el ? item : null;
2906
+ }
2907
+ _isDisabled(item) {
2908
+ return item instanceof HTMLButtonElement && item.disabled || item.getAttribute("aria-disabled") === "true" || item.classList.contains("disabled");
2909
+ }
2910
+ _rememberPressed(item) {
2911
+ if (!this._originalPressed.has(item)) {
2912
+ this._originalPressed.set(item, item.getAttribute("aria-pressed"));
2913
+ }
2914
+ }
2915
+ _startPress(item) {
2916
+ if (this._activeItem) return;
2917
+ this._finishRelease();
2918
+ const items = this._items;
2919
+ const activeIndex = items.indexOf(item);
2920
+ if (activeIndex < 0) return;
2921
+ this._activeItem = item;
2922
+ item.classList.add(PRESSED_CLASS);
2923
+ if (this.el.classList.contains("connected") || items.length < 2) return;
2924
+ const rects = items.map((candidate) => candidate.getBoundingClientRect());
2925
+ const activeWidth = rects[activeIndex].width;
2926
+ if (activeWidth <= 0) return;
2927
+ const parsedMultiplier = Number.parseFloat(
2928
+ getComputedStyle(this.el).getPropertyValue(
2929
+ "--md-comp-button-group-pressed-item-width-multiplier"
2930
+ )
2931
+ );
2932
+ const multiplier = Number.isFinite(parsedMultiplier) ? parsedMultiplier : 0.15;
2933
+ const desiredGrowth = activeWidth * multiplier;
2934
+ const neighborIndexes = [activeIndex - 1, activeIndex + 1].filter(
2935
+ (index) => index >= 0 && index < items.length
2936
+ );
2937
+ const compression = /* @__PURE__ */ new Map();
2938
+ if (neighborIndexes.length === 1) {
2939
+ const index = neighborIndexes[0];
2940
+ compression.set(
2941
+ index,
2942
+ Math.min(desiredGrowth, this._compressionCapacity(items[index], rects[index]))
2943
+ );
2944
+ } else {
2945
+ const half = desiredGrowth / 2;
2946
+ for (const index of neighborIndexes) {
2947
+ compression.set(
2948
+ index,
2949
+ Math.min(half, this._compressionCapacity(items[index], rects[index]))
2950
+ );
2951
+ }
2952
+ let remaining = desiredGrowth - [...compression.values()].reduce((sum, value) => sum + value, 0);
2953
+ for (const index of neighborIndexes) {
2954
+ if (remaining <= 0) break;
2955
+ const capacity = this._compressionCapacity(items[index], rects[index]) - compression.get(index);
2956
+ const extra = Math.min(remaining, capacity);
2957
+ compression.set(index, compression.get(index) + extra);
2958
+ remaining -= extra;
2959
+ }
2960
+ }
2961
+ const actualGrowth = [...compression.values()].reduce((sum, value) => sum + value, 0);
2962
+ if (actualGrowth <= 0) return;
2963
+ items.forEach((candidate, index) => {
2964
+ this._pressedStyles.set(candidate, {
2965
+ width: candidate.style.width,
2966
+ baseWidth: rects[index].width
2967
+ });
2968
+ candidate.style.width = `${rects[index].width}px`;
2969
+ });
2970
+ void this.el.offsetWidth;
2971
+ items.forEach((candidate, index) => {
2972
+ const adjustment = index === activeIndex ? actualGrowth : -(compression.get(index) || 0);
2973
+ candidate.style.width = `${rects[index].width + adjustment}px`;
2974
+ });
2975
+ }
2976
+ _compressionCapacity(item, rect) {
2977
+ const minimumWidth = item.classList.contains("icon-button") ? rect.width * (1 - MAX_ICON_COMPRESSION) : rect.height;
2978
+ return Math.max(0, rect.width - minimumWidth);
2979
+ }
2980
+ };
2981
+
2626
2982
  // src/ts/components/carousel.ts
2627
- var _defaults8 = {
2983
+ var _defaults10 = {
2628
2984
  duration: 200,
2629
2985
  fullWidth: false,
2630
2986
  indicators: false,
@@ -2867,7 +3223,7 @@ var _Carousel = class _Carousel extends Component {
2867
3223
  return this._trackEl ?? this.el;
2868
3224
  }
2869
3225
  static get defaults() {
2870
- return _defaults8;
3226
+ return _defaults10;
2871
3227
  }
2872
3228
  static init(els, options = {}) {
2873
3229
  return super.init(els, options, _Carousel);
@@ -3263,7 +3619,7 @@ _Carousel._onResize = Utils.throttle(() => {
3263
3619
  var Carousel = _Carousel;
3264
3620
 
3265
3621
  // src/ts/components/characterCounter.ts
3266
- var _defaults9 = Object.freeze({});
3622
+ var _defaults11 = Object.freeze({});
3267
3623
  var CharacterCounter = class _CharacterCounter extends Component {
3268
3624
  constructor(el, options) {
3269
3625
  super(el, {}, _CharacterCounter);
@@ -3288,7 +3644,7 @@ var CharacterCounter = class _CharacterCounter extends Component {
3288
3644
  this._setupEventHandlers();
3289
3645
  }
3290
3646
  static get defaults() {
3291
- return _defaults9;
3647
+ return _defaults11;
3292
3648
  }
3293
3649
  /**
3294
3650
  * Initializes instances of CharacterCounter.
@@ -3340,7 +3696,7 @@ var CharacterCounter = class _CharacterCounter extends Component {
3340
3696
  };
3341
3697
 
3342
3698
  // src/ts/components/select.ts
3343
- var _defaults10 = {
3699
+ var _defaults12 = {
3344
3700
  classes: "",
3345
3701
  menuOptions: {}
3346
3702
  };
@@ -3389,7 +3745,7 @@ var FormSelect = class _FormSelect extends Component {
3389
3745
  this._setupEventHandlers();
3390
3746
  }
3391
3747
  static get defaults() {
3392
- return _defaults10;
3748
+ return _defaults12;
3393
3749
  }
3394
3750
  /**
3395
3751
  * Initializes instances of FormSelect.
@@ -3520,7 +3876,7 @@ var FormSelect = class _FormSelect extends Component {
3520
3876
  _buildInput() {
3521
3877
  this.input = document.createElement("input");
3522
3878
  this.input.id = "select-input-" + Utils.guid();
3523
- this.input.classList.add("menu-trigger");
3879
+ this.input.classList.add("menu-trigger", "no-autoinit");
3524
3880
  this.input.type = "text";
3525
3881
  this.input.readOnly = true;
3526
3882
  this.input.setAttribute("data-target", this.menuEl.id);
@@ -3761,7 +4117,7 @@ var FormSelect = class _FormSelect extends Component {
3761
4117
  };
3762
4118
 
3763
4119
  // src/ts/plugins/dockedDisplayPlugin.ts
3764
- var _defaults11 = {
4120
+ var _defaults13 = {
3765
4121
  margin: 5,
3766
4122
  transition: 10,
3767
4123
  duration: 250,
@@ -3810,7 +4166,7 @@ var DockedDisplayPlugin = class _DockedDisplayPlugin {
3810
4166
  };
3811
4167
  this.el = el;
3812
4168
  this.options = {
3813
- ..._defaults11,
4169
+ ..._defaults13,
3814
4170
  ...options
3815
4171
  };
3816
4172
  this.container = document.createElement("div");
@@ -3831,7 +4187,7 @@ var DockedDisplayPlugin = class _DockedDisplayPlugin {
3831
4187
  };
3832
4188
 
3833
4189
  // src/ts/components/datepicker.ts
3834
- var _defaults12 = {
4190
+ var _defaults14 = {
3835
4191
  // the default output format for the input field value
3836
4192
  format: "mmm dd, yyyy",
3837
4193
  // Used to create date object from current input string
@@ -4096,7 +4452,7 @@ var _Datepicker = class _Datepicker extends Component {
4096
4452
  }
4097
4453
  }
4098
4454
  static get defaults() {
4099
- return _defaults12;
4455
+ return _defaults14;
4100
4456
  }
4101
4457
  /**
4102
4458
  * Initializes instances of Datepicker.
@@ -4814,7 +5170,7 @@ _Datepicker._template = `
4814
5170
  var Datepicker = _Datepicker;
4815
5171
 
4816
5172
  // src/ts/components/lightbox.ts
4817
- var _defaults13 = {
5173
+ var _defaults15 = {
4818
5174
  inDuration: 275,
4819
5175
  outDuration: 200,
4820
5176
  onOpenStart: null,
@@ -4933,7 +5289,7 @@ var Lightbox = class _Lightbox extends Component {
4933
5289
  this._setupEventHandlers();
4934
5290
  }
4935
5291
  static get defaults() {
4936
- return _defaults13;
5292
+ return _defaults15;
4937
5293
  }
4938
5294
  /**
4939
5295
  * Initializes instances of Lightbox.
@@ -5099,7 +5455,7 @@ var Lightbox = class _Lightbox extends Component {
5099
5455
 
5100
5456
  // src/ts/components/scrollspy.ts
5101
5457
  var _defaultGetActiveElement = (id) => `a[href="#${id}"]`;
5102
- var _defaults14 = {
5458
+ var _defaults16 = {
5103
5459
  scrollOffset: 200,
5104
5460
  activeClass: "active",
5105
5461
  getActiveElement: _defaultGetActiveElement,
@@ -5122,7 +5478,7 @@ var _ScrollSpy = class _ScrollSpy extends Component {
5122
5478
  _ScrollSpy._observer?.observe(this.el);
5123
5479
  }
5124
5480
  static get defaults() {
5125
- return _defaults14;
5481
+ return _defaults16;
5126
5482
  }
5127
5483
  static init(els, options = {}) {
5128
5484
  return super.init(els, options, _ScrollSpy);
@@ -5244,7 +5600,7 @@ _ScrollSpy._onIntersect = (entries) => {
5244
5600
  var ScrollSpy = _ScrollSpy;
5245
5601
 
5246
5602
  // src/ts/components/navigationDrawer.ts
5247
- var _defaults15 = {
5603
+ var _defaults17 = {
5248
5604
  edge: "left",
5249
5605
  draggable: true,
5250
5606
  dragTargetWidth: "10px",
@@ -5387,7 +5743,7 @@ var _NavigationDrawer = class _NavigationDrawer extends Component {
5387
5743
  _NavigationDrawer._sidenavs.push(this);
5388
5744
  }
5389
5745
  static get defaults() {
5390
- return _defaults15;
5746
+ return _defaults17;
5391
5747
  }
5392
5748
  /**
5393
5749
  * Initializes instances of NavigationDrawer.
@@ -5578,7 +5934,7 @@ _NavigationDrawer._sidenavs = [];
5578
5934
  var NavigationDrawer = _NavigationDrawer;
5579
5935
 
5580
5936
  // src/ts/components/navigationRail.ts
5581
- var _defaults16 = {
5937
+ var _defaults18 = {
5582
5938
  onOpenStart: null,
5583
5939
  onOpenEnd: null,
5584
5940
  onCloseStart: null,
@@ -5654,7 +6010,7 @@ var NavigationRail = class _NavigationRail extends Component {
5654
6010
  document.addEventListener("keydown", this._onKeyDown);
5655
6011
  }
5656
6012
  static get defaults() {
5657
- return _defaults16;
6013
+ return _defaults18;
5658
6014
  }
5659
6015
  static init(els, options = {}) {
5660
6016
  return super.init(els, options, _NavigationRail);
@@ -5684,7 +6040,7 @@ var NavigationRail = class _NavigationRail extends Component {
5684
6040
  };
5685
6041
 
5686
6042
  // src/ts/components/tabs.ts
5687
- var _defaults17 = {
6043
+ var _defaults19 = {
5688
6044
  duration: 300,
5689
6045
  onShow: null,
5690
6046
  swipeable: false,
@@ -5760,7 +6116,7 @@ var Tabs = class _Tabs extends Component {
5760
6116
  this._setupEventHandlers();
5761
6117
  }
5762
6118
  static get defaults() {
5763
- return _defaults17;
6119
+ return _defaults19;
5764
6120
  }
5765
6121
  /**
5766
6122
  * Initializes instances of Tabs.
@@ -5947,7 +6303,7 @@ var Tabs = class _Tabs extends Component {
5947
6303
  };
5948
6304
 
5949
6305
  // src/ts/components/timepicker.ts
5950
- var _defaults18 = {
6306
+ var _defaults20 = {
5951
6307
  dialRadius: 135,
5952
6308
  outerRadius: 105,
5953
6309
  innerRadius: 70,
@@ -6000,12 +6356,6 @@ var _Timepicker = class _Timepicker extends Component {
6000
6356
  if (this.displayPlugin) this.displayPlugin.show();
6001
6357
  }
6002
6358
  };
6003
- this._handleTimeInputEnterKey = (e) => {
6004
- if (e.key === Utils.keys.ENTER) {
6005
- e.preventDefault();
6006
- this._inputFromTextField();
6007
- }
6008
- };
6009
6359
  this._handleClockClickStart = (e) => {
6010
6360
  if (!e.isPrimary) return;
6011
6361
  if (e.pointerType === "mouse" && e.button !== 0) return;
@@ -6160,7 +6510,7 @@ var _Timepicker = class _Timepicker extends Component {
6160
6510
  }
6161
6511
  }
6162
6512
  static get defaults() {
6163
- return _defaults18;
6513
+ return _defaults20;
6164
6514
  }
6165
6515
  /**
6166
6516
  * Initializes instances of Timepicker.
@@ -6510,7 +6860,7 @@ _Timepicker._template = `<div class="timepicker-container">
6510
6860
  var Timepicker = _Timepicker;
6511
6861
 
6512
6862
  // src/ts/components/snackbar.ts
6513
- var _defaults19 = {
6863
+ var _defaults21 = {
6514
6864
  text: "",
6515
6865
  action: "",
6516
6866
  onAction: null,
@@ -6557,7 +6907,7 @@ var _Snackbar = class _Snackbar {
6557
6907
  this._setTimer();
6558
6908
  }
6559
6909
  static get defaults() {
6560
- return _defaults19;
6910
+ return _defaults21;
6561
6911
  }
6562
6912
  static getInstance(el) {
6563
6913
  return el["Expressive_Snackbar"];
@@ -6792,7 +7142,7 @@ _Snackbar._draggedSnackbar = null;
6792
7142
  var Snackbar = _Snackbar;
6793
7143
 
6794
7144
  // src/ts/components/tooltip.ts
6795
- var _defaults20 = {
7145
+ var _defaults22 = {
6796
7146
  exitDelay: 200,
6797
7147
  enterDelay: 0,
6798
7148
  text: "",
@@ -6862,7 +7212,7 @@ var Tooltip = class _Tooltip extends Component {
6862
7212
  this._setupEventHandlers();
6863
7213
  }
6864
7214
  static get defaults() {
6865
- return _defaults20;
7215
+ return _defaults22;
6866
7216
  }
6867
7217
  /**
6868
7218
  * Initializes instances of Tooltip.
@@ -6876,6 +7226,12 @@ var Tooltip = class _Tooltip extends Component {
6876
7226
  return el["Expressive_Tooltip"];
6877
7227
  }
6878
7228
  destroy() {
7229
+ clearTimeout(this._enterDelayTimeout);
7230
+ clearTimeout(this._exitDelayTimeout);
7231
+ clearTimeout(this._animationTimeout);
7232
+ this.isOpen = false;
7233
+ this.isHovered = false;
7234
+ this.isFocused = false;
6879
7235
  if (this.el.getAttribute("aria-describedby") === this.tooltipEl.id) {
6880
7236
  this.el.removeAttribute("aria-describedby");
6881
7237
  }
@@ -6967,32 +7323,15 @@ var Tooltip = class _Tooltip extends Component {
6967
7323
  tooltip.style.left = newCoordinates.x + "px";
6968
7324
  }
6969
7325
  _repositionWithinScreen(x, y, width, height) {
6970
- const scrollLeft = Utils.getDocumentScrollLeft();
6971
- const scrollTop = Utils.getDocumentScrollTop();
6972
- let newX = x - scrollLeft;
6973
- let newY = y - scrollTop;
6974
- const bounding = {
6975
- left: newX,
6976
- top: newY,
7326
+ return Utils._repositionWithinScreen(
7327
+ x,
7328
+ y,
6977
7329
  width,
6978
- height
6979
- };
6980
- const offset = this.options.margin + this.options.transitionMovement;
6981
- const edges = Utils.checkWithinContainer(document.body, bounding, offset);
6982
- if (edges.left) {
6983
- newX = offset;
6984
- } else if (edges.right) {
6985
- newX -= newX + width - window.innerWidth;
6986
- }
6987
- if (edges.top) {
6988
- newY = offset;
6989
- } else if (edges.bottom) {
6990
- newY -= newY + height - window.innerHeight;
6991
- }
6992
- return {
6993
- x: newX + scrollLeft,
6994
- y: newY + scrollTop
6995
- };
7330
+ height,
7331
+ this.options.margin,
7332
+ this.options.transitionMovement,
7333
+ "center"
7334
+ );
6996
7335
  }
6997
7336
  _animateIn() {
6998
7337
  this._positionTooltip();
@@ -7001,7 +7340,8 @@ var Tooltip = class _Tooltip extends Component {
7001
7340
  this.tooltipEl.style.transition = `
7002
7341
  transform ${duration}ms ease-out,
7003
7342
  opacity ${duration}ms ease-out`;
7004
- setTimeout(() => {
7343
+ clearTimeout(this._animationTimeout);
7344
+ this._animationTimeout = setTimeout(() => {
7005
7345
  this.tooltipEl.style.transform = `translateX(${this.xMovement}px) translateY(${this.yMovement}px)`;
7006
7346
  this.tooltipEl.style.opacity = (this.options.opacity || 1).toString();
7007
7347
  }, 1);
@@ -7011,7 +7351,8 @@ var Tooltip = class _Tooltip extends Component {
7011
7351
  this.tooltipEl.style.transition = `
7012
7352
  transform ${duration}ms ease-out,
7013
7353
  opacity ${duration}ms ease-out`;
7014
- setTimeout(() => {
7354
+ clearTimeout(this._animationTimeout);
7355
+ this._animationTimeout = setTimeout(() => {
7015
7356
  this.tooltipEl.style.transform = `translateX(0px) translateY(0px)`;
7016
7357
  this.tooltipEl.style.opacity = "0";
7017
7358
  }, 1);
@@ -7036,13 +7377,21 @@ var Tooltip = class _Tooltip extends Component {
7036
7377
 
7037
7378
  // src/ts/components/registry.ts
7038
7379
  var AUTO_INIT_COMPONENTS = {
7380
+ AppBar: {
7381
+ component: AppBar,
7382
+ selector: "header.medium, header.large, header:has(> :is(nav:not(.tabs, .navigation-bar, .navigation-rail), .bar) > :is(.search-bar, .searchbar))"
7383
+ },
7039
7384
  Autocomplete: {
7040
7385
  component: Autocomplete,
7041
7386
  selector: ".autocomplete"
7042
7387
  },
7388
+ ButtonGroup: {
7389
+ component: ButtonGroup,
7390
+ selector: ".button-group"
7391
+ },
7043
7392
  // Shared with Cards.Init() - see CARDS_SELECTOR. This entry used to read
7044
7393
  // '.cards', which no card markup uses.
7045
- Cards: { component: Cards, selector: CARDS_SELECTOR },
7394
+ Cards: { component: Cards, selector: CARDS_SELECTOR, filter: isCardReveal },
7046
7395
  ExpandingCard: {
7047
7396
  component: ExpandingCard,
7048
7397
  selector: EXPANDING_CARD_SELECTOR
@@ -7078,14 +7427,20 @@ var AUTO_INIT_COMPONENTS = {
7078
7427
  };
7079
7428
  function AutoInit(context = document.body, options) {
7080
7429
  for (const name of Object.keys(AUTO_INIT_COMPONENTS)) {
7081
- const { component, selector } = AUTO_INIT_COMPONENTS[name];
7430
+ const { component, selector, filter } = AUTO_INIT_COMPONENTS[name];
7082
7431
  const els = context.querySelectorAll(`:is(${selector}):not(.no-autoinit)`);
7083
- component.init(els, options?.[name] ?? {});
7432
+ if (filter) {
7433
+ els.forEach((el) => {
7434
+ if (filter(el)) component.init(el, options?.[name] ?? {});
7435
+ });
7436
+ } else {
7437
+ component.init(els, options?.[name] ?? {});
7438
+ }
7084
7439
  }
7085
7440
  }
7086
7441
 
7087
7442
  // src/ts/index.ts
7088
- var version = "0.8.0";
7443
+ var version = "0.9.0";
7089
7444
  Forms.Init();
7090
7445
  Chips.Init();
7091
7446
  Slider.Init();
@@ -7095,9 +7450,11 @@ Dialogs.Init();
7095
7450
  BottomSheets.Init();
7096
7451
  SideSheets.Init();
7097
7452
  export {
7453
+ AppBar,
7098
7454
  AutoInit,
7099
7455
  Autocomplete,
7100
7456
  BottomSheets,
7457
+ ButtonGroup,
7101
7458
  Cards,
7102
7459
  Carousel,
7103
7460
  CharacterCounter,