-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
action-nav.ts
73 lines (63 loc) · 2.01 KB
/
action-nav.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { css, customElement, FASTElement, html, observable, slotted } from '@microsoft/fast-element';
import '../codicon';
const template = html<ActionNav>`<template role="navigation"><slot ${slotted('actionNodes')}></slot></template>`;
const styles = css`
:host {
display: flex;
align-items: center;
user-select: none;
}
`;
@customElement({ name: 'action-nav', template: template, styles: styles })
export class ActionNav extends FASTElement {
@observable
actionNodes?: HTMLElement[];
actionNodesDisposer?: () => void;
actionNodesChanged(_oldValue?: HTMLElement[], newValue?: HTMLElement[]) {
this.actionNodesDisposer?.();
if (!newValue?.length) {
return;
}
const handleKeydown = this.handleKeydown.bind(this);
const nodeEvents = newValue
?.filter(node => node.nodeType === 1)
.map((node, i) => {
node.setAttribute('tabindex', i === 0 ? '0' : '-1');
node.addEventListener('keydown', handleKeydown, false);
return {
dispose: () => {
node?.removeEventListener('keydown', handleKeydown, false);
},
};
});
this.actionNodesDisposer = () => {
nodeEvents?.forEach(({ dispose }) => dispose());
};
}
override disconnectedCallback() {
this.actionNodesDisposer?.();
}
handleKeydown(e: KeyboardEvent) {
if (!e.target || this.actionNodes == null || this.actionNodes.length < 2) return;
const target = e.target as HTMLElement;
let $next: HTMLElement | null = null;
if (e.key === 'ArrowLeft') {
$next = target.previousElementSibling as HTMLElement;
if ($next == null) {
const filteredNodes = this.actionNodes.filter(node => node.nodeType === 1);
$next = filteredNodes[filteredNodes.length - 1] ?? null;
}
} else if (e.key === 'ArrowRight') {
$next = target.nextElementSibling as HTMLElement;
if ($next == null) {
$next = this.actionNodes.find(node => node.nodeType === 1) ?? null;
}
}
if ($next == null || $next === target) {
return;
}
target.setAttribute('tabindex', '-1');
$next.setAttribute('tabindex', '0');
$next.focus();
}
}