@brightspace-ui/core 3.110.1 → 3.111.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.
@@ -232,6 +232,7 @@ class AlertToast extends LitElement {
232
232
  'd2l-alert-toast-container-lowest': !this._totalSiblingHeightBelow,
233
233
  'vdiff-target': true
234
234
  };
235
+
235
236
  return html`
236
237
  <div
237
238
  class="${classMap(containerClasses)}"
@@ -248,6 +249,7 @@ class AlertToast extends LitElement {
248
249
  ?hidden="${this._state === states.CLOSED}"
249
250
  @mouseenter=${this._onMouseEnter}
250
251
  @mouseleave=${this._onMouseLeave}
252
+ role="${ifDefined(this._state !== states.CLOSED ? 'alert' : undefined)}"
251
253
  subtext="${ifDefined(this.subtext)}"
252
254
  type="${ifDefined(this.type)}">
253
255
  <slot></slot>
@@ -392,7 +394,6 @@ class AlertToast extends LitElement {
392
394
  this._totalSiblingHeightBelow = 0;
393
395
  this._numAlertsBelow = 0;
394
396
  this._closeClicked = false;
395
- this.removeAttribute('role');
396
397
  }
397
398
 
398
399
  _onTransitionEnd() {
@@ -420,13 +421,11 @@ class AlertToast extends LitElement {
420
421
  this._state = states.OPEN;
421
422
  }
422
423
  }
423
- this.setAttribute('role', 'alert');
424
424
  } else {
425
425
  if (!this._innerContainer) return;
426
426
 
427
427
  if (activeReduceMotion || this._state === states.PREOPENING) {
428
428
  cancelAnimationFrame(this._preopenFrame);
429
- this.removeAttribute('role');
430
429
  } else if (this._state === states.OPENING || this._state === states.OPEN || this._state === states.SLIDING) {
431
430
  this._state = states.CLOSING;
432
431
  }
@@ -6,14 +6,17 @@
6
6
  <link rel="stylesheet" href="../../demo/styles.css" type="text/css">
7
7
  <script type="module">
8
8
  import '../../button/button-icon.js';
9
+ import '../../button/button-subtle.js';
9
10
  import '../../demo/demo-page.js';
10
11
  import '../../dropdown/dropdown-menu.js';
11
12
  import '../../dropdown/dropdown-more.js';
12
13
  import '../../menu/menu.js';
13
14
  import '../../menu/menu-item.js';
14
15
  import '../../tooltip/tooltip.js';
16
+ import '../../tooltip/tooltip-help.js';
15
17
  import '../list-item-content.js';
16
18
  import '../list-item.js';
19
+ import '../list-item-button.js';
17
20
  import '../list.js';
18
21
  import '../../tag-list/tag-list.js';
19
22
  import '../../tag-list/tag-list-item.js';
@@ -201,6 +204,96 @@
201
204
  </template>
202
205
  </d2l-demo-snippet>
203
206
 
207
+ <h2>List (with interactive primary action content)</h2>
208
+
209
+ <d2l-demo-snippet>
210
+ <template>
211
+ <d2l-list grid>
212
+ <d2l-list-item expandable key="expand-1" label="Expandable item #1" href=" ">
213
+ <d2l-list-item-content>
214
+ <div>Week 1: Introduction</div>
215
+ <div slot="secondary" style="padding: 5px;"><d2l-tooltip-help text="Due: Jan 30, 2023">Available: Aug 11, 2023</d2l-tooltip-help></div>
216
+ <div slot="supporting-info"><d2l-button-subtle style="padding: 5px;" text="Bookmark" icon="tier1:bookmark-hollow"></d2l-button-subtle></div>
217
+ </d2l-list-item-content>
218
+ <d2l-list grid slot="nested">
219
+ <d2l-list-item selectable key="nested-1" label="Nested 1">
220
+ <d2l-list-item-content><div>Nested item #1</div></d2l-list-item-content>
221
+ </d2l-list-item>
222
+ <d2l-list-item selectable key="nested-2" label="Nested 2">
223
+ <d2l-list-item-content><div>Nested item #2</div></d2l-list-item-content>
224
+ </d2l-list-item>
225
+ </d2l-list>
226
+ </d2l-list-item>
227
+ <d2l-list-item href="http://www.d2l.com">
228
+ <d2l-list-item-content>
229
+ <div>Week 2: Learn more</div>
230
+ <div slot="secondary">Secondary Information</div>
231
+ </d2l-list-item-content>
232
+ </d2l-list-item>
233
+ <d2l-list-item href="http://www.d2l.com">
234
+ <d2l-list-item-content>
235
+ <div>Week 3: Learn even more!</div>
236
+ <div slot="secondary">Secondary Information</div>
237
+ </d2l-list-item-content>
238
+ </d2l-list-item>
239
+ </d2l-list>
240
+ </template>
241
+ <script type="module">
242
+ requestAnimationFrame(() => {
243
+ document.querySelector('d2l-button-subtle').addEventListener('click', () => {
244
+ console.log('d2l-button: click event');
245
+ });
246
+ });
247
+ </script>
248
+ </d2l-demo-snippet>
249
+
250
+ <h2>List (with button-items and interactive primary action content) </h2>
251
+
252
+ <d2l-demo-snippet>
253
+ <template>
254
+ <d2l-list grid id="button-item-list">
255
+ <d2l-list-item-button expandable key="expand-1" label="Expandable item #1">
256
+ <d2l-list-item-content>
257
+ <div>Week 1: Introduction</div>
258
+ <div slot="secondary" style="padding: 5px;"><d2l-tooltip-help text="Due: Jan 30, 2023">Available: Aug 11, 2023</d2l-tooltip-help></div>
259
+ <div slot="supporting-info"><d2l-button-subtle style="padding: 5px;" text="Bookmark" icon="tier1:bookmark-hollow"></d2l-button-subtle></div>
260
+ </d2l-list-item-content>
261
+ <d2l-list grid slot="nested">
262
+ <d2l-list-item-button selectable key="nested-1" label="Nested 1">
263
+ <d2l-list-item-content><div>Nested item #1</div></d2l-list-item-content>
264
+ </d2l-list-item-button>
265
+ <d2l-list-item-button selectable key="nested-2" label="Nested 2">
266
+ <d2l-list-item-content><div>Nested item #2</div></d2l-list-item-content>
267
+ </d2l-list-item-button>
268
+ </d2l-list>
269
+ </d2l-list-item-button>
270
+ <d2l-list-item-button button-disabled>
271
+ <d2l-list-item-content>
272
+ <div>Week 2: Learn more</div>
273
+ <div slot="secondary">Secondary Information</div>
274
+ </d2l-list-item-content>
275
+ </d2l-list-item-button>
276
+ <d2l-list-item-button>
277
+ <d2l-list-item-content>
278
+ <div>Week 3: Learn even more!</div>
279
+ <div slot="secondary">Secondary Information</div>
280
+ </d2l-list-item-content>
281
+ </d2l-list-item-button>
282
+ </d2l-list>
283
+ </template>
284
+ <script type="module">
285
+ requestAnimationFrame(() => {
286
+ const list = document.querySelector('#button-item-list');
287
+ list.addEventListener('d2l-list-item-button-click', () => {
288
+ console.log('d2l-list-item-button: click event');
289
+ });
290
+ list.querySelector('d2l-button-subtle').addEventListener('click', () => {
291
+ console.log('d2l-button: click event');
292
+ });
293
+ });
294
+ </script>
295
+ </d2l-demo-snippet>
296
+
204
297
  </d2l-demo-page>
205
298
 
206
299
  </body>
@@ -1,7 +1,8 @@
1
1
  import '../colors/colors.js';
2
2
  import { css, html } from 'lit';
3
+ import { listInteractiveElems, ListItemMixin } from './list-item-mixin.js';
3
4
  import { getUniqueId } from '../../helpers/uniqueId.js';
4
- import { ListItemMixin } from './list-item-mixin.js';
5
+ import { isInteractiveInComposedPath } from '../../helpers/interactive.js';
5
6
 
6
7
  export const ListItemButtonMixin = superclass => class extends ListItemMixin(superclass) {
7
8
  static get properties() {
@@ -29,17 +30,20 @@ export const ListItemButtonMixin = superclass => class extends ListItemMixin(sup
29
30
  button {
30
31
  background-color: transparent;
31
32
  border: none;
33
+ color: unset;
32
34
  cursor: pointer;
33
35
  display: block;
36
+ font-family: unset;
37
+ font-size: unset;
38
+ font-weight: unset;
34
39
  height: 100%;
40
+ letter-spacing: unset;
41
+ line-height: unset;
35
42
  outline: none;
43
+ padding: 0;
44
+ text-align: start;
36
45
  width: 100%;
37
46
  }
38
- :host(:not([button-disabled]):not([no-primary-action])) [slot="content"],
39
- :host(:not([no-primary-action])) [slot="control-action"] ~ [slot="content"],
40
- :host(:not([no-primary-action])) [slot="outside-control-action"] ~ [slot="content"] {
41
- pointer-events: none;
42
- }
43
47
  :host(:not([button-disabled])) [slot="control-action"],
44
48
  :host(:not([button-disabled])) [slot="outside-control-action"] {
45
49
  grid-column-end: control-end;
@@ -61,13 +65,35 @@ export const ListItemButtonMixin = superclass => class extends ListItemMixin(sup
61
65
  if (changedProperties.has('buttonDisabled') && this.buttonDisabled === true) this._hoveringPrimaryAction = false;
62
66
  }
63
67
 
64
- _onButtonClick() {
65
- /** Dispatched when the item's primary button action is clicked */
66
- this.dispatchEvent(new CustomEvent('d2l-list-item-button-click', { bubbles: true }));
68
+ _getDescendantClicked(e) {
69
+ const isPrimaryAction = (elem) => elem === this.shadowRoot.querySelector(`#${this._primaryActionId}`);
70
+ return isInteractiveInComposedPath(e.composedPath(), isPrimaryAction, { elements: listInteractiveElems });
71
+ }
72
+
73
+ _onButtonClick(e) {
74
+ if (this._getDescendantClicked(e)) {
75
+ e.preventDefault();
76
+ } else {
77
+ /** Dispatched when the item's primary button action is clicked */
78
+ this.dispatchEvent(new CustomEvent('d2l-list-item-button-click', { bubbles: true }));
79
+ }
80
+ }
81
+
82
+ _onButtonFocus(e) {
83
+ if (this._getDescendantClicked(e)) {
84
+ e.stopPropagation();
85
+ }
67
86
  }
68
87
 
69
- _renderPrimaryAction(labelledBy) {
70
- return html`<button id="${this._primaryActionId}" aria-labelledby="${labelledBy}" @click="${this._onButtonClick}" ?disabled="${this.buttonDisabled}"></button>`;
88
+ _renderPrimaryAction(labelledBy, content) {
89
+ return html`<button
90
+ id="${this._primaryActionId}"
91
+ aria-labelledby="${labelledBy}"
92
+ @click="${this._onButtonClick}"
93
+ @focusin="${this._onButtonFocus}"
94
+ ?disabled="${this.buttonDisabled}">
95
+ ${content}
96
+ </button>`;
71
97
  }
72
98
 
73
99
  };
@@ -330,6 +330,9 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
330
330
  :host([_drop-location="7"]) [slot="control-container"]::after {
331
331
  border-color: transparent;
332
332
  }
333
+ :host(:not([no-primary-action])) [slot="outside-control-action"] ~ [slot="content"] {
334
+ pointer-events: none;
335
+ }
333
336
 
334
337
  @media only screen and (hover: hover), only screen and (pointer: fine) {
335
338
  d2l-list-item-drag-handle {
@@ -154,7 +154,7 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
154
154
  }
155
155
 
156
156
  ::slotted([slot="content-action"]) {
157
- grid-column: content-start / end;
157
+ grid-column: content-start / content-end;
158
158
  }
159
159
 
160
160
  :host([no-primary-action]) ::slotted([slot="content-action"]) {
@@ -1,7 +1,8 @@
1
1
  import '../colors/colors.js';
2
2
  import { css, html } from 'lit';
3
+ import { listInteractiveElems, ListItemMixin } from './list-item-mixin.js';
3
4
  import { getUniqueId } from '../../helpers/uniqueId.js';
4
- import { ListItemMixin } from './list-item-mixin.js';
5
+ import { isInteractiveInComposedPath } from '../../helpers/interactive.js';
5
6
 
6
7
  export const ListItemLinkMixin = superclass => class extends ListItemMixin(superclass) {
7
8
 
@@ -22,16 +23,13 @@ export const ListItemLinkMixin = superclass => class extends ListItemMixin(super
22
23
  --d2l-list-item-content-text-color: var(--d2l-color-celestine);
23
24
  }
24
25
  a[href] {
26
+ color: unset;
25
27
  display: block;
26
28
  height: 100%;
27
29
  outline: none;
30
+ text-decoration: none;
28
31
  width: 100%;
29
32
  }
30
- :host([action-href]:not([action-href=""])) [slot="content"],
31
- :host(:not([no-primary-action])) [slot="control-action"] ~ [slot="content"],
32
- :host(:not([no-primary-action])) [slot="outside-control-action"] ~ [slot="content"] {
33
- pointer-events: none;
34
- }
35
33
  :host([action-href]:not([action-href=""])) [slot="control-action"],
36
34
  :host([action-href]:not([action-href=""])) [slot="outside-control-action"] {
37
35
  grid-column-end: control-end;
@@ -53,9 +51,24 @@ export const ListItemLinkMixin = superclass => class extends ListItemMixin(super
53
51
  if (changedProperties.has('actionHref') && !this.actionHref) this._hoveringPrimaryAction = false;
54
52
  }
55
53
 
56
- _handleLinkClick() {
57
- /** Dispatched when the item's primary link action is clicked */
58
- this.dispatchEvent(new CustomEvent('d2l-list-item-link-click', { bubbles: true }));
54
+ _getDescendantClicked(e) {
55
+ const isPrimaryAction = (elem) => elem === this.shadowRoot.querySelector(`#${this._primaryActionId}`);
56
+ return isInteractiveInComposedPath(e.composedPath(), isPrimaryAction, { elements: listInteractiveElems });
57
+ }
58
+
59
+ _handleLinkClick(e) {
60
+ if (this._getDescendantClicked(e)) {
61
+ e.preventDefault();
62
+ } else {
63
+ /** Dispatched when the item's primary link action is clicked */
64
+ this.dispatchEvent(new CustomEvent('d2l-list-item-link-click', { bubbles: true }));
65
+ }
66
+ }
67
+
68
+ _handleLinkFocus(e) {
69
+ if (this._getDescendantClicked(e)) {
70
+ e.stopPropagation();
71
+ }
59
72
  }
60
73
 
61
74
  _handleLinkKeyDown(e) {
@@ -63,16 +76,17 @@ export const ListItemLinkMixin = superclass => class extends ListItemMixin(super
63
76
  // handle the space key
64
77
  e.preventDefault();
65
78
  e.stopPropagation();
66
- this.shadowRoot.querySelector(`#${this._primaryActionId}`).click();
79
+ e.target.click();
67
80
  }
68
81
 
69
- _renderPrimaryAction(labelledBy) {
82
+ _renderPrimaryAction(labelledBy, content) {
70
83
  if (!this.actionHref) return;
71
84
  return html`<a aria-labelledby="${labelledBy}"
72
85
  @click="${this._handleLinkClick}"
86
+ @focusin="${this._handleLinkFocus}"
73
87
  href="${this.actionHref}"
74
88
  id="${this._primaryActionId}"
75
- @keydown="${this._handleLinkKeyDown}"></a>`;
89
+ @keydown="${this._handleLinkKeyDown}">${content}</a>`;
76
90
  }
77
91
 
78
92
  };
@@ -12,6 +12,7 @@ import { getFirstFocusableDescendant } from '../../helpers/focus.js';
12
12
  import { getUniqueId } from '../../helpers/uniqueId.js';
13
13
  import { getValidHexColor } from '../../helpers/color.js';
14
14
  import { ifDefined } from 'lit/directives/if-defined.js';
15
+ import { interactiveElements } from '../../helpers/interactive.js';
15
16
  import { LabelledMixin } from '../../mixins/labelled/labelled-mixin.js';
16
17
  import { ListItemCheckboxMixin } from './list-item-checkbox-mixin.js';
17
18
  import { ListItemDragDropMixin } from './list-item-drag-drop-mixin.js';
@@ -39,6 +40,12 @@ function addTabListener() {
39
40
 
40
41
  let hasDisplayedKeyboardTooltip = false;
41
42
 
43
+ export const listInteractiveElems = {
44
+ ...interactiveElements,
45
+ 'd2l-button': true,
46
+ 'd2l-tooltip-help': true
47
+ };
48
+
42
49
  /**
43
50
  * @property label - The hidden label for the checkbox and expand collapse control
44
51
  */
@@ -679,7 +686,17 @@ export const ListItemMixin = superclass => class extends composeMixins(
679
686
  };
680
687
 
681
688
  const alignNested = ((this.draggable && this.selectable) || (this.expandable && this.selectable && this.color)) ? 'control' : undefined;
682
- const primaryAction = ((!this.noPrimaryAction && this._renderPrimaryAction) ? this._renderPrimaryAction(this._contentId) : null);
689
+ const contentAreaContent = html`
690
+ <div slot="content"
691
+ class="d2l-list-item-content"
692
+ id="${this._contentId}"
693
+ @mouseenter="${this._onMouseEnter}"
694
+ @mouseleave="${this._onMouseLeave}">
695
+ <slot name="illustration" class="d2l-list-item-illustration">${illustration}</slot>
696
+ <slot>${content}</slot>
697
+ </div>
698
+ `;
699
+ const primaryAction = ((!this.noPrimaryAction && this._renderPrimaryAction) ? this._renderPrimaryAction(this._contentId, contentAreaContent) : null);
683
700
  let tooltipForId = null;
684
701
  if (this._showAddButton) {
685
702
  tooltipForId = this._addButtonTopId;
@@ -741,15 +758,7 @@ export const ListItemMixin = superclass => class extends composeMixins(
741
758
  @mouseenter="${this._onMouseEnterPrimaryAction}"
742
759
  @mouseleave="${this._onMouseLeavePrimaryAction}">
743
760
  ${primaryAction}
744
- </div>` : nothing}
745
- <div slot="content"
746
- class="d2l-list-item-content"
747
- id="${this._contentId}"
748
- @mouseenter="${this._onMouseEnter}"
749
- @mouseleave="${this._onMouseLeave}">
750
- <slot name="illustration" class="d2l-list-item-illustration">${illustration}</slot>
751
- <slot>${content}</slot>
752
- </div>
761
+ </div>` : contentAreaContent}
753
762
  <div slot="actions"
754
763
  @mouseenter="${this._onMouseEnter}"
755
764
  @mouseleave="${this._onMouseLeave}"
@@ -2,6 +2,7 @@ import { clearDismissible, setDismissible } from '../../helpers/dismissible.js';
2
2
  import { css, html, LitElement } from 'lit';
3
3
  import { cssEscape, elemIdListAdd, elemIdListRemove, getBoundingAncestor, getOffsetParent, isComposedAncestor } from '../../helpers/dom.js';
4
4
  import { getComposedActiveElement, isFocusable } from '../../helpers/focus.js';
5
+ import { interactiveElements, interactiveRoles, isInteractive } from '../../helpers/interactive.js';
5
6
  import { announce } from '../../helpers/announce.js';
6
7
  import { bodySmallStyles } from '../typography/styles.js';
7
8
  import { classMap } from 'lit/directives/class-map.js';
@@ -41,39 +42,20 @@ const getDelay = delay => {
41
42
  else return delay;
42
43
  };
43
44
 
44
- const interactiveElements = {
45
- // 'a' only if an href is present
46
- 'button': true,
45
+ const tooltipInteractiveElements = {
46
+ ...interactiveElements,
47
47
  'h1': true,
48
48
  'h2': true,
49
49
  'h3': true,
50
50
  'h4': true,
51
51
  'h5': true,
52
- 'h6': true,
53
- 'input': true,
54
- 'select': true,
55
- 'textarea': true
52
+ 'h6': true
56
53
  };
57
54
 
58
- const interactiveRoles = {
59
- 'button': true,
60
- 'checkbox': true,
61
- 'combobox': true,
55
+ const tooltipInteractiveRoles = {
56
+ ...interactiveRoles,
62
57
  'heading': true,
63
- 'img': true,
64
- 'link': true,
65
- 'listbox': true,
66
- 'menuitem': true,
67
- 'menuitemcheckbox': true,
68
- 'menuitemradio': true,
69
- 'option': true,
70
- 'radio': true,
71
- 'slider': true,
72
- 'spinbutton': true,
73
- 'switch': true,
74
- 'tab:': true,
75
- 'textbox': true,
76
- 'treeitem': true
58
+ 'img': true
77
59
  };
78
60
 
79
61
  const computeTooltipShift = (centerDelta, spaceLeft, spaceRight) => {
@@ -813,13 +795,8 @@ class Tooltip extends RtlMixin(LitElement) {
813
795
  if (ele.nodeType !== Node.ELEMENT_NODE) {
814
796
  return false;
815
797
  }
816
- const nodeName = ele.nodeName.toLowerCase();
817
- const isInteractive = interactiveElements[nodeName];
818
- if (isInteractive) {
819
- return true;
820
- }
821
- const role = (ele.getAttribute('role') || '');
822
- return (nodeName === 'a' && ele.hasAttribute('href')) || interactiveRoles[role];
798
+
799
+ return isInteractive(ele, tooltipInteractiveElements, tooltipInteractiveRoles);
823
800
  }
824
801
 
825
802
  _onTargetBlur() {
@@ -961,15 +938,15 @@ class Tooltip extends RtlMixin(LitElement) {
961
938
  if (this._target) {
962
939
  const targetDisabled = this._target.hasAttribute('disabled') || this._target.getAttribute('aria-disabled') === 'true';
963
940
 
964
- const isInteractive = this._isInteractive(this._target);
941
+ const isTargetInteractive = this._isInteractive(this._target);
965
942
  this.id = this.id || getUniqueId();
966
943
  this.setAttribute('role', 'tooltip');
967
944
  if (this.forType === 'label') {
968
945
  elemIdListAdd(this._target, 'aria-labelledby', this.id);
969
- } else if (!this.announced || isInteractive) {
946
+ } else if (!this.announced || isTargetInteractive) {
970
947
  elemIdListAdd(this._target, 'aria-describedby', this.id);
971
948
  }
972
- if (logAccessibilityWarning && !isInteractive && !this.announced) {
949
+ if (logAccessibilityWarning && !isTargetInteractive && !this.announced) {
973
950
  console.warn(
974
951
  'd2l-tooltip may be being used in a non-accessible manner; it should be attached to interactive elements like \'a\', \'button\',' +
975
952
  '\'input\'', '\'select\', \'textarea\' or static / custom elements if a role has been set and the element is focusable.',
@@ -0,0 +1,57 @@
1
+ export const interactiveElements = {
2
+ // 'a' only if an href is present
3
+ 'button': true,
4
+ 'input': true,
5
+ 'select': true,
6
+ 'textarea': true
7
+ };
8
+
9
+ export const interactiveRoles = {
10
+ 'button': true,
11
+ 'checkbox': true,
12
+ 'combobox': true,
13
+ 'link': true,
14
+ 'listbox': true,
15
+ 'menuitem': true,
16
+ 'menuitemcheckbox': true,
17
+ 'menuitemradio': true,
18
+ 'option': true,
19
+ 'radio': true,
20
+ 'slider': true,
21
+ 'spinbutton': true,
22
+ 'switch': true,
23
+ 'tab:': true,
24
+ 'textbox': true,
25
+ 'treeitem': true
26
+ };
27
+
28
+ export function isInteractive(ele, elems, roles) {
29
+ elems = elems || interactiveElements;
30
+ roles = roles || interactiveRoles;
31
+
32
+ const nodeName = ele.nodeName.toLowerCase();
33
+ const isInteractiveElem = elems[nodeName];
34
+ if (isInteractiveElem) {
35
+ return true;
36
+ }
37
+ const role = (ele.getAttribute('role') || '');
38
+ return (nodeName === 'a' && ele.hasAttribute('href')) || roles[role] || false;
39
+ }
40
+
41
+ export function isInteractiveInComposedPath(composedPath, predicate, options) {
42
+ const elems = options?.elements || interactiveElements;
43
+ const roles = options?.roles || interactiveRoles;
44
+ for (let i = 0; i < composedPath.length; i++) {
45
+ const elem = composedPath[i];
46
+ if (!elem.getAttribute) continue;
47
+
48
+ if (predicate && predicate(elem)) {
49
+ break;
50
+ }
51
+
52
+ if (isInteractive(elem, elems, roles)) {
53
+ return true;
54
+ }
55
+ }
56
+ return false;
57
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.110.1",
3
+ "version": "3.111.0",
4
4
  "description": "A collection of accessible, free, open-source web components for building Brightspace applications",
5
5
  "type": "module",
6
6
  "repository": "https://github.com/BrightspaceUI/core.git",