@brightspace-ui/core 3.159.3 → 3.159.5

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.
@@ -123,6 +123,7 @@ if (usePopoverMixin) {
123
123
  // reset to root view
124
124
  const menu = this.#getMenuElement();
125
125
  menu.show({ preventFocus: true });
126
+ menu.resetFocusables();
126
127
  }
127
128
 
128
129
  #handleFocus(e) {
@@ -303,6 +304,7 @@ if (usePopoverMixin) {
303
304
  // reset to root view
304
305
  const menu = this.__getMenuElement();
305
306
  menu.show({ preventFocus: true });
307
+ menu.resetFocusables();
306
308
  }
307
309
 
308
310
  _onFocus(e) {
@@ -44,32 +44,30 @@
44
44
 
45
45
  <h2>Navigation (href) Primary Action</h2>
46
46
 
47
- <d2l-demo-snippet id="link-demo">
47
+ <d2l-demo-snippet>
48
48
  <template>
49
49
  <d2l-list add-button>
50
- <d2l-list>
51
- <d2l-list-item href="http://www.d2l.com">
52
- <d2l-list-item-content>Introductory Earth Sciences</d2l-list-item-content>
53
- </d2l-list-item>
54
- <d2l-list-item href="http://www.d2l.com">
55
- <d2l-list-item-content>Engineering Materials for Energy Systems</d2l-list-item-content>
56
- </d2l-list-item>
57
- <d2l-list-item href="http://www.d2l.com">
58
- <d2l-list-item-content>Geomorphology and GIS</d2l-list-item-content>
59
- </d2l-list-item>
60
- </d2l-list>
50
+ <d2l-list-item href="http://www.d2l.com">
51
+ <d2l-list-item-content>Introductory Earth Sciences</d2l-list-item-content>
52
+ </d2l-list-item>
53
+ <d2l-list-item href="http://www.d2l.com">
54
+ <d2l-list-item-content>Engineering Materials for Energy Systems</d2l-list-item-content>
55
+ </d2l-list-item>
56
+ <d2l-list-item href="http://www.d2l.com">
57
+ <d2l-list-item-content>Geomorphology and GIS</d2l-list-item-content>
58
+ </d2l-list-item>
61
59
  </d2l-list>
62
60
  <script>
63
- document.querySelector('#link-demo').addEventListener('d2l-list-item-link-click', (e) => {
64
- console.log('d2l-list-item-link clicked!', e);
65
- });
61
+ (demo => {
62
+ demo.addEventListener('d2l-list-item-link-click', e => console.log('d2l-list-item-link clicked!', e));
63
+ })(document.currentScript.parentNode);
66
64
  </script>
67
65
  </template>
68
66
  </d2l-demo-snippet>
69
67
 
70
68
  <h2>Button Primary Action</h2>
71
69
 
72
- <d2l-demo-snippet id="button-demo">
70
+ <d2l-demo-snippet>
73
71
  <template>
74
72
  <d2l-list>
75
73
  <d2l-list-item-button>
@@ -83,9 +81,9 @@
83
81
  </d2l-list-item-button>
84
82
  </d2l-list>
85
83
  <script>
86
- document.querySelector('#button-demo').addEventListener('d2l-list-item-button-click', (e) => {
87
- console.log('d2l-list-item-button clicked!', e);
88
- });
84
+ (demo => {
85
+ demo.addEventListener('d2l-list-item-button-click', e => console.log('d2l-list-item-button clicked!', e));
86
+ })(document.currentScript.parentNode);
89
87
  </script>
90
88
  </template>
91
89
  </d2l-demo-snippet>
@@ -240,7 +238,7 @@
240
238
 
241
239
  <h2>Selection & Navigation (href) Primary Action</h2>
242
240
 
243
- <d2l-demo-snippet id="selection-link-demo">
241
+ <d2l-demo-snippet>
244
242
  <template>
245
243
  <d2l-list>
246
244
  <d2l-list-controls slot="controls">
@@ -258,16 +256,16 @@
258
256
  </d2l-list-item>
259
257
  </d2l-list>
260
258
  <script>
261
- document.querySelector('#selection-link-demo').addEventListener('d2l-list-item-link-click', (e) => {
262
- console.log('d2l-list-item-link clicked!', e);
263
- });
259
+ (demo => {
260
+ demo.addEventListener('d2l-list-item-link-click', e => console.log('d2l-list-item-link clicked!', e));
261
+ })(document.currentScript.parentNode);
264
262
  </script>
265
263
  </template>
266
264
  </d2l-demo-snippet>
267
265
 
268
266
  <h2>Selection & Button Primary Action</h2>
269
267
 
270
- <d2l-demo-snippet id="selection-button-demo">
268
+ <d2l-demo-snippet>
271
269
  <template>
272
270
  <d2l-list>
273
271
  <d2l-list-controls slot="controls">
@@ -285,16 +283,16 @@
285
283
  </d2l-list-item-button>
286
284
  </d2l-list>
287
285
  <script>
288
- document.querySelector('#selection-button-demo').addEventListener('d2l-list-item-button-click', (e) => {
289
- console.log('d2l-list-item-button clicked!', e);
290
- });
286
+ (demo => {
287
+ demo.addEventListener('d2l-list-item-button-click', e => console.log('d2l-list-item-button clicked!', e));
288
+ })(document.currentScript.parentNode);
291
289
  </script>
292
290
  </template>
293
291
  </d2l-demo-snippet>
294
292
 
295
293
  <h2>Grid Actions with Navigation (href) Primary Action</h2>
296
294
 
297
- <d2l-demo-snippet id="grid-link-demo">
295
+ <d2l-demo-snippet>
298
296
  <template>
299
297
  <d2l-list grid add-button>
300
298
  <d2l-list-controls slot="controls">
@@ -321,16 +319,16 @@
321
319
  </d2l-list-item>
322
320
  </d2l-list>
323
321
  <script>
324
- document.querySelector('#grid-link-demo').addEventListener('d2l-list-item-link-click', (e) => {
325
- console.log('d2l-list-item-link clicked!', e);
326
- });
322
+ (demo => {
323
+ demo.addEventListener('d2l-list-item-link-click', e => console.log('d2l-list-item-link clicked!', e));
324
+ })(document.currentScript.parentNode);
327
325
  </script>
328
326
  </template>
329
327
  </d2l-demo-snippet>
330
328
 
331
329
  <h2>Grid Actions with Button Primary Action</h2>
332
330
 
333
- <d2l-demo-snippet id="grid-button-demo">
331
+ <d2l-demo-snippet>
334
332
  <template>
335
333
  <d2l-list grid>
336
334
  <d2l-list-controls slot="controls">
@@ -357,9 +355,9 @@
357
355
  </d2l-list-item-button>
358
356
  </d2l-list>
359
357
  <script>
360
- document.querySelector('#grid-button-demo').addEventListener('d2l-list-item-button-click', (e) => {
361
- console.log('d2l-list-item-button clicked!', e);
362
- });
358
+ (demo => {
359
+ demo.addEventListener('d2l-list-item-button-click', e => console.log('d2l-list-item-button clicked!', e));
360
+ })(document.currentScript.parentNode);
363
361
  </script>
364
362
  </template>
365
363
  </d2l-demo-snippet>
@@ -108,6 +108,7 @@ export const ListItemMixin = superclass => class extends composeMixins(
108
108
  _addButtonText: { state: true },
109
109
  _displayKeyboardTooltip: { type: Boolean },
110
110
  _hasColorSlot: { type: Boolean, reflect: true, attribute: '_has-color-slot' },
111
+ _hasListItemContent: { state: true },
111
112
  _hasNestedList: { type: Boolean, reflect: true, attribute: '_has-nested-list' },
112
113
  _hasNestedListAddButton: { type: Boolean, reflect: true, attribute: '_has-nested-list-add-button' },
113
114
  _hovering: { type: Boolean, reflect: true },
@@ -216,6 +217,11 @@ export const ListItemMixin = superclass => class extends composeMixins(
216
217
  --d2l-list-item-content-text-outline: 2px solid var(--d2l-color-celestine);
217
218
  --d2l-list-item-content-text-outline-offset: 1px;
218
219
  }
220
+ :host([_focusing-primary-action]:not([padding-type="none"])) .d2l-list-item-content-none {
221
+ border-radius: 6px;
222
+ outline: var(--d2l-list-item-content-text-outline);
223
+ outline-offset: -4px;
224
+ }
219
225
  @supports selector(:has(a, b)) {
220
226
  :host([_list-item-new-styles][_focusing-primary-action]) .d2l-list-item-content {
221
227
  --d2l-list-item-content-text-border-radius: initial;
@@ -227,7 +233,18 @@ export const ListItemMixin = superclass => class extends composeMixins(
227
233
  --d2l-list-item-content-text-outline: 2px solid var(--d2l-color-celestine);
228
234
  --d2l-list-item-content-text-outline-offset: 1px;
229
235
  }
236
+ :host([_list-item-new-styles][_focusing-primary-action]:not([padding-type="none"])) .d2l-list-item-content-none {
237
+ border-radius: initial;
238
+ outline: initial;
239
+ outline-offset: initial;
240
+ }
241
+ :host([_list-item-new-styles][_focusing-primary-action]:not([padding-type="none"])):has(:focus-visible) .d2l-list-item-content-none {
242
+ border-radius: 8px;
243
+ outline: var(--d2l-list-item-content-text-outline);
244
+ outline-offset: -4px;
245
+ }
230
246
  }
247
+
231
248
  [slot="content-action"] {
232
249
  height: 100%;
233
250
  }
@@ -455,6 +472,7 @@ export const ListItemMixin = superclass => class extends composeMixins(
455
472
  this._contentId = getUniqueId();
456
473
  this._displayKeyboardTooltip = false;
457
474
  this._hasColorSlot = false;
475
+ this._hasListItemContent = true;
458
476
  this._hasNestedList = false;
459
477
  this._listItemInteractiveEnabled = listItemInteractiveFlag;
460
478
  this._listItemNewStyles = useNewStylesFlag;
@@ -487,6 +505,10 @@ export const ListItemMixin = superclass => class extends composeMixins(
487
505
  if (changedProperties.has('_siblingHasColor') || changedProperties.has('color')) {
488
506
  this._hasColorSlot = this.color || this._siblingHasColor;
489
507
  }
508
+ if (this._focusingPrimaryAction && changedProperties.has('_focusingPrimaryAction')) {
509
+ this._hasListItemContent = !!this.shadowRoot.querySelector('slot:not([name])').assignedElements({ flatten: true })
510
+ .find(elem => elem.tagName === 'D2L-LIST-ITEM-CONTENT');
511
+ }
490
512
  }
491
513
 
492
514
  focus() {
@@ -698,11 +720,15 @@ export const ListItemMixin = superclass => class extends composeMixins(
698
720
  'd2l-list-item-color-inner': true,
699
721
  'd2l-skeletize': this.color
700
722
  };
723
+ const contentClasses = {
724
+ 'd2l-list-item-content': true,
725
+ 'd2l-list-item-content-none': !this._hasListItemContent
726
+ };
701
727
 
702
728
  const alignNested = ((this.draggable && this.selectable) || (this.expandable && this.selectable && this.color) || (this._listItemInteractiveEnabled && this.expandable && !this.selectable)) ? 'control' : undefined;
703
729
  const contentAreaContent = html`
704
730
  <div slot="content"
705
- class="d2l-list-item-content"
731
+ class="${classMap(contentClasses)}"
706
732
  id="${this._contentId}"
707
733
  @mouseenter="${this._onMouseEnter}"
708
734
  @mouseleave="${this._onMouseLeave}">
@@ -97,14 +97,13 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
97
97
  firstUpdated(changedProperties) {
98
98
  super.firstUpdated(changedProperties);
99
99
 
100
- this.addEventListener('d2l-hierarchical-view-show-start', this._onVisibilityChange);
101
- this.addEventListener('d2l-hierarchical-view-hide-complete', this._onVisibilityChange);
100
+ this.addEventListener('d2l-hierarchical-view-show-start', this._onShowStart);
101
+ this.addEventListener('d2l-hierarchical-view-hide-complete', this._onHideComplete);
102
102
  this.addEventListener('d2l-hierarchical-view-show-complete', this._onShowComplete);
103
103
  this.addEventListener('d2l-hierarchical-view-resize', this._onViewResize);
104
104
  this.addEventListener('d2l-menu-item-visibility-change', this._onMenuItemsChanged);
105
105
  this.addEventListener('keydown', this._onKeyDown);
106
106
  this.addEventListener('keypress', this._onKeyPress);
107
- this.addEventListener('focusout', this._onFocusOut);
108
107
 
109
108
  this._labelChanged();
110
109
 
@@ -144,7 +143,9 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
144
143
  if (this.getMenuType() === 'menu-radio') {
145
144
  this._focusSelected();
146
145
  } else {
147
- this._focusFirst();
146
+ const lastFocused = this._getTabFocusable();
147
+ if (lastFocused) this._focusItem(lastFocused);
148
+ else this._focusFirst();
148
149
  }
149
150
  }
150
151
 
@@ -166,6 +167,10 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
166
167
  }
167
168
  }
168
169
 
170
+ resetFocusables() {
171
+ this._getTabFocusable()?.setAttribute('tabindex', '-1');
172
+ }
173
+
169
174
  _createReturnItem() {
170
175
  const item = document.createElement('d2l-menu-item-return');
171
176
  item.addEventListener('d2l-menu-item-select', (e) => {
@@ -177,6 +182,8 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
177
182
  }
178
183
 
179
184
  _focusFirst() {
185
+ const lastFocused = this._getTabFocusable();
186
+ if (lastFocused) lastFocused.setAttribute('tabindex', '-1');
180
187
  const item = this._tryGetNextFocusable();
181
188
  if (item) this._focusItem(item);
182
189
  }
@@ -192,11 +199,13 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
192
199
  }
193
200
 
194
201
  _focusNext(item) {
202
+ item.setAttribute('tabindex', '-1');
195
203
  item = this._tryGetNextFocusable(item);
196
204
  item ? this._focusItem(item) : this._focusFirst();
197
205
  }
198
206
 
199
207
  _focusPrevious(item) {
208
+ item.setAttribute('tabindex', '-1');
200
209
  item = this._tryGetPreviousFocusable(item);
201
210
  item ? this._focusItem(item) : this._focusLast();
202
211
  }
@@ -249,6 +258,10 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
249
258
  });
250
259
  }
251
260
 
261
+ _getTabFocusable() {
262
+ return this._items.find(i => i.getAttribute('tabindex') === '0');
263
+ }
264
+
252
265
  _isFocusable(item) {
253
266
  if (item.nodeType !== 1) {
254
267
  return false;
@@ -272,11 +285,9 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
272
285
  if (returnItem) returnItem.setAttribute('text', this.label);
273
286
  }
274
287
 
275
- _onFocusOut(e) {
276
- e.stopPropagation();
277
- const isMenuItem = e.target.role === 'menuitem' || e.target.role === 'menuitemcheckbox' || e.target.role === 'menuitemradio';
278
- if (!isMenuItem || e.target.hasAttribute('first') || e.target.hasChildView) return;
279
- e.target.setAttribute('tabindex', '-1');
288
+ _onHideComplete() {
289
+ this.resetFocusables();
290
+ this.active = this.isActive();
280
291
  }
281
292
 
282
293
  _onKeyDown(e) {
@@ -304,7 +315,8 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
304
315
  }
305
316
 
306
317
  _onKeyPress(e) {
307
- if (this._items.indexOf(e.composedPath()[0]) === -1) return;
318
+ const currentItem = e.composedPath()[0];
319
+ if (this._items.indexOf(currentItem) === -1) return;
308
320
 
309
321
  if (e.keyCode === keyCodes.DOWN || e.keyCode === keyCodes.UP
310
322
  || e.keyCode === keyCodes.SPACE || e.keyCode === keyCodes.ENTER
@@ -314,6 +326,8 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
314
326
 
315
327
  e.stopPropagation();
316
328
 
329
+ currentItem.setAttribute('tabindex', '-1');
330
+
317
331
  const startsWith = function(item, value) {
318
332
  if (item.text && item.text.length > 0 && item.text.toLowerCase().substr(0, 1) === value) {
319
333
  return true;
@@ -361,6 +375,10 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
361
375
  this.focus();
362
376
  }
363
377
 
378
+ _onShowStart() {
379
+ this.active = this.isActive();
380
+ }
381
+
364
382
  _onViewResize(e) {
365
383
  if (!this.rootView) return;
366
384
 
@@ -372,10 +390,6 @@ class Menu extends PropertyRequiredMixin(ThemeMixin(HierarchicalViewMixin(LitEle
372
390
  this.dispatchEvent(new CustomEvent('d2l-menu-resize', eventDetails));
373
391
  }
374
392
 
375
- _onVisibilityChange() {
376
- this.active = this.isActive();
377
- }
378
-
379
393
  _tryGetNextFocusable(item) {
380
394
  const focusableItems = this._items.filter(this._isFocusable, this);
381
395
  if (!focusableItems || focusableItems.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.159.3",
3
+ "version": "3.159.5",
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",