mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 08:13:42 +00:00
[CL-800] delete a11y-grid, a11y-row, a11y-cell directives (#15709)
* delete a11y-grid,-row,-cell directives * remove missed references * remove missed references
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { ContentChild, Directive, ElementRef, HostBinding } from "@angular/core";
|
||||
|
||||
import { FocusableElement } from "../shared/focusable-element";
|
||||
|
||||
@Directive({
|
||||
selector: "bitA11yCell",
|
||||
providers: [{ provide: FocusableElement, useExisting: A11yCellDirective }],
|
||||
})
|
||||
export class A11yCellDirective implements FocusableElement {
|
||||
@HostBinding("attr.role")
|
||||
role: "gridcell" | null;
|
||||
|
||||
@ContentChild(FocusableElement)
|
||||
private focusableChild: FocusableElement;
|
||||
|
||||
getFocusTarget() {
|
||||
let focusTarget: HTMLElement;
|
||||
if (this.focusableChild) {
|
||||
focusTarget = this.focusableChild.getFocusTarget();
|
||||
} else {
|
||||
focusTarget = this.elementRef.nativeElement.querySelector("button, a");
|
||||
}
|
||||
|
||||
if (!focusTarget) {
|
||||
return this.elementRef.nativeElement;
|
||||
}
|
||||
|
||||
return focusTarget;
|
||||
}
|
||||
|
||||
constructor(private elementRef: ElementRef<HTMLElement>) {}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import {
|
||||
AfterViewInit,
|
||||
ContentChildren,
|
||||
Directive,
|
||||
HostBinding,
|
||||
HostListener,
|
||||
Input,
|
||||
QueryList,
|
||||
} from "@angular/core";
|
||||
|
||||
import type { A11yCellDirective } from "./a11y-cell.directive";
|
||||
import { A11yRowDirective } from "./a11y-row.directive";
|
||||
|
||||
@Directive({
|
||||
selector: "bitA11yGrid",
|
||||
})
|
||||
export class A11yGridDirective implements AfterViewInit {
|
||||
@HostBinding("attr.role")
|
||||
role = "grid";
|
||||
|
||||
@ContentChildren(A11yRowDirective)
|
||||
rows: QueryList<A11yRowDirective>;
|
||||
|
||||
/** The number of pages to navigate on `PageUp` and `PageDown` */
|
||||
@Input() pageSize = 5;
|
||||
|
||||
private grid: A11yCellDirective[][];
|
||||
|
||||
/** The row that currently has focus */
|
||||
private activeRow = 0;
|
||||
|
||||
/** The cell that currently has focus */
|
||||
private activeCol = 0;
|
||||
|
||||
@HostListener("keydown", ["$event"])
|
||||
onKeyDown(event: KeyboardEvent) {
|
||||
switch (event.code) {
|
||||
case "ArrowUp":
|
||||
this.updateCellFocusByDelta(-1, 0);
|
||||
break;
|
||||
case "ArrowRight":
|
||||
this.updateCellFocusByDelta(0, 1);
|
||||
break;
|
||||
case "ArrowDown":
|
||||
this.updateCellFocusByDelta(1, 0);
|
||||
break;
|
||||
case "ArrowLeft":
|
||||
this.updateCellFocusByDelta(0, -1);
|
||||
break;
|
||||
case "Home":
|
||||
this.updateCellFocusByDelta(-this.activeRow, -this.activeCol);
|
||||
break;
|
||||
case "End":
|
||||
this.updateCellFocusByDelta(this.grid.length, this.grid[this.grid.length - 1].length);
|
||||
break;
|
||||
case "PageUp":
|
||||
this.updateCellFocusByDelta(-this.pageSize, 0);
|
||||
break;
|
||||
case "PageDown":
|
||||
this.updateCellFocusByDelta(this.pageSize, 0);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/** Prevent default scrolling behavior */
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.initializeGrid();
|
||||
}
|
||||
|
||||
private initializeGrid(): void {
|
||||
try {
|
||||
this.grid = this.rows.map((listItem) => {
|
||||
listItem.role = "row";
|
||||
return [...listItem.cells];
|
||||
});
|
||||
this.grid.flat().forEach((cell) => {
|
||||
cell.role = "gridcell";
|
||||
cell.getFocusTarget().tabIndex = -1;
|
||||
});
|
||||
|
||||
this.getActiveCellContent().tabIndex = 0;
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Unable to initialize grid");
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the focusable content of the active cell */
|
||||
private getActiveCellContent(): HTMLElement {
|
||||
return this.grid[this.activeRow][this.activeCol].getFocusTarget();
|
||||
}
|
||||
|
||||
/** Move focus via a delta against the currently active gridcell */
|
||||
private updateCellFocusByDelta(rowDelta: number, colDelta: number) {
|
||||
const prevActive = this.getActiveCellContent();
|
||||
|
||||
this.activeCol += colDelta;
|
||||
this.activeRow += rowDelta;
|
||||
|
||||
// Row upper bound
|
||||
if (this.activeRow >= this.grid.length) {
|
||||
this.activeRow = this.grid.length - 1;
|
||||
}
|
||||
|
||||
// Row lower bound
|
||||
if (this.activeRow < 0) {
|
||||
this.activeRow = 0;
|
||||
}
|
||||
|
||||
// Column upper bound
|
||||
if (this.activeCol >= this.grid[this.activeRow].length) {
|
||||
if (this.activeRow < this.grid.length - 1) {
|
||||
// Wrap to next row on right arrow
|
||||
this.activeCol = 0;
|
||||
this.activeRow += 1;
|
||||
} else {
|
||||
this.activeCol = this.grid[this.activeRow].length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Column lower bound
|
||||
if (this.activeCol < 0) {
|
||||
if (this.activeRow > 0) {
|
||||
// Wrap to prev row on left arrow
|
||||
this.activeRow -= 1;
|
||||
this.activeCol = this.grid[this.activeRow].length - 1;
|
||||
} else {
|
||||
this.activeCol = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const nextActive = this.getActiveCellContent();
|
||||
nextActive.tabIndex = 0;
|
||||
nextActive.focus();
|
||||
|
||||
if (nextActive !== prevActive) {
|
||||
prevActive.tabIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import {
|
||||
AfterViewInit,
|
||||
ContentChildren,
|
||||
Directive,
|
||||
HostBinding,
|
||||
QueryList,
|
||||
ViewChildren,
|
||||
} from "@angular/core";
|
||||
|
||||
import { A11yCellDirective } from "./a11y-cell.directive";
|
||||
|
||||
@Directive({
|
||||
selector: "bitA11yRow",
|
||||
})
|
||||
export class A11yRowDirective implements AfterViewInit {
|
||||
@HostBinding("attr.role")
|
||||
role: "row" | null;
|
||||
|
||||
cells: A11yCellDirective[];
|
||||
|
||||
@ViewChildren(A11yCellDirective)
|
||||
private viewCells: QueryList<A11yCellDirective>;
|
||||
|
||||
@ContentChildren(A11yCellDirective)
|
||||
private contentCells: QueryList<A11yCellDirective>;
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.cells = [...this.viewCells, ...this.contentCells];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user