@brightspace-ui/core 3.30.0 → 3.30.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  import { css, html, LitElement } from 'lit';
2
- import { findComposedAncestor, getNextAncestorSibling, getPreviousAncestorSibling, isComposedAncestor } from '../../helpers/dom.js';
3
- import { getComposedActiveElement, getFirstFocusableDescendant, getLastFocusableDescendant, getNextFocusable, getPreviousFocusable, isFocusable } from '../../helpers/focus.js';
2
+ import { findComposedAncestor, isComposedAncestor } from '../../helpers/dom.js';
3
+ import { getComposedActiveElement, getFirstFocusableDescendant, getFocusableDescendants, getLastFocusableDescendant, getNextFocusable, getPreviousFocusable } from '../../helpers/focus.js';
4
4
  import { isInteractiveDescendant } from '../../mixins/interactive/interactive-mixin.js';
5
5
  import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
6
6
 
@@ -220,7 +220,6 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
220
220
 
221
221
  firstUpdated() {
222
222
  this.addEventListener('keydown', this._onKeydown.bind(this));
223
- this.addEventListener('focusin', this._setFocusInfo.bind(this));
224
223
  }
225
224
 
226
225
  render() {
@@ -247,19 +246,18 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
247
246
  `;
248
247
  }
249
248
 
250
- _focusCellItem(num, itemNum) {
251
- const cell = this.shadowRoot && this.shadowRoot.querySelector(`[data-cell-num="${num}"]`);
249
+ _focusCellItem(focusInfo) {
250
+ const cell = this.shadowRoot?.querySelector(`[data-cell-num="${focusInfo.cellNum}"]`);
252
251
  if (!cell) return;
253
252
 
254
- const firstFocusable = getFirstFocusableDescendant(cell);
255
- if (!firstFocusable) return;
253
+ let focusable;
254
+ const focusables = getFocusableDescendants(cell, { deep: true, predicate: elem => !isInteractiveDescendant(elem) });
256
255
 
257
- if (itemNum === 1) {
258
- firstFocusable.focus();
259
- return firstFocusable;
260
- } else {
261
- return this._focusNextWithinCell(firstFocusable, itemNum);
262
- }
256
+ if (focusInfo.index <= focusables.length - 1) focusable = focusables[focusInfo.index];
257
+ else if (focusables.length > 0) focusable = focusables[focusables.length - 1];
258
+
259
+ if (focusable) focusable.focus();
260
+ return focusable;
263
261
  }
264
262
 
265
263
  _focusFirstCell() {
@@ -321,7 +319,7 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
321
319
  return focusable;
322
320
  }
323
321
 
324
- _focusNextRow(previous = false, num = 1) {
322
+ _focusNextRow(focusInfo, previous = false, num = 1) {
325
323
 
326
324
  const curListItem = findComposedAncestor(this, node => node.role === 'rowgroup');
327
325
  let listItem = curListItem;
@@ -335,7 +333,7 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
335
333
 
336
334
  if (!listItem) return;
337
335
  const listItemRow = listItem.shadowRoot.querySelector('[role="gridrow"]');
338
- const focusedCellItem = listItemRow._focusCellItem(this._cellNum, this._cellFocusedItem);
336
+ const focusedCellItem = listItemRow._focusCellItem(focusInfo);
339
337
 
340
338
  if (!focusedCellItem) {
341
339
  // could not focus on same cell in adjacent list-item so try general focus on item
@@ -351,51 +349,14 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
351
349
 
352
350
  }
353
351
 
354
- _focusNextWithinCell(node, num = 1) {
355
-
356
- if (!node || (node.assignedSlot && node.assignedSlot === this._getThisCell())) return null;
357
- let focusable = null;
358
- let siblingNum = 1;
359
- while (!focusable || siblingNum < num) {
360
- node = this._getNextSiblingInCell(node);
361
-
362
- if (!node) break;
363
- ++siblingNum;
364
-
365
- focusable = isFocusable(node, true) ? node : getFirstFocusableDescendant(node);
366
- if (isInteractiveDescendant(focusable)) focusable = null;
367
- }
368
-
369
- if (focusable) focusable.focus();
370
- return focusable;
352
+ _focusNextWithinRow(focusInfo, focusables) {
353
+ if (focusInfo.index === focusables.length - 1) this._focusNextCell(focusInfo.cellNum + 1);
354
+ else focusables[focusInfo.index + 1].focus();
371
355
  }
372
356
 
373
- _focusPreviousWithinCell(node) {
374
- if (!node || (node.assignedSlot && node.assignedSlot === this._getThisCell())) return null;
375
- let focusable = null;
376
- while (!focusable) {
377
- node = this._getPrevSiblingInCell(node);
378
- if (!node) break;
379
- focusable = isFocusable(node, true) ? node : getLastFocusableDescendant(node);
380
- }
381
- if (focusable) focusable.focus();
382
- return focusable;
383
- }
384
-
385
- _getFocusedItemPosition(node) {
386
- let position = 1;
387
- // walk the tree backwards until we hit the cell
388
- do {
389
- node = this._getPrevSiblingInCell(node);
390
- if (node) {
391
- const focusable = isFocusable(node, true) ? node : getLastFocusableDescendant(node);
392
- if (focusable) {
393
- ++position;
394
- node = focusable;
395
- }
396
- }
397
- } while (node);
398
- return position;
357
+ _focusPreviousWithinRow(focusInfo, focusables) {
358
+ if (focusInfo.index === 0) this._focusNextCell(focusInfo.cellNum - 1, false);
359
+ else focusables[focusInfo.index - 1].focus();
399
360
  }
400
361
 
401
362
  _getNextFlattenedListItem(listItem) {
@@ -430,15 +391,6 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
430
391
 
431
392
  }
432
393
 
433
- _getNextSiblingInCell(node) {
434
- const cell = findComposedAncestor(node, (parent) => parent.classList && parent.classList.contains('d2l-cell'));
435
- if (!cell || cell.name === node.slot) return null;
436
- if (node.nextElementSibling) return node.nextElementSibling;
437
-
438
- const sibling = getNextAncestorSibling(node);
439
- return isComposedAncestor(cell, sibling) ? sibling : null;
440
- }
441
-
442
394
  _getPreviousFlattenedListItem(listItem) {
443
395
 
444
396
  let previousElement = listItem.previousElementSibling;
@@ -476,72 +428,58 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
476
428
 
477
429
  }
478
430
 
479
- _getPrevSiblingInCell(node) {
480
- const cell = findComposedAncestor(node, (parent) => parent.classList && parent.classList.contains('d2l-cell'));
481
- if (!cell || cell.name === node.slot) return null;
482
- if (node.previousElementSibling) return node.previousElementSibling;
483
-
484
- const sibling = getPreviousAncestorSibling(node);
485
- return isComposedAncestor(cell, sibling) ? sibling : null;
486
- }
487
-
488
- _getThisCell() {
489
- return this.shadowRoot &&
490
- this.shadowRoot.querySelector(`.d2l-cell[data-cell-num="${this._cellNum}"]`);
491
- }
492
-
493
431
  _isContainedInSameRootList(item, node) {
494
432
  const rootList = item?.getRootList?.(item);
495
433
  return isComposedAncestor(rootList, node);
496
434
  }
497
435
 
498
- _onKeydown(event) {
436
+ _onKeydown(e) {
499
437
  if (!this.gridActive) return;
500
- let node = null;
501
438
  let preventDefault = true;
502
- switch (event.keyCode) {
439
+
440
+ const node = getComposedActiveElement();
441
+ const cell = findComposedAncestor(node, parent => parent.classList?.contains('d2l-cell'));
442
+ if (!cell) return;
443
+
444
+ const focusables = getFocusableDescendants(cell, { deep: true, predicate: elem => !isInteractiveDescendant(elem) });
445
+ const focusInfo = {
446
+ cellNum: parseInt(cell.getAttribute('data-cell-num')),
447
+ index: focusables.findIndex(elem => elem === node)
448
+ };
449
+
450
+ switch (e.keyCode) {
503
451
  case keyCodes.RIGHT:
504
- node = getComposedActiveElement();
505
452
  if (this.dir === 'rtl') {
506
- if (!this._focusPreviousWithinCell(node)) {
507
- this._focusNextCell(this._cellNum - 1, false);
508
- }
453
+ this._focusPreviousWithinRow(focusInfo, focusables);
509
454
  } else {
510
- if (!this._focusNextWithinCell(node)) {
511
- this._focusNextCell(this._cellNum + 1);
512
- }
455
+ this._focusNextWithinRow(focusInfo, focusables);
513
456
  }
514
457
  break;
515
458
  case keyCodes.LEFT:
516
- node = getComposedActiveElement();
517
459
  if (this.dir === 'rtl') {
518
- if (!this._focusNextWithinCell(node)) {
519
- this._focusNextCell(this._cellNum + 1);
520
- }
460
+ this._focusNextWithinRow(focusInfo, focusables);
521
461
  } else {
522
- if (!this._focusPreviousWithinCell(node)) {
523
- this._focusNextCell(this._cellNum - 1, false);
524
- }
462
+ this._focusPreviousWithinRow(focusInfo, focusables);
525
463
  }
526
464
  break;
527
465
  case keyCodes.UP:
528
466
  // move to above row, focus same item within the cell
529
- this._focusNextRow(true);
467
+ this._focusNextRow(focusInfo, true);
530
468
  break;
531
469
  case keyCodes.DOWN:
532
470
  // move to below row, focus same item within the cell
533
- this._focusNextRow();
471
+ this._focusNextRow(focusInfo);
534
472
  break;
535
473
  case keyCodes.HOME:
536
474
  if (this.dir === 'rtl') {
537
- if (event.ctrlKey) {
475
+ if (e.ctrlKey) {
538
476
  this._focusFirstRow();
539
477
  } else {
540
478
  // focus last cell
541
479
  this._focusLastCell();
542
480
  }
543
481
  } else {
544
- if (event.ctrlKey) {
482
+ if (e.ctrlKey) {
545
483
  // focus first item of first row
546
484
  this._focusFirstRow();
547
485
  } else {
@@ -552,7 +490,7 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
552
490
  break;
553
491
  case keyCodes.END:
554
492
  if (this.dir === 'rtl') {
555
- if (event.ctrlKey) {
493
+ if (e.ctrlKey) {
556
494
  // focus first item of last row
557
495
  this._focusLastRow();
558
496
  } else {
@@ -560,7 +498,7 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
560
498
  this._focusFirstCell();
561
499
  }
562
500
  } else {
563
- if (event.ctrlKey) {
501
+ if (e.ctrlKey) {
564
502
  // focus last item of last row
565
503
  this._focusLastRow();
566
504
  } else {
@@ -571,31 +509,21 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
571
509
  break;
572
510
  case keyCodes.PAGEUP:
573
511
  // focus five rows up
574
- this._focusNextRow(true, 5);
512
+ this._focusNextRow(focusInfo, true, 5);
575
513
  break;
576
514
  case keyCodes.PAGEDOWN:
577
515
  // focus five rows down
578
- this._focusNextRow(false, 5);
516
+ this._focusNextRow(focusInfo, false, 5);
579
517
  break;
580
518
  default:
581
519
  preventDefault = false;
582
520
  }
521
+
583
522
  if (preventDefault) {
584
- event.preventDefault();
585
- event.stopPropagation();
523
+ e.preventDefault();
524
+ e.stopPropagation();
586
525
  }
587
- }
588
-
589
- _setFocusInfo(e) {
590
- e.stopPropagation();
591
-
592
- if (!this.gridActive) return;
593
- const slot = (e.path || e.composedPath()).find(node =>
594
- node.nodeName === 'SLOT' && node.classList.contains('d2l-cell'));
595
- if (!slot) return;
596
-
597
- this._cellNum = parseInt(slot.getAttribute('data-cell-num'));
598
- this._cellFocusedItem = this._getFocusedItemPosition(e.target);
526
+ return;
599
527
  }
600
528
 
601
529
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.30.0",
3
+ "version": "3.30.1",
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",