@brightspace-ui/core 3.30.0 → 3.30.1
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.
@@ -1,6 +1,6 @@
|
|
1
1
|
import { css, html, LitElement } from 'lit';
|
2
|
-
import { findComposedAncestor,
|
3
|
-
import { getComposedActiveElement, getFirstFocusableDescendant, getLastFocusableDescendant, getNextFocusable, getPreviousFocusable
|
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(
|
251
|
-
const cell = this.shadowRoot
|
249
|
+
_focusCellItem(focusInfo) {
|
250
|
+
const cell = this.shadowRoot?.querySelector(`[data-cell-num="${focusInfo.cellNum}"]`);
|
252
251
|
if (!cell) return;
|
253
252
|
|
254
|
-
|
255
|
-
|
253
|
+
let focusable;
|
254
|
+
const focusables = getFocusableDescendants(cell, { deep: true, predicate: elem => !isInteractiveDescendant(elem) });
|
256
255
|
|
257
|
-
if (
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
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(
|
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
|
-
|
355
|
-
|
356
|
-
|
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
|
-
|
374
|
-
if (
|
375
|
-
|
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(
|
436
|
+
_onKeydown(e) {
|
499
437
|
if (!this.gridActive) return;
|
500
|
-
let node = null;
|
501
438
|
let preventDefault = true;
|
502
|
-
|
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
|
-
|
507
|
-
this._focusNextCell(this._cellNum - 1, false);
|
508
|
-
}
|
453
|
+
this._focusPreviousWithinRow(focusInfo, focusables);
|
509
454
|
} else {
|
510
|
-
|
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
|
-
|
519
|
-
this._focusNextCell(this._cellNum + 1);
|
520
|
-
}
|
460
|
+
this._focusNextWithinRow(focusInfo, focusables);
|
521
461
|
} else {
|
522
|
-
|
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 (
|
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 (
|
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 (
|
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 (
|
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
|
-
|
585
|
-
|
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.
|
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",
|