@fluentui/web-components 2.2.1 → 2.3.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.
@@ -3405,7 +3405,10 @@ class ArrayObserver extends SubscriberSet {
3405
3405
  this.splices = void 0;
3406
3406
  this.needsQueue = true;
3407
3407
  this.call = this.flush;
3408
- source.$fastController = this;
3408
+ Reflect.defineProperty(source, "$fastController", {
3409
+ value: this,
3410
+ enumerable: false
3411
+ });
3409
3412
  }
3410
3413
 
3411
3414
  addSplice(splice) {
@@ -3469,16 +3472,26 @@ function enableArrayObservation() {
3469
3472
  Observable.setArrayObserverFactory(collection => {
3470
3473
  return new ArrayObserver(collection);
3471
3474
  });
3472
- const arrayProto = Array.prototype;
3473
- const pop = arrayProto.pop;
3474
- const push = arrayProto.push;
3475
- const reverse = arrayProto.reverse;
3476
- const shift = arrayProto.shift;
3477
- const sort = arrayProto.sort;
3478
- const splice = arrayProto.splice;
3479
- const unshift = arrayProto.unshift;
3480
-
3481
- arrayProto.pop = function () {
3475
+ const proto = Array.prototype; // Don't patch Array if it has already been patched
3476
+ // by another copy of fast-element.
3477
+
3478
+ if (proto.$fastPatch) {
3479
+ return;
3480
+ }
3481
+
3482
+ Reflect.defineProperty(proto, "$fastPatch", {
3483
+ value: 1,
3484
+ enumerable: false
3485
+ });
3486
+ const pop = proto.pop;
3487
+ const push = proto.push;
3488
+ const reverse = proto.reverse;
3489
+ const shift = proto.shift;
3490
+ const sort = proto.sort;
3491
+ const splice = proto.splice;
3492
+ const unshift = proto.unshift;
3493
+
3494
+ proto.pop = function () {
3482
3495
  const notEmpty = this.length > 0;
3483
3496
  const methodCallResult = pop.apply(this, arguments);
3484
3497
  const o = this.$fastController;
@@ -3490,7 +3503,7 @@ function enableArrayObservation() {
3490
3503
  return methodCallResult;
3491
3504
  };
3492
3505
 
3493
- arrayProto.push = function () {
3506
+ proto.push = function () {
3494
3507
  const methodCallResult = push.apply(this, arguments);
3495
3508
  const o = this.$fastController;
3496
3509
 
@@ -3501,7 +3514,7 @@ function enableArrayObservation() {
3501
3514
  return methodCallResult;
3502
3515
  };
3503
3516
 
3504
- arrayProto.reverse = function () {
3517
+ proto.reverse = function () {
3505
3518
  let oldArray;
3506
3519
  const o = this.$fastController;
3507
3520
 
@@ -3519,7 +3532,7 @@ function enableArrayObservation() {
3519
3532
  return methodCallResult;
3520
3533
  };
3521
3534
 
3522
- arrayProto.shift = function () {
3535
+ proto.shift = function () {
3523
3536
  const notEmpty = this.length > 0;
3524
3537
  const methodCallResult = shift.apply(this, arguments);
3525
3538
  const o = this.$fastController;
@@ -3531,7 +3544,7 @@ function enableArrayObservation() {
3531
3544
  return methodCallResult;
3532
3545
  };
3533
3546
 
3534
- arrayProto.sort = function () {
3547
+ proto.sort = function () {
3535
3548
  let oldArray;
3536
3549
  const o = this.$fastController;
3537
3550
 
@@ -3549,7 +3562,7 @@ function enableArrayObservation() {
3549
3562
  return methodCallResult;
3550
3563
  };
3551
3564
 
3552
- arrayProto.splice = function () {
3565
+ proto.splice = function () {
3553
3566
  const methodCallResult = splice.apply(this, arguments);
3554
3567
  const o = this.$fastController;
3555
3568
 
@@ -3560,7 +3573,7 @@ function enableArrayObservation() {
3560
3573
  return methodCallResult;
3561
3574
  };
3562
3575
 
3563
- arrayProto.unshift = function () {
3576
+ proto.unshift = function () {
3564
3577
  const methodCallResult = unshift.apply(this, arguments);
3565
3578
  const o = this.$fastController;
3566
3579
 
@@ -3634,7 +3647,8 @@ function when(binding, templateOrTemplateBinding) {
3634
3647
  }
3635
3648
 
3636
3649
  const defaultRepeatOptions = Object.freeze({
3637
- positioning: false
3650
+ positioning: false,
3651
+ recycle: true
3638
3652
  });
3639
3653
 
3640
3654
  function bindWithoutPositioning(view, items, index, context) {
@@ -3778,7 +3792,7 @@ class RepeatBehavior {
3778
3792
  for (; addIndex < end; ++addIndex) {
3779
3793
  const neighbor = views[addIndex];
3780
3794
  const location = neighbor ? neighbor.firstChild : this.location;
3781
- const view = totalRemoved.length > 0 ? totalRemoved.shift() : template.create();
3795
+ const view = this.options.recycle && totalRemoved.length > 0 ? totalRemoved.shift() : template.create();
3782
3796
  views.splice(addIndex, 0, view);
3783
3797
  bindView(view, items, addIndex, childContext);
3784
3798
  view.insertBefore(location);
@@ -4176,7 +4190,7 @@ const startTemplate = html`<span part="start" ${ref("startContainer")}><slot nam
4176
4190
  * @public
4177
4191
  */
4178
4192
 
4179
- const accordionItemTemplate = (context, definition) => html`<template class="${x => x.expanded ? "expanded" : ""}" slot="item"><div class="heading" part="heading" role="heading" aria-level="${x => x.headinglevel}"><button class="button" part="button" ${ref("expandbutton")} aria-expanded="${x => x.expanded}" aria-controls="${x => x.id}-panel" id="${x => x.id}" @click="${(x, c) => x.clickHandler(c.event)}"><span class="heading"><slot name="heading" part="heading"></slot></span></button>${startSlotTemplate(context, definition)} ${endSlotTemplate(context, definition)}<span class="icon" part="icon" aria-hidden="true"><slot name="expanded-icon" part="expanded-icon">${definition.expandedIcon || ""}</slot><slot name="collapsed-icon" part="collapsed-icon">${definition.collapsedIcon || ""}</slot><span></div><div class="region" part="region" id="${x => x.id}-panel" role="region" aria-labelledby="${x => x.id}"><slot></slot></div></template>`;
4193
+ const accordionItemTemplate = (context, definition) => html`<template class="${x => x.expanded ? "expanded" : ""}"><div class="heading" part="heading" role="heading" aria-level="${x => x.headinglevel}"><button class="button" part="button" ${ref("expandbutton")} aria-expanded="${x => x.expanded}" aria-controls="${x => x.id}-panel" id="${x => x.id}" @click="${(x, c) => x.clickHandler(c.event)}"><span class="heading"><slot name="heading" part="heading"></slot></span></button>${startSlotTemplate(context, definition)} ${endSlotTemplate(context, definition)}<span class="icon" part="icon" aria-hidden="true"><slot name="expanded-icon" part="expanded-icon">${definition.expandedIcon || ""}</slot><slot name="collapsed-icon" part="collapsed-icon">${definition.collapsedIcon || ""}</slot><span></div><div class="region" part="region" id="${x => x.id}-panel" role="region" aria-labelledby="${x => x.id}"><slot></slot></div></template>`;
4180
4194
 
4181
4195
  /*! *****************************************************************************
4182
4196
  Copyright (c) Microsoft Corporation.
@@ -5904,7 +5918,12 @@ applyMixins(AccordionItem, StartEnd);
5904
5918
  * @public
5905
5919
  */
5906
5920
 
5907
- const accordionTemplate = (context, definition) => html`<template><slot name="item" part="item" ${slotted("accordionItems")}></slot></template>`;
5921
+ const accordionTemplate = (context, definition) =>
5922
+ /* TODO: deprecate slot name `item` to only support default slot https://github.com/microsoft/fast/issues/5515 */
5923
+ html`<template><slot ${slotted({
5924
+ property: "accordionItems",
5925
+ filter: elements()
5926
+ })}></slot><slot name="item" part="item" ${slotted("accordionItems")}></slot></template>`;
5908
5927
 
5909
5928
  var Orientation;
5910
5929
 
@@ -5913,6 +5932,24 @@ var Orientation;
5913
5932
  Orientation["vertical"] = "vertical";
5914
5933
  })(Orientation || (Orientation = {}));
5915
5934
 
5935
+ /**
5936
+ * Returns the index of the last element in the array where predicate is true, and -1 otherwise.
5937
+ *
5938
+ * @param array - the array to test
5939
+ * @param predicate - find calls predicate once for each element of the array, in descending order, until it finds one where predicate returns true. If such an element is found, findLastIndex immediately returns that element index. Otherwise, findIndex returns -1.
5940
+ */
5941
+ function findLastIndex(array, predicate) {
5942
+ let k = array.length;
5943
+
5944
+ while (k--) {
5945
+ if (predicate(array[k], k, array)) {
5946
+ return k;
5947
+ }
5948
+ }
5949
+
5950
+ return -1;
5951
+ }
5952
+
5916
5953
  /**
5917
5954
  * Checks if the DOM is available to access and use
5918
5955
  */
@@ -6112,12 +6149,12 @@ const ArrowKeys = {
6112
6149
  /**
6113
6150
  * Expose ltr and rtl strings
6114
6151
  */
6115
- var Direction$1;
6152
+ var Direction;
6116
6153
 
6117
6154
  (function (Direction) {
6118
6155
  Direction["ltr"] = "ltr";
6119
6156
  Direction["rtl"] = "rtl";
6120
- })(Direction$1 || (Direction$1 = {}));
6157
+ })(Direction || (Direction = {}));
6121
6158
 
6122
6159
  /**
6123
6160
  * This method keeps a given value within the bounds of a min and max value. If the value
@@ -6141,6 +6178,18 @@ function wrapInBounds(min, max, value) {
6141
6178
  function limit(min, max, value) {
6142
6179
  return Math.min(Math.max(value, min), max);
6143
6180
  }
6181
+ /**
6182
+ * Determines if a number value is within a specified range.
6183
+ *
6184
+ * @param value - the value to check
6185
+ * @param min - the range start
6186
+ * @param max - the range end
6187
+ */
6188
+
6189
+ function inRange(value, min, max = 0) {
6190
+ [min, max] = [min, max].sort((a, b) => a - b);
6191
+ return min <= value && value < max;
6192
+ }
6144
6193
 
6145
6194
  let uniqueIdCounter = 0;
6146
6195
  /**
@@ -6151,6 +6200,28 @@ function uniqueId(prefix = "") {
6151
6200
  return `${prefix}${uniqueIdCounter++}`;
6152
6201
  }
6153
6202
 
6203
+ /**
6204
+ * Define system colors for use in CSS stylesheets.
6205
+ *
6206
+ * https://drafts.csswg.org/css-color/#css-system-colors
6207
+ */
6208
+ var SystemColors;
6209
+
6210
+ (function (SystemColors) {
6211
+ SystemColors["Canvas"] = "Canvas";
6212
+ SystemColors["CanvasText"] = "CanvasText";
6213
+ SystemColors["LinkText"] = "LinkText";
6214
+ SystemColors["VisitedText"] = "VisitedText";
6215
+ SystemColors["ActiveText"] = "ActiveText";
6216
+ SystemColors["ButtonFace"] = "ButtonFace";
6217
+ SystemColors["ButtonText"] = "ButtonText";
6218
+ SystemColors["Field"] = "Field";
6219
+ SystemColors["FieldText"] = "FieldText";
6220
+ SystemColors["Highlight"] = "Highlight";
6221
+ SystemColors["HighlightText"] = "HighlightText";
6222
+ SystemColors["GrayText"] = "GrayText";
6223
+ })(SystemColors || (SystemColors = {}));
6224
+
6154
6225
  /**
6155
6226
  * Expand mode for {@link Accordion}
6156
6227
  * @public
@@ -6238,7 +6309,7 @@ class Accordion extends FoundationElement {
6238
6309
 
6239
6310
  this.activeItemChange = event => {
6240
6311
  const selectedItem = event.target;
6241
- this.activeid = event.target.getAttribute("id");
6312
+ this.activeid = selectedItem.getAttribute("id");
6242
6313
 
6243
6314
  if (this.isSingleExpandMode()) {
6244
6315
  this.resetItems();
@@ -6562,7 +6633,7 @@ const anchoredRegionTemplate = (context, definition) => html`<template class="${
6562
6633
 
6563
6634
  const getDirection = rootNode => {
6564
6635
  const dirNode = rootNode.closest("[dir]");
6565
- return dirNode !== null && dirNode.dir === "rtl" ? Direction$1.rtl : Direction$1.ltr;
6636
+ return dirNode !== null && dirNode.dir === "rtl" ? Direction.rtl : Direction.ltr;
6566
6637
  };
6567
6638
 
6568
6639
  /**
@@ -6850,7 +6921,7 @@ class AnchoredRegion extends FoundationElement {
6850
6921
  this.baseVerticalOffset = 0;
6851
6922
  this.pendingPositioningUpdate = false;
6852
6923
  this.pendingReset = false;
6853
- this.currentDirection = Direction$1.ltr;
6924
+ this.currentDirection = Direction.ltr;
6854
6925
  this.regionVisible = false; // indicates that a layout update should occur even if geometry has not changed
6855
6926
  // used to ensure some attribute changes are applied
6856
6927
 
@@ -7079,7 +7150,7 @@ class AnchoredRegion extends FoundationElement {
7079
7150
  return;
7080
7151
  }
7081
7152
 
7082
- if (this.currentDirection === Direction$1.ltr) {
7153
+ if (this.currentDirection === Direction.ltr) {
7083
7154
  dirCorrectedHorizontalDefaultPosition = dirCorrectedHorizontalDefaultPosition === "start" ? "left" : "right";
7084
7155
  } else {
7085
7156
  dirCorrectedHorizontalDefaultPosition = dirCorrectedHorizontalDefaultPosition === "start" ? "right" : "left";
@@ -8480,10 +8551,23 @@ class FormAssociatedButton extends FormAssociated(_Button) {
8480
8551
  class Button$1 extends FormAssociatedButton {
8481
8552
  constructor() {
8482
8553
  super(...arguments);
8554
+ /**
8555
+ * Prevent events to propagate if disabled and has no slotted content wrapped in HTML elements
8556
+ * @internal
8557
+ */
8558
+
8559
+ this.handleClick = e => {
8560
+ var _a;
8561
+
8562
+ if (this.disabled && ((_a = this.defaultSlottedContent) === null || _a === void 0 ? void 0 : _a.length) <= 1) {
8563
+ e.stopPropagation();
8564
+ }
8565
+ };
8483
8566
  /**
8484
8567
  * Submits the parent form
8485
8568
  */
8486
8569
 
8570
+
8487
8571
  this.handleSubmission = () => {
8488
8572
  if (!this.form) {
8489
8573
  return;
@@ -8578,9 +8662,35 @@ class Button$1 extends FormAssociatedButton {
8578
8662
 
8579
8663
 
8580
8664
  connectedCallback() {
8665
+ var _a;
8666
+
8581
8667
  super.connectedCallback();
8582
8668
  this.proxy.setAttribute("type", this.type);
8583
8669
  this.handleUnsupportedDelegatesFocus();
8670
+ const elements = Array.from((_a = this.control) === null || _a === void 0 ? void 0 : _a.children);
8671
+
8672
+ if (elements) {
8673
+ elements.forEach(span => {
8674
+ span.addEventListener("click", this.handleClick);
8675
+ });
8676
+ }
8677
+ }
8678
+ /**
8679
+ * @internal
8680
+ */
8681
+
8682
+
8683
+ disconnectedCallback() {
8684
+ var _a;
8685
+
8686
+ super.disconnectedCallback();
8687
+ const elements = Array.from((_a = this.control) === null || _a === void 0 ? void 0 : _a.children);
8688
+
8689
+ if (elements) {
8690
+ elements.forEach(span => {
8691
+ span.removeEventListener("click", this.handleClick);
8692
+ });
8693
+ }
8584
8694
  }
8585
8695
 
8586
8696
  }
@@ -10341,28 +10451,6 @@ __decorate$1([observable], Checkbox.prototype, "defaultSlottedNodes", void 0);
10341
10451
 
10342
10452
  __decorate$1([observable], Checkbox.prototype, "indeterminate", void 0);
10343
10453
 
10344
- /**
10345
- * Positioning directions for the listbox when a select is open.
10346
- * @public
10347
- */
10348
- var SelectPosition;
10349
-
10350
- (function (SelectPosition) {
10351
- SelectPosition["above"] = "above";
10352
- SelectPosition["below"] = "below";
10353
- })(SelectPosition || (SelectPosition = {}));
10354
- /**
10355
- * Select role.
10356
- * @public
10357
- */
10358
-
10359
-
10360
- var SelectRole;
10361
-
10362
- (function (SelectRole) {
10363
- SelectRole["combobox"] = "combobox";
10364
- })(SelectRole || (SelectRole = {}));
10365
-
10366
10454
  /**
10367
10455
  * Determines if the element is a {@link (ListboxOption:class)}
10368
10456
  *
@@ -10407,7 +10495,6 @@ class ListboxOption extends FoundationElement {
10407
10495
  */
10408
10496
 
10409
10497
  this.dirtyValue = false;
10410
- this.initialValue = this.initialValue || "";
10411
10498
 
10412
10499
  if (text) {
10413
10500
  this.textContent = text;
@@ -10428,6 +10515,24 @@ class ListboxOption extends FoundationElement {
10428
10515
  this.proxy = new Option(`${this.textContent}`, this.initialValue, this.defaultSelected, this.selected);
10429
10516
  this.proxy.disabled = this.disabled;
10430
10517
  }
10518
+ /**
10519
+ * Updates the ariaChecked property when the checked property changes.
10520
+ *
10521
+ * @param prev - the previous checked value
10522
+ * @param next - the current checked value
10523
+ *
10524
+ * @public
10525
+ */
10526
+
10527
+
10528
+ checkedChanged(prev, next) {
10529
+ if (typeof next === "boolean") {
10530
+ this.ariaChecked = next ? "true" : "false";
10531
+ return;
10532
+ }
10533
+
10534
+ this.ariaChecked = undefined;
10535
+ }
10431
10536
 
10432
10537
  defaultSelectedChanged() {
10433
10538
  if (!this.dirtySelected) {
@@ -10440,6 +10545,8 @@ class ListboxOption extends FoundationElement {
10440
10545
  }
10441
10546
 
10442
10547
  disabledChanged(prev, next) {
10548
+ this.ariaDisabled = this.disabled ? "true" : "false";
10549
+
10443
10550
  if (this.proxy instanceof HTMLOptionElement) {
10444
10551
  this.proxy.disabled = this.disabled;
10445
10552
  }
@@ -10454,14 +10561,14 @@ class ListboxOption extends FoundationElement {
10454
10561
  }
10455
10562
 
10456
10563
  selectedChanged() {
10457
- if (this.$fastController.isConnected) {
10458
- if (!this.dirtySelected) {
10459
- this.dirtySelected = true;
10460
- }
10564
+ this.ariaSelected = this.selected ? "true" : "false";
10461
10565
 
10462
- if (this.proxy instanceof HTMLOptionElement) {
10463
- this.proxy.selected = this.selected;
10464
- }
10566
+ if (!this.dirtySelected) {
10567
+ this.dirtySelected = true;
10568
+ }
10569
+
10570
+ if (this.proxy instanceof HTMLOptionElement) {
10571
+ this.proxy.selected = this.selected;
10465
10572
  }
10466
10573
  }
10467
10574
 
@@ -10475,7 +10582,9 @@ class ListboxOption extends FoundationElement {
10475
10582
  }
10476
10583
 
10477
10584
  get label() {
10478
- return this.value ? this.value : this.textContent ? this.textContent : "";
10585
+ var _a, _b;
10586
+
10587
+ return (_b = (_a = this.value) !== null && _a !== void 0 ? _a : this.textContent) !== null && _b !== void 0 ? _b : "";
10479
10588
  }
10480
10589
 
10481
10590
  get text() {
@@ -10494,8 +10603,10 @@ class ListboxOption extends FoundationElement {
10494
10603
  }
10495
10604
 
10496
10605
  get value() {
10606
+ var _a, _b;
10607
+
10497
10608
  Observable.track(this, "value");
10498
- return this._value ? this._value : this.text;
10609
+ return (_b = (_a = this._value) !== null && _a !== void 0 ? _a : this.textContent) !== null && _b !== void 0 ? _b : "";
10499
10610
  }
10500
10611
 
10501
10612
  get form() {
@@ -10504,6 +10615,8 @@ class ListboxOption extends FoundationElement {
10504
10615
 
10505
10616
  }
10506
10617
 
10618
+ __decorate$1([observable], ListboxOption.prototype, "checked", void 0);
10619
+
10507
10620
  __decorate$1([observable], ListboxOption.prototype, "defaultSelected", void 0);
10508
10621
 
10509
10622
  __decorate$1([attr({
@@ -10521,18 +10634,25 @@ __decorate$1([attr({
10521
10634
  attribute: "value",
10522
10635
  mode: "fromView"
10523
10636
  })], ListboxOption.prototype, "initialValue", void 0);
10524
-
10525
- applyMixins(ListboxOption, StartEnd);
10526
-
10527
10637
  /**
10528
- * Listbox role.
10638
+ * States and properties relating to the ARIA `option` role.
10639
+ *
10529
10640
  * @public
10530
10641
  */
10531
- var ListboxRole;
10532
10642
 
10533
- (function (ListboxRole) {
10534
- ListboxRole["listbox"] = "listbox";
10535
- })(ListboxRole || (ListboxRole = {}));
10643
+
10644
+ class DelegatesARIAListboxOption {}
10645
+
10646
+ __decorate$1([observable], DelegatesARIAListboxOption.prototype, "ariaChecked", void 0);
10647
+
10648
+ __decorate$1([observable], DelegatesARIAListboxOption.prototype, "ariaPosInSet", void 0);
10649
+
10650
+ __decorate$1([observable], DelegatesARIAListboxOption.prototype, "ariaSelected", void 0);
10651
+
10652
+ __decorate$1([observable], DelegatesARIAListboxOption.prototype, "ariaSetSize", void 0);
10653
+
10654
+ applyMixins(DelegatesARIAListboxOption, ARIAGlobalStatesAndProperties);
10655
+ applyMixins(ListboxOption, StartEnd, DelegatesARIAListboxOption);
10536
10656
 
10537
10657
  /**
10538
10658
  * A Listbox Custom HTML Element.
@@ -10551,15 +10671,6 @@ class Listbox$1 extends FoundationElement {
10551
10671
  */
10552
10672
 
10553
10673
  this._options = [];
10554
- /**
10555
- * The role of the element.
10556
- *
10557
- * @public
10558
- * @remarks
10559
- * HTML Attribute: `role`
10560
- */
10561
-
10562
- this.role = ListboxRole.listbox;
10563
10674
  /**
10564
10675
  * The index of the selected option.
10565
10676
  *
@@ -10616,6 +10727,16 @@ class Listbox$1 extends FoundationElement {
10616
10727
 
10617
10728
  return (_a = this.selectedOptions[0]) !== null && _a !== void 0 ? _a : null;
10618
10729
  }
10730
+ /**
10731
+ * Returns true if there is one or more selectable option.
10732
+ *
10733
+ * @internal
10734
+ */
10735
+
10736
+
10737
+ get hasSelectableOptions() {
10738
+ return this.options.length > 0 && !this.options.every(o => o.disabled);
10739
+ }
10619
10740
  /**
10620
10741
  * The number of options.
10621
10742
  *
@@ -10624,11 +10745,9 @@ class Listbox$1 extends FoundationElement {
10624
10745
 
10625
10746
 
10626
10747
  get length() {
10627
- if (this.options) {
10628
- return this.options.length;
10629
- }
10748
+ var _a, _b;
10630
10749
 
10631
- return 0;
10750
+ return (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
10632
10751
  }
10633
10752
  /**
10634
10753
  * The list of options.
@@ -10677,17 +10796,23 @@ class Listbox$1 extends FoundationElement {
10677
10796
  }
10678
10797
  }
10679
10798
  /**
10680
- * Focus the first selected option and scroll it into view.
10799
+ * Ensures that the provided option is focused and scrolled into view.
10681
10800
  *
10801
+ * @param optionToFocus - The option to focus
10682
10802
  * @internal
10683
10803
  */
10684
10804
 
10685
10805
 
10686
- focusAndScrollOptionIntoView() {
10687
- if (this.contains(document.activeElement) && this.firstSelectedOption) {
10688
- this.firstSelectedOption.focus();
10806
+ focusAndScrollOptionIntoView(optionToFocus = this.firstSelectedOption) {
10807
+ // To ensure that the browser handles both `focus()` and `scrollIntoView()`, the
10808
+ // timing here needs to guarantee that they happen on different frames. Since this
10809
+ // function is typically called from the `openChanged` observer, `DOM.queueUpdate`
10810
+ // causes the calls to be grouped into the same frame. To prevent this,
10811
+ // `requestAnimationFrame` is used instead of `DOM.queueUpdate`.
10812
+ if (this.contains(document.activeElement) && optionToFocus !== null) {
10813
+ optionToFocus.focus();
10689
10814
  requestAnimationFrame(() => {
10690
- this.firstSelectedOption.scrollIntoView({
10815
+ optionToFocus.scrollIntoView({
10691
10816
  block: "nearest"
10692
10817
  });
10693
10818
  });
@@ -10710,6 +10835,72 @@ class Listbox$1 extends FoundationElement {
10710
10835
 
10711
10836
  this.shouldSkipFocus = false;
10712
10837
  }
10838
+ /**
10839
+ * Returns the options which match the current typeahead buffer.
10840
+ *
10841
+ * @internal
10842
+ */
10843
+
10844
+
10845
+ getTypeaheadMatches() {
10846
+ const pattern = this.typeaheadBuffer.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&");
10847
+ const re = new RegExp(`^${pattern}`, "gi");
10848
+ return this.options.filter(o => o.text.trim().match(re));
10849
+ }
10850
+ /**
10851
+ * Determines the index of the next option which is selectable, if any.
10852
+ *
10853
+ * @param prev - the previous selected index
10854
+ * @param next - the next index to select
10855
+ *
10856
+ * @internal
10857
+ */
10858
+
10859
+
10860
+ getSelectableIndex(prev = this.selectedIndex, next) {
10861
+ const direction = prev > next ? -1 : prev < next ? 1 : 0;
10862
+ const potentialDirection = prev + direction;
10863
+ let nextSelectableOption = null;
10864
+
10865
+ switch (direction) {
10866
+ case -1:
10867
+ {
10868
+ nextSelectableOption = this.options.reduceRight((nextSelectableOption, thisOption, index) => !nextSelectableOption && !thisOption.disabled && index < potentialDirection ? thisOption : nextSelectableOption, nextSelectableOption);
10869
+ break;
10870
+ }
10871
+
10872
+ case 1:
10873
+ {
10874
+ nextSelectableOption = this.options.reduce((nextSelectableOption, thisOption, index) => !nextSelectableOption && !thisOption.disabled && index > potentialDirection ? thisOption : nextSelectableOption, nextSelectableOption);
10875
+ break;
10876
+ }
10877
+ }
10878
+
10879
+ return this.options.indexOf(nextSelectableOption);
10880
+ }
10881
+ /**
10882
+ * Handles external changes to child options.
10883
+ *
10884
+ * @param source - the source object
10885
+ * @param propertyName - the property
10886
+ *
10887
+ * @internal
10888
+ */
10889
+
10890
+
10891
+ handleChange(source, propertyName) {
10892
+ switch (propertyName) {
10893
+ case "selected":
10894
+ {
10895
+ if (Listbox$1.slottedOptionFilter(source)) {
10896
+ this.selectedIndex = this.options.indexOf(source);
10897
+ }
10898
+
10899
+ this.setSelectedOptions();
10900
+ break;
10901
+ }
10902
+ }
10903
+ }
10713
10904
  /**
10714
10905
  * Moves focus to an option whose label matches characters typed by the user.
10715
10906
  * Consecutive keystrokes are batched into a buffer of search text used
@@ -10717,6 +10908,8 @@ class Listbox$1 extends FoundationElement {
10717
10908
  * between consecutive keystrokes, the search restarts.
10718
10909
  *
10719
10910
  * @param key - the key to be evaluated
10911
+ *
10912
+ * @internal
10720
10913
  */
10721
10914
 
10722
10915
 
@@ -10832,6 +11025,19 @@ class Listbox$1 extends FoundationElement {
10832
11025
  this.shouldSkipFocus = !this.contains(document.activeElement);
10833
11026
  return true;
10834
11027
  }
11028
+ /**
11029
+ * Switches between single-selection and multi-selection mode.
11030
+ *
11031
+ * @param prev - the previous value of the `multiple` attribute
11032
+ * @param next - the next value of the `multiple` attribute
11033
+ *
11034
+ * @internal
11035
+ */
11036
+
11037
+
11038
+ multipleChanged(prev, next) {
11039
+ this.ariaMultiSelectable = next ? "true" : undefined;
11040
+ }
10835
11041
  /**
10836
11042
  * Updates the list of selected options when the `selectedIndex` changes.
10837
11043
  *
@@ -10843,6 +11049,25 @@ class Listbox$1 extends FoundationElement {
10843
11049
 
10844
11050
 
10845
11051
  selectedIndexChanged(prev, next) {
11052
+ var _a;
11053
+
11054
+ if (!this.hasSelectableOptions) {
11055
+ this.selectedIndex = -1;
11056
+ return;
11057
+ }
11058
+
11059
+ if (((_a = this.options[this.selectedIndex]) === null || _a === void 0 ? void 0 : _a.disabled) && typeof prev === "number") {
11060
+ const selectableIndex = this.getSelectableIndex(prev, next);
11061
+ const newNext = selectableIndex > -1 ? selectableIndex : prev;
11062
+ this.selectedIndex = newNext;
11063
+
11064
+ if (next === newNext) {
11065
+ this.selectedIndexChanged(next, newNext);
11066
+ }
11067
+
11068
+ return;
11069
+ }
11070
+
10846
11071
  this.setSelectedOptions();
10847
11072
  }
10848
11073
  /**
@@ -10856,11 +11081,15 @@ class Listbox$1 extends FoundationElement {
10856
11081
 
10857
11082
 
10858
11083
  selectedOptionsChanged(prev, next) {
10859
- if (this.$fastController.isConnected) {
10860
- this.options.forEach(o => {
10861
- o.selected = next.includes(o);
10862
- });
10863
- }
11084
+ var _a;
11085
+
11086
+ const filteredNext = next.filter(Listbox$1.slottedOptionFilter);
11087
+ (_a = this.options) === null || _a === void 0 ? void 0 : _a.forEach(o => {
11088
+ const notifier = Observable.getNotifier(o);
11089
+ notifier.unsubscribe(this, "selected");
11090
+ o.selected = filteredNext.includes(o);
11091
+ notifier.subscribe(this, "selected");
11092
+ });
10864
11093
  }
10865
11094
  /**
10866
11095
  * Moves focus to the first selectable option.
@@ -10870,8 +11099,10 @@ class Listbox$1 extends FoundationElement {
10870
11099
 
10871
11100
 
10872
11101
  selectFirstOption() {
11102
+ var _a, _b;
11103
+
10873
11104
  if (!this.disabled) {
10874
- this.selectedIndex = 0;
11105
+ this.selectedIndex = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.findIndex(o => !o.disabled)) !== null && _b !== void 0 ? _b : -1;
10875
11106
  }
10876
11107
  }
10877
11108
  /**
@@ -10883,7 +11114,7 @@ class Listbox$1 extends FoundationElement {
10883
11114
 
10884
11115
  selectLastOption() {
10885
11116
  if (!this.disabled) {
10886
- this.selectedIndex = this.options.length - 1;
11117
+ this.selectedIndex = findLastIndex(this.options, o => !o.disabled);
10887
11118
  }
10888
11119
  }
10889
11120
  /**
@@ -10894,7 +11125,7 @@ class Listbox$1 extends FoundationElement {
10894
11125
 
10895
11126
 
10896
11127
  selectNextOption() {
10897
- if (!this.disabled && this.options && this.selectedIndex < this.options.length - 1) {
11128
+ if (!this.disabled && this.selectedIndex < this.options.length - 1) {
10898
11129
  this.selectedIndex += 1;
10899
11130
  }
10900
11131
  }
@@ -10918,8 +11149,10 @@ class Listbox$1 extends FoundationElement {
10918
11149
 
10919
11150
 
10920
11151
  setDefaultSelectedOption() {
10921
- if (this.options && this.$fastController.isConnected) {
10922
- const selectedIndex = this.options.findIndex(el => el.getAttribute("selected") !== null);
11152
+ var _a;
11153
+
11154
+ if (this.$fastController.isConnected) {
11155
+ const selectedIndex = (_a = this.options) === null || _a === void 0 ? void 0 : _a.findIndex(el => el.getAttribute("selected") !== null);
10923
11156
 
10924
11157
  if (selectedIndex !== -1) {
10925
11158
  this.selectedIndex = selectedIndex;
@@ -10930,7 +11163,7 @@ class Listbox$1 extends FoundationElement {
10930
11163
  }
10931
11164
  }
10932
11165
  /**
10933
- * Sets the selected option and gives it focus.
11166
+ * Sets an option as selected and gives it focus.
10934
11167
  *
10935
11168
  * @public
10936
11169
  */
@@ -10939,9 +11172,8 @@ class Listbox$1 extends FoundationElement {
10939
11172
  setSelectedOptions() {
10940
11173
  var _a, _b, _c;
10941
11174
 
10942
- if (this.$fastController.isConnected && this.options) {
10943
- const selectedOption = (_a = this.options[this.selectedIndex]) !== null && _a !== void 0 ? _a : null;
10944
- this.selectedOptions = this.options.filter(el => el.isSameNode(selectedOption));
11175
+ if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.length) && !this.disabled) {
11176
+ this.selectedOptions = [this.options[this.selectedIndex]];
10945
11177
  this.ariaActiveDescendant = (_c = (_b = this.firstSelectedOption) === null || _b === void 0 ? void 0 : _b.id) !== null && _c !== void 0 ? _c : "";
10946
11178
  this.focusAndScrollOptionIntoView();
10947
11179
  }
@@ -10957,17 +11189,24 @@ class Listbox$1 extends FoundationElement {
10957
11189
 
10958
11190
 
10959
11191
  slottedOptionsChanged(prev, next) {
10960
- if (this.$fastController.isConnected) {
10961
- this.options = next.reduce((options, item) => {
10962
- if (isListboxOption(item)) {
10963
- options.push(item);
10964
- }
11192
+ this.options = next.reduce((options, item) => {
11193
+ if (isListboxOption(item)) {
11194
+ options.push(item);
11195
+ }
10965
11196
 
10966
- return options;
10967
- }, []);
10968
- this.options.forEach(o => {
10969
- o.id = o.id || uniqueId("option-");
10970
- });
11197
+ return options;
11198
+ }, []);
11199
+ const setSize = `${this.options.length}`;
11200
+ this.options.forEach((option, index) => {
11201
+ if (!option.id) {
11202
+ option.id = uniqueId("option-");
11203
+ }
11204
+
11205
+ option.ariaPosInSet = `${index + 1}`;
11206
+ option.ariaSetSize = setSize;
11207
+ });
11208
+
11209
+ if (this.$fastController.isConnected) {
10971
11210
  this.setSelectedOptions();
10972
11211
  this.setDefaultSelectedOption();
10973
11212
  }
@@ -10984,12 +11223,10 @@ class Listbox$1 extends FoundationElement {
10984
11223
 
10985
11224
  typeaheadBufferChanged(prev, next) {
10986
11225
  if (this.$fastController.isConnected) {
10987
- const pattern = this.typeaheadBuffer.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&");
10988
- const re = new RegExp(`^${pattern}`, "gi");
10989
- const filteredOptions = this.options.filter(o => o.text.trim().match(re));
11226
+ const typeaheadMatches = this.getTypeaheadMatches();
10990
11227
 
10991
- if (filteredOptions.length) {
10992
- const selectedIndex = this.options.indexOf(filteredOptions[0]);
11228
+ if (typeaheadMatches.length) {
11229
+ const selectedIndex = this.options.indexOf(typeaheadMatches[0]);
10993
11230
 
10994
11231
  if (selectedIndex > -1) {
10995
11232
  this.selectedIndex = selectedIndex;
@@ -11022,7 +11259,9 @@ __decorate$1([attr({
11022
11259
  mode: "boolean"
11023
11260
  })], Listbox$1.prototype, "disabled", void 0);
11024
11261
 
11025
- __decorate$1([attr], Listbox$1.prototype, "role", void 0);
11262
+ __decorate$1([attr({
11263
+ mode: "boolean"
11264
+ })], Listbox$1.prototype, "multiple", void 0);
11026
11265
 
11027
11266
  __decorate$1([observable], Listbox$1.prototype, "selectedIndex", void 0);
11028
11267
 
@@ -11038,18 +11277,7 @@ __decorate$1([observable], Listbox$1.prototype, "typeaheadBuffer", void 0);
11038
11277
  */
11039
11278
 
11040
11279
 
11041
- class DelegatesARIAListbox {
11042
- constructor() {
11043
- /**
11044
- * See {@link https://www.w3.org/WAI/PF/aria/roles#listbox} for more information
11045
- * @public
11046
- * @remarks
11047
- * HTML Attribute: aria-activedescendant
11048
- */
11049
- this.ariaActiveDescendant = "";
11050
- }
11051
-
11052
- }
11280
+ class DelegatesARIAListbox {}
11053
11281
 
11054
11282
  __decorate$1([observable], DelegatesARIAListbox.prototype, "ariaActiveDescendant", void 0);
11055
11283
 
@@ -11057,24 +11285,595 @@ __decorate$1([observable], DelegatesARIAListbox.prototype, "ariaDisabled", void
11057
11285
 
11058
11286
  __decorate$1([observable], DelegatesARIAListbox.prototype, "ariaExpanded", void 0);
11059
11287
 
11288
+ __decorate$1([observable], DelegatesARIAListbox.prototype, "ariaMultiSelectable", void 0);
11289
+
11060
11290
  applyMixins(DelegatesARIAListbox, ARIAGlobalStatesAndProperties);
11061
11291
  applyMixins(Listbox$1, DelegatesARIAListbox);
11062
11292
 
11063
- class _Combobox extends Listbox$1 {}
11064
11293
  /**
11065
- * A form-associated base class for the {@link (Combobox:class)} component.
11294
+ * A Listbox Custom HTML Element.
11295
+ * Implements the {@link https://w3c.github.io/aria/#listbox | ARIA listbox }.
11066
11296
  *
11067
- * @internal
11297
+ * @public
11068
11298
  */
11069
11299
 
11070
-
11071
- class FormAssociatedCombobox extends FormAssociated(_Combobox) {
11300
+ class ListboxElement extends Listbox$1 {
11072
11301
  constructor() {
11073
11302
  super(...arguments);
11074
- this.proxy = document.createElement("input");
11075
- }
11076
-
11077
- }
11303
+ /**
11304
+ * The index of the most recently checked option.
11305
+ *
11306
+ * @internal
11307
+ * @remarks
11308
+ * Multiple-selection mode only.
11309
+ */
11310
+
11311
+ this.activeIndex = -1;
11312
+ /**
11313
+ * The start index when checking a range of options.
11314
+ *
11315
+ * @internal
11316
+ */
11317
+
11318
+ this.rangeStartIndex = -1;
11319
+ }
11320
+ /**
11321
+ * Returns the last checked option.
11322
+ *
11323
+ * @internal
11324
+ */
11325
+
11326
+
11327
+ get activeOption() {
11328
+ return this.options[this.activeIndex];
11329
+ }
11330
+ /**
11331
+ * Returns the list of checked options.
11332
+ *
11333
+ * @internal
11334
+ */
11335
+
11336
+
11337
+ get checkedOptions() {
11338
+ var _a;
11339
+
11340
+ return (_a = this.options) === null || _a === void 0 ? void 0 : _a.filter(o => o.checked);
11341
+ }
11342
+ /**
11343
+ * Returns the index of the first selected option.
11344
+ *
11345
+ * @internal
11346
+ */
11347
+
11348
+
11349
+ get firstSelectedOptionIndex() {
11350
+ return this.options.indexOf(this.firstSelectedOption);
11351
+ }
11352
+ /**
11353
+ * Updates the `ariaActiveDescendant` property when the active index changes.
11354
+ *
11355
+ * @param prev - the previous active index
11356
+ * @param next - the next active index
11357
+ *
11358
+ * @internal
11359
+ */
11360
+
11361
+
11362
+ activeIndexChanged(prev, next) {
11363
+ var _a, _b;
11364
+
11365
+ this.ariaActiveDescendant = (_b = (_a = this.options[next]) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : "";
11366
+ this.focusAndScrollOptionIntoView();
11367
+ }
11368
+ /**
11369
+ * Toggles the checked state for the currently active option.
11370
+ *
11371
+ * @remarks
11372
+ * Multiple-selection mode only.
11373
+ *
11374
+ * @internal
11375
+ */
11376
+
11377
+
11378
+ checkActiveIndex() {
11379
+ if (!this.multiple) {
11380
+ return;
11381
+ }
11382
+
11383
+ const activeItem = this.activeOption;
11384
+
11385
+ if (activeItem) {
11386
+ activeItem.checked = true;
11387
+ }
11388
+ }
11389
+ /**
11390
+ * Sets the active index to the first option and marks it as checked.
11391
+ *
11392
+ * @remarks
11393
+ * Multi-selection mode only.
11394
+ *
11395
+ * @param preserveChecked - mark all options unchecked before changing the active index
11396
+ *
11397
+ * @internal
11398
+ */
11399
+
11400
+
11401
+ checkFirstOption(preserveChecked = false) {
11402
+ if (preserveChecked) {
11403
+ if (this.rangeStartIndex === -1) {
11404
+ this.rangeStartIndex = this.activeIndex + 1;
11405
+ }
11406
+
11407
+ this.options.forEach((o, i) => {
11408
+ o.checked = inRange(i, this.rangeStartIndex);
11409
+ });
11410
+ } else {
11411
+ this.uncheckAllOptions();
11412
+ }
11413
+
11414
+ this.activeIndex = 0;
11415
+ this.checkActiveIndex();
11416
+ }
11417
+ /**
11418
+ * Decrements the active index and sets the matching option as checked.
11419
+ *
11420
+ * @remarks
11421
+ * Multi-selection mode only.
11422
+ *
11423
+ * @param preserveChecked - mark all options unchecked before changing the active index
11424
+ *
11425
+ * @internal
11426
+ */
11427
+
11428
+
11429
+ checkLastOption(preserveChecked = false) {
11430
+ if (preserveChecked) {
11431
+ if (this.rangeStartIndex === -1) {
11432
+ this.rangeStartIndex = this.activeIndex;
11433
+ }
11434
+
11435
+ this.options.forEach((o, i) => {
11436
+ o.checked = inRange(i, this.rangeStartIndex, this.options.length);
11437
+ });
11438
+ } else {
11439
+ this.uncheckAllOptions();
11440
+ }
11441
+
11442
+ this.activeIndex = this.options.length - 1;
11443
+ this.checkActiveIndex();
11444
+ }
11445
+ /**
11446
+ * @override
11447
+ * @internal
11448
+ */
11449
+
11450
+
11451
+ connectedCallback() {
11452
+ super.connectedCallback();
11453
+ this.addEventListener("focusout", this.focusoutHandler);
11454
+ }
11455
+ /**
11456
+ * @override
11457
+ * @internal
11458
+ */
11459
+
11460
+
11461
+ disconnectedCallback() {
11462
+ this.removeEventListener("focusout", this.focusoutHandler);
11463
+ super.disconnectedCallback();
11464
+ }
11465
+ /**
11466
+ * Increments the active index and marks the matching option as checked.
11467
+ *
11468
+ * @remarks
11469
+ * Multiple-selection mode only.
11470
+ *
11471
+ * @param preserveChecked - mark all options unchecked before changing the active index
11472
+ *
11473
+ * @internal
11474
+ */
11475
+
11476
+
11477
+ checkNextOption(preserveChecked = false) {
11478
+ if (preserveChecked) {
11479
+ if (this.rangeStartIndex === -1) {
11480
+ this.rangeStartIndex = this.activeIndex;
11481
+ }
11482
+
11483
+ this.options.forEach((o, i) => {
11484
+ o.checked = inRange(i, this.rangeStartIndex, this.activeIndex + 1);
11485
+ });
11486
+ } else {
11487
+ this.uncheckAllOptions();
11488
+ }
11489
+
11490
+ this.activeIndex += this.activeIndex < this.options.length - 1 ? 1 : 0;
11491
+ this.checkActiveIndex();
11492
+ }
11493
+ /**
11494
+ * Decrements the active index and marks the matching option as checked.
11495
+ *
11496
+ * @remarks
11497
+ * Multiple-selection mode only.
11498
+ *
11499
+ * @param preserveChecked - mark all options unchecked before changing the active index
11500
+ *
11501
+ * @internal
11502
+ */
11503
+
11504
+
11505
+ checkPreviousOption(preserveChecked = false) {
11506
+ if (preserveChecked) {
11507
+ if (this.rangeStartIndex === -1) {
11508
+ this.rangeStartIndex = this.activeIndex;
11509
+ }
11510
+
11511
+ if (this.checkedOptions.length === 1) {
11512
+ this.rangeStartIndex += 1;
11513
+ }
11514
+
11515
+ this.options.forEach((o, i) => {
11516
+ o.checked = inRange(i, this.activeIndex, this.rangeStartIndex);
11517
+ });
11518
+ } else {
11519
+ this.uncheckAllOptions();
11520
+ }
11521
+
11522
+ this.activeIndex -= this.activeIndex > 0 ? 1 : 0;
11523
+ this.checkActiveIndex();
11524
+ }
11525
+ /**
11526
+ * Handles click events for listbox options.
11527
+ *
11528
+ * @param e - the event object
11529
+ *
11530
+ * @override
11531
+ * @internal
11532
+ */
11533
+
11534
+
11535
+ clickHandler(e) {
11536
+ var _a;
11537
+
11538
+ if (!this.multiple) {
11539
+ return super.clickHandler(e);
11540
+ }
11541
+
11542
+ const captured = (_a = e.target) === null || _a === void 0 ? void 0 : _a.closest(`[role=option]`);
11543
+
11544
+ if (!captured || captured.disabled) {
11545
+ return;
11546
+ }
11547
+
11548
+ this.uncheckAllOptions();
11549
+ this.activeIndex = this.options.indexOf(captured);
11550
+ this.checkActiveIndex();
11551
+ this.toggleSelectedForAllCheckedOptions();
11552
+ return true;
11553
+ }
11554
+ /**
11555
+ * @override
11556
+ * @internal
11557
+ */
11558
+
11559
+
11560
+ focusAndScrollOptionIntoView() {
11561
+ super.focusAndScrollOptionIntoView(this.activeOption);
11562
+ }
11563
+ /**
11564
+ * In multiple-selection mode:
11565
+ * If any options are selected, the first selected option is checked when
11566
+ * the listbox receives focus. If no options are selected, the first
11567
+ * selectable option is checked.
11568
+ *
11569
+ * @override
11570
+ * @internal
11571
+ */
11572
+
11573
+
11574
+ focusinHandler(e) {
11575
+ if (!this.multiple) {
11576
+ return super.focusinHandler(e);
11577
+ }
11578
+
11579
+ if (!this.shouldSkipFocus && e.target === e.currentTarget) {
11580
+ this.uncheckAllOptions();
11581
+
11582
+ if (this.activeIndex === -1) {
11583
+ this.activeIndex = this.firstSelectedOptionIndex !== -1 ? this.firstSelectedOptionIndex : 0;
11584
+ }
11585
+
11586
+ this.checkActiveIndex();
11587
+ this.setSelectedOptions();
11588
+ this.focusAndScrollOptionIntoView();
11589
+ }
11590
+
11591
+ this.shouldSkipFocus = false;
11592
+ }
11593
+ /**
11594
+ * Unchecks all options when the listbox loses focus.
11595
+ *
11596
+ * @internal
11597
+ */
11598
+
11599
+
11600
+ focusoutHandler(e) {
11601
+ if (this.multiple) {
11602
+ this.uncheckAllOptions();
11603
+ }
11604
+ }
11605
+ /**
11606
+ * Handles keydown actions for listbox navigation and typeahead
11607
+ *
11608
+ * @override
11609
+ * @internal
11610
+ */
11611
+
11612
+
11613
+ keydownHandler(e) {
11614
+ if (!this.multiple) {
11615
+ return super.keydownHandler(e);
11616
+ }
11617
+
11618
+ if (this.disabled) {
11619
+ return true;
11620
+ }
11621
+
11622
+ const {
11623
+ key,
11624
+ shiftKey
11625
+ } = e;
11626
+ this.shouldSkipFocus = false;
11627
+
11628
+ switch (key) {
11629
+ // Select the first available option
11630
+ case keyHome:
11631
+ {
11632
+ this.checkFirstOption(shiftKey);
11633
+ return;
11634
+ }
11635
+ // Select the next selectable option
11636
+
11637
+ case keyArrowDown:
11638
+ {
11639
+ this.checkNextOption(shiftKey);
11640
+ return;
11641
+ }
11642
+ // Select the previous selectable option
11643
+
11644
+ case keyArrowUp:
11645
+ {
11646
+ this.checkPreviousOption(shiftKey);
11647
+ return;
11648
+ }
11649
+ // Select the last available option
11650
+
11651
+ case keyEnd:
11652
+ {
11653
+ this.checkLastOption(shiftKey);
11654
+ return;
11655
+ }
11656
+
11657
+ case keyTab:
11658
+ {
11659
+ this.focusAndScrollOptionIntoView();
11660
+ return true;
11661
+ }
11662
+
11663
+ case keyEscape:
11664
+ {
11665
+ if (this.multiple) {
11666
+ this.uncheckAllOptions();
11667
+ this.checkActiveIndex();
11668
+ }
11669
+
11670
+ return true;
11671
+ }
11672
+
11673
+ case keySpace:
11674
+ {
11675
+ e.preventDefault();
11676
+
11677
+ if (this.typeAheadExpired) {
11678
+ this.toggleSelectedForAllCheckedOptions();
11679
+ }
11680
+
11681
+ return;
11682
+ }
11683
+ // Send key to Typeahead handler
11684
+
11685
+ default:
11686
+ {
11687
+ if (key.length === 1) {
11688
+ this.handleTypeAhead(`${key}`);
11689
+ }
11690
+
11691
+ return true;
11692
+ }
11693
+ }
11694
+ }
11695
+ /**
11696
+ * Prevents `focusin` events from firing before `click` events when the
11697
+ * element is unfocused.
11698
+ *
11699
+ * @override
11700
+ * @internal
11701
+ */
11702
+
11703
+
11704
+ mousedownHandler(e) {
11705
+ if (e.offsetX >= 0 && e.offsetX <= this.scrollWidth) {
11706
+ return super.mousedownHandler(e);
11707
+ }
11708
+ }
11709
+ /**
11710
+ * Switches between single-selection and multi-selection mode.
11711
+ *
11712
+ * @override
11713
+ * @internal
11714
+ */
11715
+
11716
+
11717
+ multipleChanged(prev, next) {
11718
+ var _a;
11719
+
11720
+ super.multipleChanged(prev, next);
11721
+ (_a = this.options) === null || _a === void 0 ? void 0 : _a.forEach(o => {
11722
+ o.checked = next ? false : undefined;
11723
+ });
11724
+ this.setSelectedOptions();
11725
+
11726
+ if (next && !this.size) {
11727
+ this.size = 0;
11728
+ }
11729
+ }
11730
+ /**
11731
+ * Sets an option as selected and gives it focus.
11732
+ *
11733
+ * @override
11734
+ * @public
11735
+ */
11736
+
11737
+
11738
+ setSelectedOptions() {
11739
+ if (!this.multiple) {
11740
+ super.setSelectedOptions();
11741
+ return;
11742
+ }
11743
+
11744
+ if (this.$fastController.isConnected && this.options) {
11745
+ this.selectedOptions = this.options.filter(o => o.selected);
11746
+ this.focusAndScrollOptionIntoView();
11747
+ }
11748
+ }
11749
+ /**
11750
+ * Ensures the size is a positive integer when the property is updated.
11751
+ *
11752
+ * @param prev - the previous size value
11753
+ * @param next - the current size value
11754
+ *
11755
+ * @internal
11756
+ */
11757
+
11758
+
11759
+ sizeChanged(prev, next) {
11760
+ const size = Math.max(0, parseInt(next.toFixed(), 10));
11761
+
11762
+ if (size !== next) {
11763
+ DOM.queueUpdate(() => {
11764
+ this.size = size;
11765
+ });
11766
+ }
11767
+ }
11768
+ /**
11769
+ * Toggles the selected state of the provided options. If any provided items
11770
+ * are in an unselected state, all items are set to selected. If every
11771
+ * provided item is selected, they are all unselected.
11772
+ *
11773
+ * @internal
11774
+ */
11775
+
11776
+
11777
+ toggleSelectedForAllCheckedOptions() {
11778
+ const enabledCheckedOptions = this.checkedOptions.filter(o => !o.disabled);
11779
+ const force = !enabledCheckedOptions.every(o => o.selected);
11780
+ enabledCheckedOptions.forEach(o => o.selected = force);
11781
+ this.selectedIndex = this.options.indexOf(enabledCheckedOptions[enabledCheckedOptions.length - 1]);
11782
+ this.setSelectedOptions();
11783
+ }
11784
+ /**
11785
+ * @override
11786
+ * @internal
11787
+ */
11788
+
11789
+
11790
+ typeaheadBufferChanged(prev, next) {
11791
+ if (!this.multiple) {
11792
+ super.typeaheadBufferChanged(prev, next);
11793
+ return;
11794
+ }
11795
+
11796
+ if (this.$fastController.isConnected) {
11797
+ const typeaheadMatches = this.getTypeaheadMatches();
11798
+
11799
+ if (typeaheadMatches) {
11800
+ const activeIndex = this.options.indexOf(this.getTypeaheadMatches[0]);
11801
+
11802
+ if (activeIndex > -1) {
11803
+ this.activeIndex = activeIndex;
11804
+ this.uncheckAllOptions();
11805
+ this.checkActiveIndex();
11806
+ }
11807
+ }
11808
+
11809
+ this.typeAheadExpired = false;
11810
+ }
11811
+ }
11812
+ /**
11813
+ * Unchecks all options.
11814
+ *
11815
+ * @remarks
11816
+ * Multiple-selection mode only.
11817
+ *
11818
+ * @param preserveChecked - reset the rangeStartIndex
11819
+ *
11820
+ * @internal
11821
+ */
11822
+
11823
+
11824
+ uncheckAllOptions(preserveChecked = false) {
11825
+ this.options.forEach(o => o.checked = this.multiple ? false : undefined);
11826
+
11827
+ if (!preserveChecked) {
11828
+ this.rangeStartIndex = -1;
11829
+ }
11830
+ }
11831
+
11832
+ }
11833
+
11834
+ __decorate$1([observable], ListboxElement.prototype, "activeIndex", void 0);
11835
+
11836
+ __decorate$1([attr({
11837
+ converter: nullableNumberConverter
11838
+ })], ListboxElement.prototype, "size", void 0);
11839
+
11840
+ /**
11841
+ * The template for the {@link @microsoft/fast-foundation#(Listbox:class)} component.
11842
+ * @public
11843
+ */
11844
+
11845
+ const listboxTemplate = (context, definition) => html`<template aria-activedescendant="${x => x.ariaActiveDescendant}" aria-multiselectable="${x => x.ariaMultiSelectable}" class="listbox" role="listbox" tabindex="${x => !x.disabled ? "0" : null}" @click="${(x, c) => x.clickHandler(c.event)}" @focusin="${(x, c) => x.focusinHandler(c.event)}" @keydown="${(x, c) => x.keydownHandler(c.event)}" @mousedown="${(x, c) => x.mousedownHandler(c.event)}"><slot ${slotted({
11846
+ filter: ListboxElement.slottedOptionFilter,
11847
+ flatten: true,
11848
+ property: "slottedOptions"
11849
+ })}></slot></template>`;
11850
+
11851
+ /**
11852
+ * Positioning directions for the listbox when a select is open.
11853
+ * @public
11854
+ */
11855
+ var SelectPosition;
11856
+
11857
+ (function (SelectPosition) {
11858
+ SelectPosition["above"] = "above";
11859
+ SelectPosition["below"] = "below";
11860
+ })(SelectPosition || (SelectPosition = {}));
11861
+
11862
+ class _Combobox extends Listbox$1 {}
11863
+ /**
11864
+ * A form-associated base class for the {@link (Combobox:class)} component.
11865
+ *
11866
+ * @internal
11867
+ */
11868
+
11869
+
11870
+ class FormAssociatedCombobox extends FormAssociated(_Combobox) {
11871
+ constructor() {
11872
+ super(...arguments);
11873
+ this.proxy = document.createElement("input");
11874
+ }
11875
+
11876
+ }
11078
11877
 
11079
11878
  /**
11080
11879
  * Autocomplete values for combobox.
@@ -11128,7 +11927,7 @@ class Combobox$1 extends FormAssociatedCombobox {
11128
11927
 
11129
11928
  this.forcedPosition = false;
11130
11929
  /**
11131
- * The unique id of the internal listbox.
11930
+ * The unique id for the internal listbox element.
11132
11931
  *
11133
11932
  * @internal
11134
11933
  */
@@ -11157,15 +11956,6 @@ class Combobox$1 extends FormAssociatedCombobox {
11157
11956
  */
11158
11957
 
11159
11958
  this.position = SelectPosition.below;
11160
- /**
11161
- * The role of the element.
11162
- *
11163
- * @public
11164
- * @remarks
11165
- * HTML Attribute: role
11166
- */
11167
-
11168
- this.role = SelectRole.combobox;
11169
11959
  }
11170
11960
  /**
11171
11961
  * Reset the element to its first selectable option when its parent form is reset.
@@ -11199,12 +11989,18 @@ class Combobox$1 extends FormAssociatedCombobox {
11199
11989
  }
11200
11990
 
11201
11991
  openChanged() {
11202
- this.ariaExpanded = this.open ? "true" : "false";
11203
-
11204
11992
  if (this.open) {
11993
+ this.ariaControls = this.listboxId;
11994
+ this.ariaExpanded = "true";
11205
11995
  this.setPositioning();
11206
- this.focusAndScrollOptionIntoView();
11996
+ this.focusAndScrollOptionIntoView(); // focus is directed to the element when `open` is changed programmatically
11997
+
11998
+ DOM.queueUpdate(() => this.focus());
11999
+ return;
11207
12000
  }
12001
+
12002
+ this.ariaControls = "";
12003
+ this.ariaExpanded = "false";
11208
12004
  }
11209
12005
  /**
11210
12006
  * The list of options.
@@ -11235,6 +12031,11 @@ class Combobox$1 extends FormAssociatedCombobox {
11235
12031
  this.proxy.placeholder = this.placeholder;
11236
12032
  }
11237
12033
  }
12034
+
12035
+ positionChanged() {
12036
+ this.positionAttribute = this.position;
12037
+ this.setPositioning();
12038
+ }
11238
12039
  /**
11239
12040
  * The value property.
11240
12041
  *
@@ -11365,7 +12166,9 @@ class Combobox$1 extends FormAssociatedCombobox {
11365
12166
 
11366
12167
  if (this.firstSelectedOption) {
11367
12168
  requestAnimationFrame(() => {
11368
- this.firstSelectedOption.scrollIntoView({
12169
+ var _a;
12170
+
12171
+ (_a = this.firstSelectedOption) === null || _a === void 0 ? void 0 : _a.scrollIntoView({
11369
12172
  block: "nearest"
11370
12173
  });
11371
12174
  });
@@ -11705,12 +12508,11 @@ __decorate$1([observable], Combobox$1.prototype, "position", void 0);
11705
12508
 
11706
12509
  class DelegatesARIACombobox {}
11707
12510
 
11708
- __decorate$1([attr({
11709
- attribute: "aria-autocomplete",
11710
- mode: "fromView"
11711
- })], DelegatesARIACombobox.prototype, "ariaAutocomplete", void 0);
12511
+ __decorate$1([observable], DelegatesARIACombobox.prototype, "ariaAutoComplete", void 0);
12512
+
12513
+ __decorate$1([observable], DelegatesARIACombobox.prototype, "ariaControls", void 0);
11712
12514
 
11713
- applyMixins(DelegatesARIACombobox, ARIAGlobalStatesAndProperties);
12515
+ applyMixins(DelegatesARIACombobox, DelegatesARIAListbox);
11714
12516
  applyMixins(Combobox$1, StartEnd, DelegatesARIACombobox);
11715
12517
 
11716
12518
  /**
@@ -11718,7 +12520,7 @@ applyMixins(Combobox$1, StartEnd, DelegatesARIACombobox);
11718
12520
  * @public
11719
12521
  */
11720
12522
 
11721
- const comboboxTemplate = (context, definition) => html`<template autocomplete="${x => x.autocomplete}" class="${x => x.disabled ? "disabled" : ""} ${x => x.position}" tabindex="${x => !x.disabled ? "0" : null}" aria-disabled="${x => x.ariaDisabled}" aria-autocomplete="${x => x.autocomplete}" @click="${(x, c) => x.clickHandler(c.event)}" @focusout="${(x, c) => x.focusoutHandler(c.event)}"><div class="control" part="control">${startSlotTemplate(context, definition)}<slot name="control"><input class="selected-value" part="selected-value" placeholder="${x => x.placeholder}" role="${x => x.role}" type="text" aria-activedescendant="${x => x.open ? x.ariaActiveDescendant : null}" aria-controls="${x => x.listboxId}" aria-expanded="${x => x.ariaExpanded}" aria-haspopup="listbox" ?disabled="${x => x.disabled}" :value="${x => x.value}" @input="${(x, c) => x.inputHandler(c.event)}" @keydown="${(x, c) => x.keydownHandler(c.event)}" @keyup="${(x, c) => x.keyupHandler(c.event)}" ${ref("control")} /><div class="indicator" part="indicator" aria-hidden="true"><slot name="indicator">${definition.indicator || ""}</slot></div></slot>${endSlotTemplate(context, definition)}</div><div aria-disabled="${x => x.disabled}" class="listbox" id="${x => x.listboxId}" part="listbox" role="listbox" ?disabled="${x => x.disabled}" ?hidden="${x => !x.open}" ${ref("listbox")}><slot ${slotted({
12523
+ const comboboxTemplate = (context, definition) => html`<template aria-disabled="${x => x.ariaDisabled}" autocomplete="${x => x.autocomplete}" class="${x => x.open ? "open" : ""} ${x => x.disabled ? "disabled" : ""} ${x => x.position}" ?open="${x => x.open}" tabindex="${x => !x.disabled ? "0" : null}" @click="${(x, c) => x.clickHandler(c.event)}" @focusout="${(x, c) => x.focusoutHandler(c.event)}" @keydown="${(x, c) => x.keydownHandler(c.event)}"><div class="control" part="control">${startSlotTemplate(context, definition)}<slot name="control"><input aria-activedescendant="${x => x.open ? x.ariaActiveDescendant : null}" aria-autocomplete="${x => x.ariaAutoComplete}" aria-controls="${x => x.ariaControls}" aria-disabled="${x => x.ariaDisabled}" aria-expanded="${x => x.ariaExpanded}" aria-haspopup="listbox" class="selected-value" part="selected-value" placeholder="${x => x.placeholder}" role="combobox" type="text" ?disabled="${x => x.disabled}" :value="${x => x.value}" @input="${(x, c) => x.inputHandler(c.event)}" @keyup="${(x, c) => x.keyupHandler(c.event)}" ${ref("control")} /><div class="indicator" part="indicator" aria-hidden="true"><slot name="indicator">${definition.indicator || ""}</slot></div></slot>${endSlotTemplate(context, definition)}</div><div class="listbox" id="${x => x.listboxId}" part="listbox" role="listbox" ?disabled="${x => x.disabled}" ?hidden="${x => !x.open}" ${ref("listbox")}><slot ${slotted({
11722
12524
  filter: Listbox$1.slottedOptionFilter,
11723
12525
  flatten: true,
11724
12526
  property: "slottedOptions"
@@ -11982,6 +12784,7 @@ class PropertyStyleSheetBehavior {
11982
12784
  /**
11983
12785
  * Change event for the provided element.
11984
12786
  * @param source - the element for which to attach or detach styles.
12787
+ * @param key - the key to lookup to know if the element already has the styles
11985
12788
  * @internal
11986
12789
  */
11987
12790
 
@@ -13822,7 +14625,7 @@ __decorate$1([attr({
13822
14625
  * @public
13823
14626
  */
13824
14627
 
13825
- const dividerTemplate = (context, definition) => html`<template role="${x => x.role}"></template>`;
14628
+ const dividerTemplate = (context, definition) => html`<template role="${x => x.role}" aria-orientation="${x => x.orientation}"></template>`;
13826
14629
 
13827
14630
  /**
13828
14631
  * Divider roles
@@ -13862,12 +14665,23 @@ class Divider extends FoundationElement {
13862
14665
  */
13863
14666
 
13864
14667
  this.role = DividerRole.separator;
14668
+ /**
14669
+ * The orientation of the divider.
14670
+ *
14671
+ * @public
14672
+ * @remarks
14673
+ * HTML Attribute: orientation
14674
+ */
14675
+
14676
+ this.orientation = Orientation.horizontal;
13865
14677
  }
13866
14678
 
13867
14679
  }
13868
14680
 
13869
14681
  __decorate$1([attr], Divider.prototype, "role", void 0);
13870
14682
 
14683
+ __decorate$1([attr], Divider.prototype, "orientation", void 0);
14684
+
13871
14685
  /**
13872
14686
  * The direction options for flipper.
13873
14687
  * @public
@@ -13956,64 +14770,7 @@ __decorate$1([attr], Flipper.prototype, "direction", void 0);
13956
14770
  * @public
13957
14771
  */
13958
14772
 
13959
- const listboxOptionTemplate = (context, definition) => html`<template aria-selected="${x => x.selected}" class="${x => x.selected ? "selected" : ""} ${x => x.disabled ? "disabled" : ""}" role="option">${startSlotTemplate(context, definition)}<span class="content" part="content"><slot></slot></span>${endSlotTemplate(context, definition)}</template>`;
13960
-
13961
- /**
13962
- * A Listbox Custom HTML Element.
13963
- * Implements the {@link https://w3c.github.io/aria/#listbox | ARIA listbox }.
13964
- *
13965
- * @public
13966
- */
13967
-
13968
- class ListboxElement extends Listbox$1 {
13969
- /**
13970
- * Prevents `focusin` events from firing before `click` events when the
13971
- * element is unfocused.
13972
- *
13973
- * @override
13974
- * @internal
13975
- */
13976
- mousedownHandler(e) {
13977
- if (e.offsetX >= 0 && e.offsetX <= this.scrollWidth) {
13978
- return super.mousedownHandler(e);
13979
- }
13980
- }
13981
- /**
13982
- * Ensures the size is a positive integer when the property is updated.
13983
- *
13984
- * @param prev - the previous size value
13985
- * @param next - the current size value
13986
- *
13987
- * @internal
13988
- */
13989
-
13990
-
13991
- sizeChanged(prev, next) {
13992
- const size = Math.max(0, parseInt(next.toFixed(), 10));
13993
-
13994
- if (size !== next) {
13995
- DOM.queueUpdate(() => {
13996
- this.size = size;
13997
- });
13998
- }
13999
- }
14000
-
14001
- }
14002
-
14003
- __decorate$1([attr({
14004
- converter: nullableNumberConverter
14005
- })], ListboxElement.prototype, "size", void 0);
14006
-
14007
- /**
14008
- * The template for the {@link @microsoft/fast-foundation#(Listbox:class)} component.
14009
- * @public
14010
- */
14011
-
14012
- const listboxTemplate = (context, definition) => html`<template aria-activedescendant="${x => x.ariaActiveDescendant}" class="listbox" role="${x => x.role}" tabindex="${x => !x.disabled ? "0" : null}" @click="${(x, c) => x.clickHandler(c.event)}" @focusin="${(x, c) => x.focusinHandler(c.event)}" @keydown="${(x, c) => x.keydownHandler(c.event)}" @mousedown="${(x, c) => x.mousedownHandler(c.event)}"><slot ${slotted({
14013
- filter: ListboxElement.slottedOptionFilter,
14014
- flatten: true,
14015
- property: "slottedOptions"
14016
- })}></slot></template>`;
14773
+ const listboxOptionTemplate = (context, definition) => html`<template aria-checked="${x => x.ariaChecked}" aria-disabled="${x => x.ariaDisabled}" aria-posinset="${x => x.ariaPosInSet}" aria-selected="${x => x.ariaSelected}" aria-setsize="${x => x.ariaSetSize}" class="${x => [x.checked && "checked", x.selected && "selected", x.disabled && "disabled"].filter(Boolean).join(" ")}" role="option">${startSlotTemplate(context, definition)}<span class="content" part="content"><slot></slot></span>${endSlotTemplate(context, definition)}</template>`;
14017
14774
 
14018
14775
  /**
14019
14776
  * Menu items roles.
@@ -14078,7 +14835,7 @@ class MenuItem extends FoundationElement {
14078
14835
  * @internal
14079
14836
  */
14080
14837
 
14081
- this.currentDirection = Direction$1.ltr;
14838
+ this.currentDirection = Direction.ltr;
14082
14839
  this.focusSubmenuOnLoad = false;
14083
14840
  /**
14084
14841
  * @internal
@@ -14369,7 +15126,7 @@ class Menu$1 extends FoundationElement {
14369
15126
 
14370
15127
 
14371
15128
  this.handleFocusOut = e => {
14372
- if (!this.contains(e.relatedTarget)) {
15129
+ if (!this.contains(e.relatedTarget) && this.menuItems !== undefined) {
14373
15130
  this.collapseExpandedItem(); // find our first focusable element
14374
15131
 
14375
15132
  const focusIndex = this.menuItems.findIndex(this.isFocusableElement); // set the current focus index's tabindex to -1
@@ -14385,7 +15142,7 @@ class Menu$1 extends FoundationElement {
14385
15142
  this.handleItemFocus = e => {
14386
15143
  const targetItem = e.target;
14387
15144
 
14388
- if (targetItem !== this.menuItems[this.focusIndex]) {
15145
+ if (this.menuItems !== undefined && targetItem !== this.menuItems[this.focusIndex]) {
14389
15146
  this.menuItems[this.focusIndex].setAttribute("tabindex", "-1");
14390
15147
  this.focusIndex = this.menuItems.indexOf(targetItem);
14391
15148
  targetItem.setAttribute("tabindex", "0");
@@ -14393,7 +15150,7 @@ class Menu$1 extends FoundationElement {
14393
15150
  };
14394
15151
 
14395
15152
  this.handleExpandedChanged = e => {
14396
- if (e.defaultPrevented || e.target === null || this.menuItems.indexOf(e.target) < 0) {
15153
+ if (e.defaultPrevented || e.target === null || this.menuItems === undefined || this.menuItems.indexOf(e.target) < 0) {
14397
15154
  return;
14398
15155
  }
14399
15156
 
@@ -14417,7 +15174,19 @@ class Menu$1 extends FoundationElement {
14417
15174
  }
14418
15175
  };
14419
15176
 
15177
+ this.removeItemListeners = () => {
15178
+ if (this.menuItems !== undefined) {
15179
+ this.menuItems.forEach(item => {
15180
+ item.removeEventListener("expanded-change", this.handleExpandedChanged);
15181
+ item.removeEventListener("focus", this.handleItemFocus);
15182
+ });
15183
+ }
15184
+ };
15185
+
14420
15186
  this.setItems = () => {
15187
+ const newItems = this.domChildren();
15188
+ this.removeItemListeners();
15189
+ this.menuItems = newItems;
14421
15190
  const menuItems = this.menuItems.filter(this.isMenuItemElement); // if our focus index is not -1 we have items
14422
15191
 
14423
15192
  if (menuItems.length) {
@@ -14454,19 +15223,16 @@ class Menu$1 extends FoundationElement {
14454
15223
  }
14455
15224
  });
14456
15225
  };
14457
-
14458
- this.resetItems = oldValue => {
14459
- oldValue.forEach(item => {
14460
- item.removeEventListener("expanded-change", this.handleExpandedChanged);
14461
- item.removeEventListener("focus", this.handleItemFocus);
14462
- });
14463
- };
14464
15226
  /**
14465
15227
  * handle change from child element
14466
15228
  */
14467
15229
 
14468
15230
 
14469
15231
  this.changeHandler = e => {
15232
+ if (this.menuItems === undefined) {
15233
+ return;
15234
+ }
15235
+
14470
15236
  const changedMenuItem = e.target;
14471
15237
  const changeItemIndex = this.menuItems.indexOf(changedMenuItem);
14472
15238
 
@@ -14523,9 +15289,10 @@ class Menu$1 extends FoundationElement {
14523
15289
  }
14524
15290
 
14525
15291
  itemsChanged(oldValue, newValue) {
14526
- if (this.$fastController.isConnected) {
14527
- this.menuItems = this.domChildren();
14528
- this.resetItems(oldValue);
15292
+ // only update children after the component is connected and
15293
+ // the setItems has run on connectedCallback
15294
+ // (menuItems is undefined until then)
15295
+ if (this.$fastController.isConnected && this.menuItems !== undefined) {
14529
15296
  this.setItems();
14530
15297
  }
14531
15298
  }
@@ -14536,7 +15303,11 @@ class Menu$1 extends FoundationElement {
14536
15303
 
14537
15304
  connectedCallback() {
14538
15305
  super.connectedCallback();
14539
- this.menuItems = this.domChildren();
15306
+ DOM.queueUpdate(() => {
15307
+ // wait until children have had a chance to
15308
+ // connect before setting/checking their props/attributes
15309
+ this.setItems();
15310
+ });
14540
15311
  this.addEventListener("change", this.changeHandler);
14541
15312
  }
14542
15313
  /**
@@ -14546,7 +15317,8 @@ class Menu$1 extends FoundationElement {
14546
15317
 
14547
15318
  disconnectedCallback() {
14548
15319
  super.disconnectedCallback();
14549
- this.menuItems = [];
15320
+ this.removeItemListeners();
15321
+ this.menuItems = undefined;
14550
15322
  this.removeEventListener("change", this.changeHandler);
14551
15323
  }
14552
15324
  /**
@@ -14578,7 +15350,7 @@ class Menu$1 extends FoundationElement {
14578
15350
 
14579
15351
 
14580
15352
  handleMenuKeyDown(e) {
14581
- if (e.defaultPrevented) {
15353
+ if (e.defaultPrevented || this.menuItems === undefined) {
14582
15354
  return;
14583
15355
  }
14584
15356
 
@@ -14981,6 +15753,20 @@ class NumberField$1 extends FormAssociatedNumberField {
14981
15753
 
14982
15754
  this.value = this.getValidValue(this.value);
14983
15755
  }
15756
+ /**
15757
+ * The value property, typed as a number.
15758
+ *
15759
+ * @public
15760
+ */
15761
+
15762
+
15763
+ get valueAsNumber() {
15764
+ return parseFloat(super.value);
15765
+ }
15766
+
15767
+ set valueAsNumber(next) {
15768
+ this.value = next.toString();
15769
+ }
14984
15770
  /**
14985
15771
  * Validates that the value is a number between the min and max
14986
15772
  * @param previous - previous stored value
@@ -15013,7 +15799,6 @@ class NumberField$1 extends FormAssociatedNumberField {
15013
15799
  /**
15014
15800
  * Sets the internal value to a valid number between the min and max properties
15015
15801
  * @param value - user input
15016
- * @param updateControl - should the text field update to the valid value
15017
15802
  *
15018
15803
  * @internal
15019
15804
  */
@@ -15517,7 +16302,7 @@ class RadioGroup extends FoundationElement {
15517
16302
  case keyArrowRight:
15518
16303
  case keyArrowDown:
15519
16304
  {
15520
- if (this.direction === Direction$1.ltr) {
16305
+ if (this.direction === Direction.ltr) {
15521
16306
  this.moveRight(e);
15522
16307
  } else {
15523
16308
  this.moveLeft(e);
@@ -15529,7 +16314,7 @@ class RadioGroup extends FoundationElement {
15529
16314
  case keyArrowLeft:
15530
16315
  case keyArrowUp:
15531
16316
  {
15532
- if (this.direction === Direction$1.ltr) {
16317
+ if (this.direction === Direction.ltr) {
15533
16318
  this.moveLeft(e);
15534
16319
  } else {
15535
16320
  this.moveRight(e);
@@ -16213,7 +16998,7 @@ __decorate$1([attr], HorizontalScroll$1.prototype, "duration", void 0);
16213
16998
  __decorate$1([attr], HorizontalScroll$1.prototype, "easing", void 0);
16214
16999
 
16215
17000
  __decorate$1([attr({
16216
- attribute: "aria-hidden",
17001
+ attribute: "flippers-hidden-from-at",
16217
17002
  converter: booleanConverter
16218
17003
  })], HorizontalScroll$1.prototype, "flippersHiddenFromAT", void 0);
16219
17004
 
@@ -16456,21 +17241,19 @@ class Select$1 extends FormAssociatedSelect {
16456
17241
 
16457
17242
  this.forcedPosition = false;
16458
17243
  /**
16459
- * The role of the element.
17244
+ * Holds the current state for the calculated position of the listbox.
16460
17245
  *
16461
17246
  * @public
16462
- * @remarks
16463
- * HTML Attribute: role
16464
17247
  */
16465
17248
 
16466
- this.role = SelectRole.combobox;
17249
+ this.position = SelectPosition.below;
16467
17250
  /**
16468
- * Holds the current state for the calculated position of the listbox.
17251
+ * The unique id for the internal listbox element.
16469
17252
  *
16470
- * @public
17253
+ * @internal
16471
17254
  */
16472
17255
 
16473
- this.position = SelectPosition.below;
17256
+ this.listboxId = uniqueId("listbox-");
16474
17257
  /**
16475
17258
  * The max height for the listbox when opened.
16476
17259
  *
@@ -16488,13 +17271,19 @@ class Select$1 extends FormAssociatedSelect {
16488
17271
  }
16489
17272
 
16490
17273
  openChanged() {
16491
- this.ariaExpanded = this.open ? "true" : "false";
16492
-
16493
17274
  if (this.open) {
17275
+ this.ariaControls = this.listboxId;
17276
+ this.ariaExpanded = "true";
16494
17277
  this.setPositioning();
16495
17278
  this.focusAndScrollOptionIntoView();
16496
- this.indexWhenOpened = this.selectedIndex;
17279
+ this.indexWhenOpened = this.selectedIndex; // focus is directed to the element when `open` is changed programmatically
17280
+
17281
+ DOM.queueUpdate(() => this.focus());
17282
+ return;
16497
17283
  }
17284
+
17285
+ this.ariaControls = "";
17286
+ this.ariaExpanded = "false";
16498
17287
  }
16499
17288
  /**
16500
17289
  * The value property.
@@ -16509,9 +17298,11 @@ class Select$1 extends FormAssociatedSelect {
16509
17298
  }
16510
17299
 
16511
17300
  set value(next) {
17301
+ var _a;
17302
+
16512
17303
  const prev = `${this._value}`;
16513
17304
 
16514
- if (this.$fastController.isConnected && this.options) {
17305
+ if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.length) {
16515
17306
  const selectedIndex = this.options.findIndex(el => el.value === next);
16516
17307
  const prevSelectedOption = this.options[this.selectedIndex];
16517
17308
  const nextSelectedOption = this.options[selectedIndex];
@@ -16563,6 +17354,11 @@ class Select$1 extends FormAssociatedSelect {
16563
17354
  super.selectedIndexChanged(prev, next);
16564
17355
  this.updateValue();
16565
17356
  }
17357
+
17358
+ positionChanged() {
17359
+ this.positionAttribute = this.position;
17360
+ this.setPositioning();
17361
+ }
16566
17362
  /**
16567
17363
  * Calculate and apply listbox positioning based on available viewport space.
16568
17364
  *
@@ -16610,8 +17406,10 @@ class Select$1 extends FormAssociatedSelect {
16610
17406
 
16611
17407
 
16612
17408
  formResetCallback() {
16613
- this.setProxyOptions();
16614
- this.setDefaultSelectedOption();
17409
+ this.setProxyOptions(); // Call the base class's implementation setDefaultSelectedOption instead of the select's
17410
+ // override, in order to reset the selectedIndex without using the value property.
17411
+
17412
+ super.setDefaultSelectedOption();
16615
17413
  this.value = this.firstSelectedOption.value;
16616
17414
  }
16617
17415
  /**
@@ -16690,6 +17488,20 @@ class Select$1 extends FormAssociatedSelect {
16690
17488
  this.setProxyOptions();
16691
17489
  this.updateValue();
16692
17490
  }
17491
+
17492
+ setDefaultSelectedOption() {
17493
+ var _a;
17494
+
17495
+ const options = (_a = this.options) !== null && _a !== void 0 ? _a : Array.from(this.children).filter(Listbox$1.slottedOptionFilter);
17496
+ const selectedIndex = options === null || options === void 0 ? void 0 : options.findIndex(el => el.hasAttribute("selected") || el.selected || el.value === this.value);
17497
+
17498
+ if (selectedIndex !== -1) {
17499
+ this.selectedIndex = selectedIndex;
17500
+ return;
17501
+ }
17502
+
17503
+ this.selectedIndex = 0;
17504
+ }
16693
17505
  /**
16694
17506
  * Reset and fill the proxy to match the component's options.
16695
17507
  *
@@ -16798,14 +17610,9 @@ __decorate$1([observable], Select$1.prototype, "displayValue", void 0);
16798
17610
 
16799
17611
  class DelegatesARIASelect {}
16800
17612
 
16801
- __decorate$1([observable], DelegatesARIASelect.prototype, "ariaExpanded", void 0);
16802
-
16803
- __decorate$1([attr({
16804
- attribute: "aria-pressed",
16805
- mode: "fromView"
16806
- })], DelegatesARIASelect.prototype, "ariaPressed", void 0);
17613
+ __decorate$1([observable], DelegatesARIASelect.prototype, "ariaControls", void 0);
16807
17614
 
16808
- applyMixins(DelegatesARIASelect, ARIAGlobalStatesAndProperties);
17615
+ applyMixins(DelegatesARIASelect, DelegatesARIAListbox);
16809
17616
  applyMixins(Select$1, StartEnd, DelegatesARIASelect);
16810
17617
 
16811
17618
  /**
@@ -16813,7 +17620,7 @@ applyMixins(Select$1, StartEnd, DelegatesARIASelect);
16813
17620
  * @public
16814
17621
  */
16815
17622
 
16816
- const selectTemplate = (context, definition) => html`<template class="${x => x.open ? "open" : ""} ${x => x.disabled ? "disabled" : ""} ${x => x.position}" role="${x => x.role}" tabindex="${x => !x.disabled ? "0" : null}" aria-disabled="${x => x.ariaDisabled}" aria-expanded="${x => x.ariaExpanded}" @click="${(x, c) => x.clickHandler(c.event)}" @focusout="${(x, c) => x.focusoutHandler(c.event)}" @keydown="${(x, c) => x.keydownHandler(c.event)}"><div aria-activedescendant="${x => x.open ? x.ariaActiveDescendant : null}" aria-controls="listbox" aria-expanded="${x => x.ariaExpanded}" aria-haspopup="listbox" class="control" part="control" role="button" ?disabled="${x => x.disabled}">${startSlotTemplate(context, definition)}<slot name="button-container"><div class="selected-value" part="selected-value"><slot name="selected-value">${x => x.displayValue}</slot></div><div class="indicator" part="indicator"><slot name="indicator">${definition.indicator || ""}</slot></div></slot>${endSlotTemplate(context, definition)}</div><div aria-disabled="${x => x.disabled}" class="listbox" id="listbox" part="listbox" role="listbox" ?disabled="${x => x.disabled}" ?hidden="${x => !x.open}" ${ref("listbox")}><slot ${slotted({
17623
+ const selectTemplate = (context, definition) => html`<template class="${x => x.open ? "open" : ""} ${x => x.disabled ? "disabled" : ""} ${x => x.position}" aria-activedescendant="${x => x.ariaActiveDescendant}" aria-controls="${x => x.ariaControls}" aria-disabled="${x => x.ariaDisabled}" aria-expanded="${x => x.ariaExpanded}" aria-haspopup="listbox" ?open="${x => x.open}" role="combobox" tabindex="${x => !x.disabled ? "0" : null}" @click="${(x, c) => x.clickHandler(c.event)}" @focusout="${(x, c) => x.focusoutHandler(c.event)}" @keydown="${(x, c) => x.keydownHandler(c.event)}"><div class="control" part="control" ?disabled="${x => x.disabled}">${startSlotTemplate(context, definition)}<slot name="button-container"><div class="selected-value" part="selected-value"><slot name="selected-value">${x => x.displayValue}</slot></div><div aria-hidden="true" class="indicator" part="indicator"><slot name="indicator">${definition.indicator || ""}</slot></div></slot>${endSlotTemplate(context, definition)}</div><div class="listbox" id="${x => x.listboxId}" part="listbox" role="listbox" ?disabled="${x => x.disabled}" ?hidden="${x => !x.open}" ${ref("listbox")}><slot ${slotted({
16817
17624
  filter: Listbox$1.slottedOptionFilter,
16818
17625
  flatten: true,
16819
17626
  property: "slottedOptions"
@@ -16872,7 +17679,7 @@ const sliderLabelTemplate = (context, definition) => html`<template aria-disable
16872
17679
  function convertPixelToPercent(pixelPos, minPosition, maxPosition, direction) {
16873
17680
  let pct = limit(0, 1, (pixelPos - minPosition) / (maxPosition - minPosition));
16874
17681
 
16875
- if (direction === Direction$1.rtl) {
17682
+ if (direction === Direction.rtl) {
16876
17683
  pct = 1 - pct;
16877
17684
  }
16878
17685
 
@@ -16882,7 +17689,7 @@ function convertPixelToPercent(pixelPos, minPosition, maxPosition, direction) {
16882
17689
  const defaultConfig = {
16883
17690
  min: 0,
16884
17691
  max: 0,
16885
- direction: Direction$1.ltr,
17692
+ direction: Direction.ltr,
16886
17693
  orientation: Orientation.horizontal,
16887
17694
  disabled: false
16888
17695
  };
@@ -16908,11 +17715,11 @@ class SliderLabel extends FoundationElement {
16908
17715
  * @internal
16909
17716
  */
16910
17717
 
16911
- this.sliderDirection = Direction$1.ltr;
17718
+ this.sliderDirection = Direction.ltr;
16912
17719
 
16913
17720
  this.getSliderConfiguration = () => {
16914
17721
  if (!this.isSliderConfig(this.parentNode)) {
16915
- this.sliderDirection = defaultConfig.direction || Direction$1.ltr;
17722
+ this.sliderDirection = defaultConfig.direction || Direction.ltr;
16916
17723
  this.sliderOrientation = defaultConfig.orientation || Orientation.horizontal;
16917
17724
  this.sliderMaxPosition = defaultConfig.max;
16918
17725
  this.sliderMinPosition = defaultConfig.min;
@@ -16930,7 +17737,7 @@ class SliderLabel extends FoundationElement {
16930
17737
  this.disabled = disabled;
16931
17738
  }
16932
17739
 
16933
- this.sliderDirection = direction || Direction$1.ltr;
17740
+ this.sliderDirection = direction || Direction.ltr;
16934
17741
  this.sliderOrientation = orientation || Orientation.horizontal;
16935
17742
  this.sliderMaxPosition = max;
16936
17743
  this.sliderMinPosition = min;
@@ -16938,7 +17745,7 @@ class SliderLabel extends FoundationElement {
16938
17745
  };
16939
17746
 
16940
17747
  this.positionAsStyle = () => {
16941
- const direction = this.sliderDirection ? this.sliderDirection : Direction$1.ltr;
17748
+ const direction = this.sliderDirection ? this.sliderDirection : Direction.ltr;
16942
17749
  const pct = convertPixelToPercent(Number(this.position), Number(this.sliderMinPosition), Number(this.sliderMaxPosition));
16943
17750
  let rightNum = Math.round((1 - pct) * 100);
16944
17751
  let leftNum = Math.round(pct * 100);
@@ -16949,7 +17756,7 @@ class SliderLabel extends FoundationElement {
16949
17756
  }
16950
17757
 
16951
17758
  if (this.sliderOrientation === Orientation.horizontal) {
16952
- return direction === Direction$1.rtl ? `right: ${leftNum}%; left: ${rightNum}%;` : `left: ${leftNum}%; right: ${rightNum}%;`;
17759
+ return direction === Direction.rtl ? `right: ${leftNum}%; left: ${rightNum}%;` : `left: ${leftNum}%; right: ${rightNum}%;`;
16953
17760
  } else {
16954
17761
  return `top: ${leftNum}%; bottom: ${rightNum}%;`;
16955
17762
  }
@@ -17096,7 +17903,7 @@ class Slider extends FormAssociatedSlider {
17096
17903
  * @internal
17097
17904
  */
17098
17905
 
17099
- this.direction = Direction$1.ltr;
17906
+ this.direction = Direction.ltr;
17100
17907
  /**
17101
17908
  * @internal
17102
17909
  */
@@ -17348,6 +18155,20 @@ class Slider extends FormAssociatedSlider {
17348
18155
  this.proxy.readOnly = this.readOnly;
17349
18156
  }
17350
18157
  }
18158
+ /**
18159
+ * The value property, typed as a number.
18160
+ *
18161
+ * @public
18162
+ */
18163
+
18164
+
18165
+ get valueAsNumber() {
18166
+ return parseFloat(super.value);
18167
+ }
18168
+
18169
+ set valueAsNumber(next) {
18170
+ this.value = next.toString();
18171
+ }
17351
18172
  /**
17352
18173
  * @internal
17353
18174
  */
@@ -17424,7 +18245,7 @@ class Slider extends FormAssociatedSlider {
17424
18245
 
17425
18246
 
17426
18247
  increment() {
17427
- const newVal = this.direction !== Direction$1.rtl && this.orientation !== Orientation.vertical ? Number(this.value) + Number(this.step) : Number(this.value) - Number(this.step);
18248
+ const newVal = this.direction !== Direction.rtl && this.orientation !== Orientation.vertical ? Number(this.value) + Number(this.step) : Number(this.value) - Number(this.step);
17428
18249
  const incrementedVal = this.convertToConstrainedValue(newVal);
17429
18250
  const incrementedValString = incrementedVal < Number(this.max) ? `${incrementedVal}` : `${this.max}`;
17430
18251
  this.value = incrementedValString;
@@ -17437,7 +18258,7 @@ class Slider extends FormAssociatedSlider {
17437
18258
 
17438
18259
 
17439
18260
  decrement() {
17440
- const newVal = this.direction !== Direction$1.rtl && this.orientation !== Orientation.vertical ? Number(this.value) - Number(this.step) : Number(this.value) + Number(this.step);
18261
+ const newVal = this.direction !== Direction.rtl && this.orientation !== Orientation.vertical ? Number(this.value) - Number(this.step) : Number(this.value) + Number(this.step);
17441
18262
  const decrementedVal = this.convertToConstrainedValue(newVal);
17442
18263
  const decrementedValString = decrementedVal > Number(this.min) ? `${decrementedVal}` : `${this.min}`;
17443
18264
  this.value = decrementedValString;
@@ -17452,7 +18273,7 @@ class Slider extends FormAssociatedSlider {
17452
18273
 
17453
18274
  setThumbPositionForOrientation(direction) {
17454
18275
  const newPct = convertPixelToPercent(Number(this.value), Number(this.min), Number(this.max), direction);
17455
- const percentage = Math.round((1 - newPct) * 100);
18276
+ const percentage = (1 - newPct) * 100;
17456
18277
 
17457
18278
  if (this.orientation === Orientation.horizontal) {
17458
18279
  this.position = this.isDragging ? `right: ${percentage}%; transition: none;` : `right: ${percentage}%; transition: all 0.2s ease;`;
@@ -18251,14 +19072,14 @@ const ToolbarArrowKeyMap = Object.freeze({
18251
19072
  },
18252
19073
  [ArrowKeys.ArrowLeft]: {
18253
19074
  [Orientation.horizontal]: {
18254
- [Direction$1.ltr]: -1,
18255
- [Direction$1.rtl]: 1
19075
+ [Direction.ltr]: -1,
19076
+ [Direction.rtl]: 1
18256
19077
  }
18257
19078
  },
18258
19079
  [ArrowKeys.ArrowRight]: {
18259
19080
  [Orientation.horizontal]: {
18260
- [Direction$1.ltr]: 1,
18261
- [Direction$1.rtl]: -1
19081
+ [Direction.ltr]: 1,
19082
+ [Direction.rtl]: -1
18262
19083
  }
18263
19084
  }
18264
19085
  });
@@ -18285,7 +19106,7 @@ class Toolbar$1 extends FoundationElement {
18285
19106
  * @internal
18286
19107
  */
18287
19108
 
18288
- this.direction = Direction$1.ltr;
19109
+ this.direction = Direction.ltr;
18289
19110
  /**
18290
19111
  * The orientation of the toolbar.
18291
19112
  *
@@ -18625,7 +19446,7 @@ class Tooltip$1 extends FoundationElement {
18625
19446
  * @internal
18626
19447
  */
18627
19448
 
18628
- this.horizontalInset = "true";
19449
+ this.horizontalInset = "false";
18629
19450
  /**
18630
19451
  * @internal
18631
19452
  */
@@ -18635,7 +19456,7 @@ class Tooltip$1 extends FoundationElement {
18635
19456
  * @internal
18636
19457
  */
18637
19458
 
18638
- this.horizontalScaling = "anchor";
19459
+ this.horizontalScaling = "content";
18639
19460
  /**
18640
19461
  * @internal
18641
19462
  */
@@ -18663,7 +19484,7 @@ class Tooltip$1 extends FoundationElement {
18663
19484
  * @internal
18664
19485
  */
18665
19486
 
18666
- this.currentDirection = Direction$1.ltr;
19487
+ this.currentDirection = Direction.ltr;
18667
19488
  /**
18668
19489
  * The timer that tracks delay time before the tooltip is shown on hover
18669
19490
  */
@@ -18685,10 +19506,12 @@ class Tooltip$1 extends FoundationElement {
18685
19506
  this.classList.toggle("bottom", this.region.verticalPosition === "end");
18686
19507
  this.classList.toggle("inset-top", this.region.verticalPosition === "insetStart");
18687
19508
  this.classList.toggle("inset-bottom", this.region.verticalPosition === "insetEnd");
19509
+ this.classList.toggle("center-vertical", this.region.verticalPosition === "center");
18688
19510
  this.classList.toggle("left", this.region.horizontalPosition === "start");
18689
19511
  this.classList.toggle("right", this.region.horizontalPosition === "end");
18690
19512
  this.classList.toggle("inset-left", this.region.horizontalPosition === "insetStart");
18691
19513
  this.classList.toggle("inset-right", this.region.horizontalPosition === "insetEnd");
19514
+ this.classList.toggle("center-horizontal", this.region.horizontalPosition === "center");
18692
19515
  };
18693
19516
  /**
18694
19517
  * mouse enters anchor
@@ -18867,7 +19690,7 @@ class Tooltip$1 extends FoundationElement {
18867
19690
 
18868
19691
  anchorChanged() {
18869
19692
  if (this.$fastController.isConnected) {
18870
- this.updateLayout();
19693
+ this.anchorElement = this.getAnchor();
18871
19694
  }
18872
19695
  }
18873
19696
 
@@ -18929,7 +19752,6 @@ class Tooltip$1 extends FoundationElement {
18929
19752
  connectedCallback() {
18930
19753
  super.connectedCallback();
18931
19754
  this.anchorElement = this.getAnchor();
18932
- this.updateLayout();
18933
19755
  this.updateTooltipVisibility();
18934
19756
  }
18935
19757
 
@@ -18948,38 +19770,26 @@ class Tooltip$1 extends FoundationElement {
18948
19770
  case TooltipPosition.top:
18949
19771
  case TooltipPosition.bottom:
18950
19772
  this.verticalPositioningMode = "locktodefault";
18951
- this.horizontalPositioningMode = "dynamic";
19773
+ this.horizontalPositioningMode = "locktodefault";
18952
19774
  this.verticalDefaultPosition = this.position;
18953
- this.horizontalDefaultPosition = undefined;
18954
- this.horizontalInset = "true";
18955
- this.verticalInset = "false";
18956
- this.horizontalScaling = "anchor";
18957
- this.verticalScaling = "content";
19775
+ this.horizontalDefaultPosition = "center";
18958
19776
  break;
18959
19777
 
18960
19778
  case TooltipPosition.right:
18961
19779
  case TooltipPosition.left:
18962
19780
  case TooltipPosition.start:
18963
19781
  case TooltipPosition.end:
18964
- this.verticalPositioningMode = "dynamic";
19782
+ this.verticalPositioningMode = "locktodefault";
18965
19783
  this.horizontalPositioningMode = "locktodefault";
18966
- this.verticalDefaultPosition = undefined;
19784
+ this.verticalDefaultPosition = "center";
18967
19785
  this.horizontalDefaultPosition = this.position;
18968
- this.horizontalInset = "false";
18969
- this.verticalInset = "true";
18970
- this.horizontalScaling = "content";
18971
- this.verticalScaling = "anchor";
18972
19786
  break;
18973
19787
 
18974
19788
  default:
18975
19789
  this.verticalPositioningMode = "dynamic";
18976
19790
  this.horizontalPositioningMode = "dynamic";
18977
- this.verticalDefaultPosition = undefined;
18978
- this.horizontalDefaultPosition = undefined;
18979
- this.horizontalInset = "true";
18980
- this.verticalInset = "false";
18981
- this.horizontalScaling = "anchor";
18982
- this.verticalScaling = "content";
19791
+ this.verticalDefaultPosition = void 0;
19792
+ this.horizontalDefaultPosition = "center";
18983
19793
  break;
18984
19794
  }
18985
19795
  }
@@ -19037,7 +19847,7 @@ __decorate$1([observable], Tooltip$1.prototype, "currentDirection", void 0);
19037
19847
  * @public
19038
19848
  */
19039
19849
 
19040
- const treeItemTemplate = (context, definition) => html`<template role="treeitem" slot="${x => x.isNestedItem() ? "item" : void 0}" tabindex="${x => !x.focusable ? -1 : 0}" class="${x => x.expanded ? "expanded" : ""} ${x => x.selected ? "selected" : ""} ${x => x.nested ? "nested" : ""} ${x => x.disabled ? "disabled" : ""}" aria-expanded="${x => x.childItems && x.childItemLength() > 0 ? x.expanded : void 0}" aria-selected="${x => x.selected}" aria-disabled="${x => x.disabled}" @click="${(x, c) => x.handleClick(c.event)}" ${children({
19850
+ const treeItemTemplate = (context, definition) => html`<template role="treeitem" slot="${x => x.isNestedItem() ? "item" : void 0}" tabindex="-1" class="${x => x.expanded ? "expanded" : ""} ${x => x.selected ? "selected" : ""} ${x => x.nested ? "nested" : ""} ${x => x.disabled ? "disabled" : ""}" aria-expanded="${x => x.childItems && x.childItemLength() > 0 ? x.expanded : void 0}" aria-selected="${x => x.selected}" aria-disabled="${x => x.disabled}" @focusin="${(x, c) => x.handleFocus(c.event)}" @focusout="${(x, c) => x.handleBlur(c.event)}" ${children({
19041
19851
  property: "childItems",
19042
19852
  filter: elements()
19043
19853
  })}><div class="positioning-region" part="positioning-region"><div class="content-region" part="content-region">${when(x => x.childItems && x.childItemLength() > 0, html`<div aria-hidden="true" class="expand-collapse-button" part="expand-collapse-button" @click="${(x, c) => x.handleExpandCollapseButtonClick(c.event)}" ${ref("expandCollapseButton")}><slot name="expand-collapse-glyph">${definition.expandCollapseGlyph || ""}</slot></div>`)} ${startSlotTemplate(context, definition)}<slot></slot>${endSlotTemplate(context, definition)}</div></div>${when(x => x.childItems && x.childItemLength() > 0 && (x.expanded || x.renderCollapsedChildren), html`<div role="group" class="items" part="items"><slot name="item" ${slotted("items")}></slot></div>`)}</template>`;
@@ -19069,32 +19879,66 @@ class TreeItem extends FoundationElement {
19069
19879
  */
19070
19880
 
19071
19881
  this.expanded = false;
19882
+ /**
19883
+ * Whether the item is focusable
19884
+ *
19885
+ * @internal
19886
+ */
19887
+
19072
19888
  this.focusable = false;
19889
+ /**
19890
+ * Whether the tree is nested
19891
+ *
19892
+ * @public
19893
+ */
19894
+
19895
+ this.isNestedItem = () => {
19896
+ return isTreeItemElement(this.parentElement);
19897
+ };
19898
+ /**
19899
+ * Handle expand button click
19900
+ *
19901
+ * @internal
19902
+ */
19903
+
19073
19904
 
19074
19905
  this.handleExpandCollapseButtonClick = e => {
19075
- if (!this.disabled) {
19076
- e.preventDefault();
19077
- this.setExpanded(!this.expanded);
19906
+ if (!this.disabled && !e.defaultPrevented) {
19907
+ this.expanded = !this.expanded;
19078
19908
  }
19079
19909
  };
19910
+ /**
19911
+ * Handle focus events
19912
+ *
19913
+ * @internal
19914
+ */
19080
19915
 
19081
- this.handleClick = e => {
19082
- if (!e.defaultPrevented) {
19083
- const target = e.composedPath();
19084
- const clickedTreeItem = target.find(t => t instanceof HTMLElement && isTreeItemElement(t));
19085
19916
 
19086
- if (clickedTreeItem === this) {
19087
- this.handleSelected();
19088
- } // do not prevent default as it completely eats the click
19917
+ this.handleFocus = e => {
19918
+ this.setAttribute("tabindex", "0");
19919
+ };
19920
+ /**
19921
+ * Handle blur events
19922
+ *
19923
+ * @internal
19924
+ */
19089
19925
 
19090
19926
 
19091
- return true;
19092
- }
19927
+ this.handleBlur = e => {
19928
+ this.setAttribute("tabindex", "-1");
19093
19929
  };
19930
+ }
19094
19931
 
19095
- this.isNestedItem = () => {
19096
- return isTreeItemElement(this.parentElement);
19097
- };
19932
+ expandedChanged() {
19933
+ if (this.$fastController.isConnected) {
19934
+ this.$emit("expanded-change", this);
19935
+ }
19936
+ }
19937
+
19938
+ selectedChanged() {
19939
+ if (this.$fastController.isConnected) {
19940
+ this.$emit("selected-change", this);
19941
+ }
19098
19942
  }
19099
19943
 
19100
19944
  itemsChanged(oldValue, newValue) {
@@ -19109,6 +19953,8 @@ class TreeItem extends FoundationElement {
19109
19953
  }
19110
19954
  /**
19111
19955
  * Places document focus on a tree item
19956
+ *
19957
+ * @public
19112
19958
  * @param el - the element to focus
19113
19959
  */
19114
19960
 
@@ -19117,6 +19963,12 @@ class TreeItem extends FoundationElement {
19117
19963
  el.focusable = true;
19118
19964
  el.focus();
19119
19965
  }
19966
+ /**
19967
+ * Gets number of children
19968
+ *
19969
+ * @internal
19970
+ */
19971
+
19120
19972
 
19121
19973
  childItemLength() {
19122
19974
  const treeChildren = this.childItems.filter(item => {
@@ -19125,23 +19977,6 @@ class TreeItem extends FoundationElement {
19125
19977
  return treeChildren ? treeChildren.length : 0;
19126
19978
  }
19127
19979
 
19128
- handleSelected(e) {
19129
- if (e === null || e === void 0 ? void 0 : e.defaultPrevented) {
19130
- return;
19131
- }
19132
-
19133
- e === null || e === void 0 ? void 0 : e.preventDefault();
19134
-
19135
- if (!this.disabled) {
19136
- this.$emit("selected-change", e);
19137
- }
19138
- }
19139
-
19140
- setExpanded(expanded) {
19141
- this.expanded = expanded;
19142
- this.$emit("expanded-change", this);
19143
- }
19144
-
19145
19980
  }
19146
19981
 
19147
19982
  __decorate$1([attr({
@@ -19173,7 +20008,7 @@ applyMixins(TreeItem, StartEnd);
19173
20008
  * @public
19174
20009
  */
19175
20010
 
19176
- const treeViewTemplate = (context, definition) => html`<template role="tree" ${ref("treeView")} @keydown="${(x, c) => x.handleKeyDown(c.event)}" @focusout="${(x, c) => x.handleBlur(c.event)}" @focusin="${(x, c) => x.handleFocus(c.event)}"><slot ${slotted("slottedTreeItems")}></slot></template>`;
20011
+ const treeViewTemplate = (context, definition) => html`<template role="tree" ${ref("treeView")} @keydown="${(x, c) => x.handleKeyDown(c.event)}" @focusin="${(x, c) => x.handleFocus(c.event)}" @focusout="${(x, c) => x.handleBlur(c.event)}" @click="${(x, c) => x.handleClick(c.event)}" @selected-change="${(x, c) => x.handleSelectedChange(c.event)}"><slot ${slotted("slottedTreeItems")}></slot></template>`;
19177
20012
 
19178
20013
  /**
19179
20014
  * A Tree view Custom HTML Element.
@@ -19185,57 +20020,86 @@ const treeViewTemplate = (context, definition) => html`<template role="tree" ${r
19185
20020
  class TreeView extends FoundationElement {
19186
20021
  constructor() {
19187
20022
  super(...arguments);
20023
+ /**
20024
+ * The tree item that is designated to be in the tab queue.
20025
+ *
20026
+ * @internal
20027
+ */
19188
20028
 
19189
- this.handleBlur = e => {
19190
- const {
19191
- relatedTarget,
19192
- target
19193
- } = e;
19194
-
19195
- if (target instanceof HTMLElement && (relatedTarget === null || !this.contains(relatedTarget))) {
19196
- this.setAttribute("tabindex", "0");
19197
- }
19198
- };
20029
+ this.currentFocused = null;
20030
+ /**
20031
+ * Handle focus events
20032
+ *
20033
+ * @internal
20034
+ */
19199
20035
 
19200
20036
  this.handleFocus = e => {
19201
- const {
19202
- relatedTarget,
19203
- target
19204
- } = e;
20037
+ if (this.slottedTreeItems.length < 1) {
20038
+ // no child items, nothing to do
20039
+ return;
20040
+ }
19205
20041
 
19206
- if (target instanceof HTMLElement && (relatedTarget === null || !this.contains(relatedTarget))) {
19207
- const treeView = this;
20042
+ if (e.target === this) {
20043
+ if (this.currentFocused === null) {
20044
+ this.currentFocused = this.getValidFocusableItem();
20045
+ }
19208
20046
 
19209
- if (target === this && this.currentFocused instanceof TreeItem) {
20047
+ if (this.currentFocused !== null) {
19210
20048
  TreeItem.focusItem(this.currentFocused);
19211
- this.currentFocused.setAttribute("tabindex", "0");
19212
20049
  }
19213
20050
 
19214
- treeView.setAttribute("tabindex", "-1");
20051
+ return;
20052
+ }
20053
+
20054
+ if (this.contains(e.target)) {
20055
+ this.setAttribute("tabindex", "-1");
20056
+ this.currentFocused = e.target;
20057
+ }
20058
+ };
20059
+ /**
20060
+ * Handle blur events
20061
+ *
20062
+ * @internal
20063
+ */
20064
+
20065
+
20066
+ this.handleBlur = e => {
20067
+ if (e.target instanceof HTMLElement && (e.relatedTarget === null || !this.contains(e.relatedTarget))) {
20068
+ this.setAttribute("tabindex", "0");
19215
20069
  }
19216
20070
  };
20071
+ /**
20072
+ * KeyDown handler
20073
+ *
20074
+ * @internal
20075
+ */
20076
+
19217
20077
 
19218
20078
  this.handleKeyDown = e => {
19219
- if (!this.treeItems) {
20079
+ if (e.defaultPrevented) {
20080
+ return;
20081
+ }
20082
+
20083
+ if (this.slottedTreeItems.length < 1) {
19220
20084
  return true;
19221
20085
  }
19222
20086
 
20087
+ const treeItems = this.getVisibleNodes();
20088
+
19223
20089
  switch (e.key) {
19224
20090
  case keyHome:
19225
- if (this.treeItems && this.treeItems.length) {
19226
- TreeItem.focusItem(this.treeItems[0]);
19227
- this.treeItems[0].setAttribute("tabindex", "0");
20091
+ if (treeItems.length) {
20092
+ TreeItem.focusItem(treeItems[0]);
19228
20093
  }
19229
20094
 
19230
- break;
20095
+ return;
19231
20096
 
19232
20097
  case keyEnd:
19233
- if (this.treeItems && this.treeItems.length) {
19234
- TreeItem.focusItem(this.treeItems[this.treeItems.length - 1]);
19235
- this.treeItems[this.treeItems.length - 1].setAttribute("tabindex", "0");
20098
+ if (treeItems.length) {
20099
+ TreeItem.focusItem(treeItems[treeItems.length - 1]);
19236
20100
  }
19237
20101
 
19238
- break;
20102
+ return;
19239
20103
 
19240
20104
  case keyArrowLeft:
19241
20105
  if (e.target && this.isFocusableElement(e.target)) {
@@ -19246,7 +20110,7 @@ class TreeView extends FoundationElement {
19246
20110
  }
19247
20111
  }
19248
20112
 
19249
- break;
20113
+ return false;
19250
20114
 
19251
20115
  case keyArrowRight:
19252
20116
  if (e.target && this.isFocusableElement(e.target)) {
@@ -19257,62 +20121,84 @@ class TreeView extends FoundationElement {
19257
20121
  }
19258
20122
  }
19259
20123
 
19260
- break;
20124
+ return;
19261
20125
 
19262
20126
  case keyArrowDown:
19263
20127
  if (e.target && this.isFocusableElement(e.target)) {
19264
20128
  this.focusNextNode(1, e.target);
19265
20129
  }
19266
20130
 
19267
- break;
20131
+ return;
19268
20132
 
19269
20133
  case keyArrowUp:
19270
20134
  if (e.target && this.isFocusableElement(e.target)) {
19271
20135
  this.focusNextNode(-1, e.target);
19272
20136
  }
19273
20137
 
19274
- break;
20138
+ return;
19275
20139
 
19276
20140
  case keyEnter:
19277
20141
  // In single-select trees where selection does not follow focus (see note below),
19278
20142
  // the default action is typically to select the focused node.
19279
- this.handleSelected(e.target);
19280
- break;
20143
+ this.handleClick(e);
20144
+ return;
20145
+ } // don't prevent default if we took no action
19281
20146
 
19282
- default:
19283
- return true;
19284
- }
20147
+
20148
+ return true;
19285
20149
  };
20150
+ /**
20151
+ * Handles the selected-changed events bubbling up
20152
+ * from child tree items
20153
+ *
20154
+ * @internal
20155
+ */
19286
20156
 
19287
- this.setItems = () => {
19288
- let focusIndex = this.treeItems.findIndex(this.isSelectedElement);
19289
20157
 
19290
- if (focusIndex === -1) {
19291
- focusIndex = this.treeItems.findIndex(this.isFocusableElement);
20158
+ this.handleSelectedChange = e => {
20159
+ if (e.defaultPrevented) {
20160
+ return;
19292
20161
  }
19293
20162
 
19294
- for (let item = 0; item < this.treeItems.length; item++) {
19295
- if (item === focusIndex) {
19296
- this.treeItems[item].setAttribute("tabindex", "0");
19297
- this.currentFocused = this.treeItems[item];
19298
- }
19299
-
19300
- this.treeItems[item].addEventListener("selected-change", this.handleItemSelected);
20163
+ if (!(e.target instanceof Element) || !isTreeItemElement(e.target)) {
20164
+ return true;
19301
20165
  }
19302
- };
19303
20166
 
19304
- this.resetItems = () => {
19305
- for (let item = 0; item < this.treeItems.length; item++) {
19306
- this.treeItems[item].removeEventListener("selected-change", this.handleItemSelected);
20167
+ const item = e.target;
20168
+
20169
+ if (item.selected && this.currentSelected !== item) {
20170
+ // new selected item
20171
+ this.currentSelected = item;
20172
+ } else if (!item.selected && this.currentSelected === item) {
20173
+ // selected item deselected
20174
+ this.currentSelected = null;
19307
20175
  }
20176
+
20177
+ return;
19308
20178
  };
20179
+ /**
20180
+ * Updates the tree view when slottedTreeItems changes
20181
+ */
19309
20182
 
19310
- this.handleItemSelected = e => {
19311
- const newSelection = e.target;
19312
20183
 
19313
- if (newSelection !== this.currentSelected) {
19314
- this.handleSelected(newSelection);
19315
- }
20184
+ this.setItems = () => {
20185
+ // force single selection
20186
+ // defaults to first one found
20187
+ const selectedItem = this.treeView.querySelector("[aria-selected='true']");
20188
+ this.currentSelected = selectedItem; // invalidate the current focused item if it is no longer valid
20189
+
20190
+ if (this.currentFocused === null || !this.contains(this.currentFocused)) {
20191
+ this.currentFocused = this.getValidFocusableItem();
20192
+ } // toggle properties on child elements
20193
+
20194
+
20195
+ this.nested = this.checkForNestedItems();
20196
+ const treeItems = this.getVisibleNodes();
20197
+ treeItems.forEach(node => {
20198
+ if (isTreeItemElement(node)) {
20199
+ node.nested = this.nested;
20200
+ }
20201
+ });
19316
20202
  };
19317
20203
  /**
19318
20204
  * check if the item is focusable
@@ -19328,95 +20214,94 @@ class TreeView extends FoundationElement {
19328
20214
  };
19329
20215
  }
19330
20216
 
19331
- slottedTreeItemsChanged(oldValue, newValue) {
20217
+ slottedTreeItemsChanged() {
19332
20218
  if (this.$fastController.isConnected) {
19333
- // filter the tree items until that's done for us in the framework
19334
- this.resetItems();
19335
- this.treeItems = this.getVisibleNodes();
19336
- this.setItems(); // check if any tree items have nested items
19337
- // if they do, apply the nested attribute
19338
-
19339
- if (this.checkForNestedItems()) {
19340
- this.slottedTreeItems.forEach(node => {
19341
- if (isTreeItemElement(node)) {
19342
- node.nested = true;
19343
- }
19344
- });
19345
- }
20219
+ // update for slotted children change
20220
+ this.setItems();
19346
20221
  }
19347
20222
  }
19348
20223
 
19349
- checkForNestedItems() {
19350
- return this.slottedTreeItems.some(node => {
19351
- return isTreeItemElement(node) && node.querySelector("[role='treeitem']");
19352
- });
19353
- }
19354
-
19355
20224
  connectedCallback() {
19356
20225
  super.connectedCallback();
19357
- this.treeItems = this.getVisibleNodes();
20226
+ this.setAttribute("tabindex", "0");
19358
20227
  DOM.queueUpdate(() => {
19359
- //only supporting single select
19360
- const node = this.treeView.querySelector("[aria-selected='true']");
19361
-
19362
- if (node) {
19363
- this.currentSelected = node;
19364
- }
20228
+ this.setItems();
19365
20229
  });
19366
20230
  }
20231
+ /**
20232
+ * Handles click events bubbling up
20233
+ *
20234
+ * @internal
20235
+ */
19367
20236
 
19368
- focusNextNode(delta, item) {
19369
- const visibleNodes = this.getVisibleNodes();
19370
20237
 
19371
- if (!visibleNodes) {
20238
+ handleClick(e) {
20239
+ if (e.defaultPrevented) {
20240
+ // handled, do nothing
19372
20241
  return;
19373
20242
  }
19374
20243
 
19375
- const index = visibleNodes.indexOf(item);
19376
- const lastItem = visibleNodes[index];
20244
+ if (!(e.target instanceof Element) || !isTreeItemElement(e.target)) {
20245
+ // not a tree item, ignore
20246
+ return true;
20247
+ }
20248
+
20249
+ const item = e.target;
20250
+
20251
+ if (!item.disabled) {
20252
+ item.selected = !item.selected;
20253
+ }
20254
+
20255
+ return;
20256
+ }
20257
+ /**
20258
+ * Move focus to a tree item based on its offset from the provided item
20259
+ */
20260
+
20261
+
20262
+ focusNextNode(delta, item) {
20263
+ const visibleNodes = this.getVisibleNodes();
19377
20264
 
19378
- if (delta < 0 && index > 0) {
19379
- lastItem.setAttribute("tabindex", "-1");
19380
- } else if (delta > 0 && index < visibleNodes.length - 1) {
19381
- lastItem.setAttribute("tabindex", "-1");
20265
+ if (!visibleNodes) {
20266
+ return;
19382
20267
  }
19383
20268
 
19384
20269
  const focusItem = visibleNodes[visibleNodes.indexOf(item) + delta];
19385
20270
 
19386
20271
  if (isHTMLElement(focusItem)) {
19387
20272
  TreeItem.focusItem(focusItem);
19388
- focusItem.setAttribute("tabindex", "0");
19389
- this.currentFocused = focusItem;
19390
20273
  }
19391
20274
  }
20275
+ /**
20276
+ * checks if there are any nested tree items
20277
+ */
19392
20278
 
19393
- handleSelected(item) {
19394
- if (this.currentSelected !== item) {
19395
- item.setAttribute("tabindex", "0");
19396
-
19397
- if (this.currentSelected instanceof TreeItem && this.currentFocused) {
19398
- if (!item.disabled) {
19399
- this.currentSelected.selected = false;
19400
- }
19401
20279
 
19402
- this.currentFocused.setAttribute("tabindex", "-1");
19403
- }
20280
+ getValidFocusableItem() {
20281
+ const treeItems = this.getVisibleNodes(); // default to selected element if there is one
19404
20282
 
19405
- if (!this.currentSelected) {
19406
- this.slottedTreeItems.forEach(item => {
19407
- if (item instanceof TreeItem) {
19408
- item.setAttribute("tabindex", "-1");
19409
- }
19410
- });
19411
- }
20283
+ let focusIndex = treeItems.findIndex(this.isSelectedElement);
19412
20284
 
19413
- if (!item.disabled) {
19414
- item.selected = true;
19415
- this.currentSelected = item;
19416
- }
20285
+ if (focusIndex === -1) {
20286
+ // otherwise first focusable tree item
20287
+ focusIndex = treeItems.findIndex(this.isFocusableElement);
20288
+ }
19417
20289
 
19418
- this.currentFocused = item;
20290
+ if (focusIndex !== -1) {
20291
+ return treeItems[focusIndex];
19419
20292
  }
20293
+
20294
+ return null;
20295
+ }
20296
+ /**
20297
+ * checks if there are any nested tree items
20298
+ */
20299
+
20300
+
20301
+ checkForNestedItems() {
20302
+ return this.slottedTreeItems.some(node => {
20303
+ return isTreeItemElement(node) && node.querySelector("[role='treeitem']");
20304
+ });
19420
20305
  }
19421
20306
 
19422
20307
  getVisibleNodes() {
@@ -19431,42 +20316,8 @@ __decorate$1([attr({
19431
20316
 
19432
20317
  __decorate$1([observable], TreeView.prototype, "currentSelected", void 0);
19433
20318
 
19434
- __decorate$1([observable], TreeView.prototype, "nested", void 0);
19435
-
19436
20319
  __decorate$1([observable], TreeView.prototype, "slottedTreeItems", void 0);
19437
20320
 
19438
- /**
19439
- * Expose ltr and rtl strings
19440
- */
19441
- var Direction;
19442
-
19443
- (function (Direction) {
19444
- Direction["ltr"] = "ltr";
19445
- Direction["rtl"] = "rtl";
19446
- })(Direction || (Direction = {}));
19447
-
19448
- /**
19449
- * Define system colors for use in CSS stylesheets.
19450
- *
19451
- * https://drafts.csswg.org/css-color/#css-system-colors
19452
- */
19453
- var SystemColors;
19454
-
19455
- (function (SystemColors) {
19456
- SystemColors["Canvas"] = "Canvas";
19457
- SystemColors["CanvasText"] = "CanvasText";
19458
- SystemColors["LinkText"] = "LinkText";
19459
- SystemColors["VisitedText"] = "VisitedText";
19460
- SystemColors["ActiveText"] = "ActiveText";
19461
- SystemColors["ButtonFace"] = "ButtonFace";
19462
- SystemColors["ButtonText"] = "ButtonText";
19463
- SystemColors["Field"] = "Field";
19464
- SystemColors["FieldText"] = "FieldText";
19465
- SystemColors["Highlight"] = "Highlight";
19466
- SystemColors["HighlightText"] = "HighlightText";
19467
- SystemColors["GrayText"] = "GrayText";
19468
- })(SystemColors || (SystemColors = {}));
19469
-
19470
20321
  /**
19471
20322
  * Ensures that an input number does not exceed a max value and is not less than a min value.
19472
20323
  * @param i - the number to clamp
@@ -19907,22 +20758,50 @@ function rgbToRelativeLuminance(rgb) {
19907
20758
 
19908
20759
  return rgbToLinearLuminance(new ColorRGBA64(luminanceHelper(rgb.r), luminanceHelper(rgb.g), luminanceHelper(rgb.b), 1));
19909
20760
  }
20761
+
20762
+ function calcChannelOverlay(match, background, overlay) {
20763
+ if (overlay - background === 0) {
20764
+ return 0;
20765
+ } else {
20766
+ return (match - background) / (overlay - background);
20767
+ }
20768
+ }
20769
+
20770
+ function calcRgbOverlay(rgbMatch, rgbBackground, rgbOverlay) {
20771
+ const rChannel = calcChannelOverlay(rgbMatch.r, rgbBackground.r, rgbOverlay.r);
20772
+ const gChannel = calcChannelOverlay(rgbMatch.g, rgbBackground.g, rgbOverlay.g);
20773
+ const bChannel = calcChannelOverlay(rgbMatch.b, rgbBackground.b, rgbOverlay.b);
20774
+ return (rChannel + gChannel + bChannel) / 3;
20775
+ }
19910
20776
  /**
19911
- * Calculate an overlay color that uses rgba (rgb + alpha) that matches the appareance of a given solid color when placed on the same background
20777
+ * Calculate an overlay color that uses rgba (rgb + alpha) that matches the appearance of a given solid color when placed on the same background
19912
20778
  * @param rgbMatch - The solid color the overlay should match in appearance when placed over the rgbBackground
19913
20779
  * @param rgbBackground - The background on which the overlay rests
19914
- * @param rgbOverlay - The rgb color of the overlay. Typically this is either pure white or pure black. This color will be used in the returned output
20780
+ * @param rgbOverlay - The rgb color of the overlay. Typically this is either pure white or pure black and when not provided will be determined automatically. This color will be used in the returned output
19915
20781
  * @returns The rgba (rgb + alpha) color of the overlay
19916
20782
  *
19917
20783
  * @public
19918
20784
  */
19919
20785
 
19920
- function calculateOverlayColor(rgbMatch, rgbBackground, rgbOverlay) {
19921
- const rChannel = (rgbMatch.r - rgbBackground.r) / (rgbOverlay.r - rgbBackground.r);
19922
- const gChannel = (rgbMatch.g - rgbBackground.g) / (rgbOverlay.g - rgbBackground.g);
19923
- const bChannel = (rgbMatch.b - rgbBackground.b) / (rgbOverlay.b - rgbBackground.b);
19924
- const alpha = (rChannel + gChannel + bChannel) / 3;
19925
- return new ColorRGBA64(rgbOverlay.r, rgbOverlay.g, rgbOverlay.b, alpha);
20786
+
20787
+ function calculateOverlayColor(rgbMatch, rgbBackground, rgbOverlay = null) {
20788
+ let alpha = 0;
20789
+ let overlay = rgbOverlay;
20790
+
20791
+ if (overlay !== null) {
20792
+ alpha = calcRgbOverlay(rgbMatch, rgbBackground, overlay);
20793
+ } else {
20794
+ overlay = new ColorRGBA64(0, 0, 0, 1);
20795
+ alpha = calcRgbOverlay(rgbMatch, rgbBackground, overlay);
20796
+
20797
+ if (alpha <= 0) {
20798
+ overlay = new ColorRGBA64(1, 1, 1, 1);
20799
+ alpha = calcRgbOverlay(rgbMatch, rgbBackground, overlay);
20800
+ }
20801
+ }
20802
+
20803
+ alpha = Math.round(alpha * 1000) / 1000;
20804
+ return new ColorRGBA64(overlay.r, overlay.g, overlay.b, alpha);
19926
20805
  }
19927
20806
  /**
19928
20807
  * Converts a {@link @microsoft/fast-colors#ColorRGBA64} to a {@link @microsoft/fast-colors#ColorHSL}
@@ -21090,7 +21969,7 @@ const typeRampPlus1LineHeight = create('type-ramp-plus-1-line-height').withDefau
21090
21969
  const typeRampPlus2FontSize = create('type-ramp-plus-2-font-size').withDefault('20px');
21091
21970
  /** @public */
21092
21971
 
21093
- const typeRampPlus2LineHeight = create('type-ramp-plus-2-line-height').withDefault('28px');
21972
+ const typeRampPlus2LineHeight = create('type-ramp-plus-2-line-height').withDefault('26px');
21094
21973
  /** @public */
21095
21974
 
21096
21975
  const typeRampPlus3FontSize = create('type-ramp-plus-3-font-size').withDefault('24px');
@@ -22848,6 +23727,9 @@ __decorate([attr({
22848
23727
  const fluentCombobox = Combobox.compose({
22849
23728
  baseName: 'combobox',
22850
23729
  baseClass: Combobox$1,
23730
+ shadowOptions: {
23731
+ delegatesFocus: true
23732
+ },
22851
23733
  template: comboboxTemplate,
22852
23734
  styles: comboboxStyles$1,
22853
23735
  indicator: `