@brightspace-ui/core 3.110.2 → 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.
- package/components/list/demo/list.html +93 -0
- package/components/list/list-item-button-mixin.js +37 -11
- package/components/list/list-item-drag-drop-mixin.js +3 -0
- package/components/list/list-item-generic-layout.js +1 -1
- package/components/list/list-item-link-mixin.js +26 -12
- package/components/list/list-item-mixin.js +19 -10
- package/components/tooltip/tooltip.js +12 -35
- package/helpers/interactive.js +57 -0
- package/package.json +1 -1
@@ -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 {
|
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
|
-
|
65
|
-
|
66
|
-
|
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
|
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 {
|
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
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
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}"
|
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
|
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>` :
|
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
|
45
|
-
|
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
|
59
|
-
|
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
|
-
|
817
|
-
|
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
|
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 ||
|
946
|
+
} else if (!this.announced || isTargetInteractive) {
|
970
947
|
elemIdListAdd(this._target, 'aria-describedby', this.id);
|
971
948
|
}
|
972
|
-
if (logAccessibilityWarning && !
|
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.
|
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",
|