Skip to content

Commit 358d5aa

Browse files
committed
refactor(material/tree): docs updates and rename variables
Make miscelaneous fixes to documentation. Rename variables. Responding to PR feedback. * remove comment about API contract of CdkTreeNodeToggle * rename CdkTree#_groups to CdkTree#_ariaSets * move documentation about default key manager configuration from TreeKeyManagerStrategy interface to TreeKeyManager class. * add JSDoc style comments for NoopTreeKeyManager
1 parent 5356d69 commit 358d5aa

File tree

6 files changed

+69
-43
lines changed

6 files changed

+69
-43
lines changed

src/cdk/a11y/key-manager/noop-tree-key-manager.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ import {
2222
/**
2323
* @docs-private
2424
*
25+
* Opt-out of Tree of key manager behavior.
26+
*
27+
* When provided, Tree has same focus management behavior as before TreeKeyManager was introduced.
28+
* - Tree does not respond to keyboard interaction
29+
* - Tree node allows tabindex to be set by Input binding
30+
* - Tree node allows tabindex to be set by attribute binding
31+
*
2532
* @deprecated NoopTreeKeyManager deprecated. Use TreeKeyManager or inject a
2633
* TreeKeyManagerStrategy instead. To be removed in a future version.
2734
*
@@ -58,6 +65,13 @@ export class NoopTreeKeyManager<T extends TreeKeyManagerItem> implements TreeKey
5865
/**
5966
* @docs-private
6067
*
68+
* Opt-out of Tree of key manager behavior.
69+
*
70+
* When provided, Tree has same focus management behavior as before TreeKeyManager was introduced.
71+
* - Tree does not respond to keyboard interaction
72+
* - Tree node allows tabindex to be set by Input binding
73+
* - Tree node allows tabindex to be set by attribute binding
74+
*
6175
* @deprecated NoopTreeKeyManager deprecated. Use TreeKeyManager or inject a
6276
* TreeKeyManagerStrategy instead. To be removed in a future version.
6377
*
@@ -72,6 +86,13 @@ export function NOOP_TREE_KEY_MANAGER_FACTORY<
7286
/**
7387
* @docs-private
7488
*
89+
* Opt-out of Tree of key manager behavior.
90+
*
91+
* When provided, Tree has same focus management behavior as before TreeKeyManager was introduced.
92+
* - Tree does not respond to keyboard interaction
93+
* - Tree node allows tabindex to be set by Input binding
94+
* - Tree node allows tabindex to be set by attribute binding
95+
*
7596
* @deprecated NoopTreeKeyManager deprecated. Use TreeKeyManager or inject a
7697
* TreeKeyManagerStrategy instead. To be removed in a future version.
7798
*

src/cdk/a11y/key-manager/tree-key-manager-strategy.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,21 +52,20 @@ export interface TreeKeyManagerItem {
5252
export interface TreeKeyManagerOptions<T extends TreeKeyManagerItem> {
5353
/**
5454
* If true, then the key manager will call `activate` in addition to calling `focus` when a
55-
* particular item is focused. By default, this is false.
55+
* particular item is focused.
5656
*/
57-
activationFollowsFocus?: boolean;
57+
shouldActivationFollowFocus?: boolean;
5858

5959
/**
6060
* The direction in which the tree items are laid out horizontally. This influences which key
61-
* will be interpreted as expand or collapse. Defaults to 'ltr'.
61+
* will be interpreted as expand or collapse.
6262
*/
6363
horizontalOrientation?: 'rtl' | 'ltr';
6464

6565
/**
66-
* Sets the predicate function that determines which items should be skipped by the tree key
67-
* manager. By default, disabled items are skipped.
66+
* If provided, navigation "skips" over items that pass the given predicate.
6867
*
69-
* If the item is to be skipped, this function should return false.
68+
* If the item is to be skipped, predicate function should return false.
7069
*/
7170
skipPredicate?: (item: T) => boolean;
7271

src/cdk/a11y/key-manager/tree-key-manager.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ function coerceObservable<T>(data: T | Observable<T>): Observable<T> {
4848
export class TreeKeyManager<T extends TreeKeyManagerItem> implements TreeKeyManagerStrategy<T> {
4949
private _activeItemIndex = -1;
5050
private _activeItem: T | null = null;
51-
private _activationFollowsFocus = false;
52-
private _horizontal: 'ltr' | 'rtl' = 'ltr';
51+
private _shouldActivationFollowFocus = false;
52+
private _horizontalOrientation: 'ltr' | 'rtl' = 'ltr';
5353
private readonly _letterKeyStream = new Subject<string>();
5454
private _typeaheadSubscription = Subscription.EMPTY;
5555

@@ -92,6 +92,14 @@ export class TreeKeyManager<T extends TreeKeyManagerItem> implements TreeKeyMana
9292
this._hasInitialFocused = true;
9393
}
9494

95+
/**
96+
*
97+
* @param items List of TreeKeyManager options. Can be synchronous or asynchronous.
98+
* @param config Optional configuration options. By default, use 'ltr' horizontal orientation. By
99+
* default, do not skip any nodes. By default, key manager only calls `focus` method when items
100+
* are focused and does not call `activate`. If `typeaheadDefaultInterval` is `true`, use a
101+
* default interval of 200ms.
102+
*/
95103
constructor(items: Observable<T[]> | QueryList<T> | T[], config: TreeKeyManagerOptions<T>) {
96104
// We allow for the items to be an array or Observable because, in some cases, the consumer may
97105
// not have access to a QueryList of the items they want to manage (e.g. when the
@@ -114,11 +122,11 @@ export class TreeKeyManager<T extends TreeKeyManagerItem> implements TreeKeyMana
114122
this._initialFocus();
115123
}
116124

117-
if (typeof config.activationFollowsFocus === 'boolean') {
118-
this._activationFollowsFocus = config.activationFollowsFocus;
125+
if (typeof config.shouldActivationFollowFocus === 'boolean') {
126+
this._shouldActivationFollowFocus = config.shouldActivationFollowFocus;
119127
}
120128
if (config.horizontalOrientation) {
121-
this._horizontal = config.horizontalOrientation;
129+
this._horizontalOrientation = config.horizontalOrientation;
122130
}
123131
if (config.skipPredicate) {
124132
this._skipPredicateFn = config.skipPredicate;
@@ -160,11 +168,15 @@ export class TreeKeyManager<T extends TreeKeyManagerItem> implements TreeKeyMana
160168
break;
161169

162170
case RIGHT_ARROW:
163-
this._horizontal === 'rtl' ? this._collapseCurrentItem() : this._expandCurrentItem();
171+
this._horizontalOrientation === 'rtl'
172+
? this._collapseCurrentItem()
173+
: this._expandCurrentItem();
164174
break;
165175

166176
case LEFT_ARROW:
167-
this._horizontal === 'rtl' ? this._expandCurrentItem() : this._collapseCurrentItem();
177+
this._horizontalOrientation === 'rtl'
178+
? this._expandCurrentItem()
179+
: this._collapseCurrentItem();
168180
break;
169181

170182
case HOME:
@@ -273,11 +285,10 @@ export class TreeKeyManager<T extends TreeKeyManagerItem> implements TreeKeyMana
273285
previousActiveItem?.unfocus();
274286

275287
if (options.emitChangeEvent) {
276-
// Emit to `change` stream as required by TreeKeyManagerStrategy interface.
277288
this.change.next(this._activeItem);
278289
}
279290

280-
if (this._activationFollowsFocus) {
291+
if (this._shouldActivationFollowFocus) {
281292
this._activateCurrentItem();
282293
}
283294
}

src/cdk/tree/toggle.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ import {CdkTree, CdkTreeNode} from './tree';
1212

1313
/**
1414
* Node toggle to expand and collapse the node.
15-
*
16-
* CdkTreeNodeToggle is intended only to be used on native button elements, elements with button role,
17-
* or elements with treeitem role.
1815
*/
1916
@Directive({
2017
selector: '[cdkTreeNodeToggle]',

src/cdk/tree/tree.ts

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,14 @@ export class CdkTree<T, K = T>
132132
private _parents: Map<K, T | null> = new Map<K, T | null>();
133133

134134
/**
135-
* The internal node groupings for each node; we use this to determine where
136-
* a particular node is within each group. This allows us to compute the
137-
* correct aria attribute values.
135+
* Nodes grouped into each set, which is a list of nodes displayed together in the DOM.
138136
*
139-
* The structure of this is that:
140-
* - the outer index is the level
141-
* - the inner index is the parent node for this particular group. If there is no parent node, we
142-
* use `null`.
137+
* Lookup key is the parent of a set. Root nodes have key of null.
138+
*
139+
* Values is a 'set' of tree nodes. Each tree node maps to a treeitem element. Sets are in the
140+
* order that it is rendered. Each set maps directly to aria-posinset and aria-setsize attributes.
143141
*/
144-
private _groups: Map<K | null, T[]> = new Map<K | null, T[]>();
142+
private _ariaSets: Map<K | null, T[]> = new Map<K | null, T[]>();
145143

146144
/**
147145
* Provides a stream containing the latest data array to render. Influenced by the tree's
@@ -498,10 +496,10 @@ export class CdkTree<T, K = T>
498496
this.insertNode(data[currentIndex!], currentIndex!, viewContainer, parentData);
499497
} else if (currentIndex == null) {
500498
viewContainer.remove(adjustedPreviousIndex!);
501-
const group = this._getNodeGroup(item.item);
499+
const set = this._getAriaSet(item.item);
502500
const key = this._getExpansionKey(item.item);
503-
group.splice(
504-
group.findIndex(groupItem => this._getExpansionKey(groupItem) === key),
501+
set.splice(
502+
set.findIndex(groupItem => this._getExpansionKey(groupItem) === key),
505503
1,
506504
);
507505
} else {
@@ -782,8 +780,8 @@ export class CdkTree<T, K = T>
782780
* This is intended to be used for `aria-setsize`.
783781
*/
784782
_getSetSize(dataNode: T) {
785-
const group = this._getNodeGroup(dataNode);
786-
return group.length;
783+
const set = this._getAriaSet(dataNode);
784+
return set.length;
787785
}
788786

789787
/**
@@ -792,9 +790,9 @@ export class CdkTree<T, K = T>
792790
* This is intended to be used for `aria-posinset`.
793791
*/
794792
_getPositionInSet(dataNode: T) {
795-
const group = this._getNodeGroup(dataNode);
793+
const set = this._getAriaSet(dataNode);
796794
const key = this._getExpansionKey(dataNode);
797-
return group.findIndex(node => this._getExpansionKey(node) === key) + 1;
795+
return set.findIndex(node => this._getExpansionKey(node) === key) + 1;
798796
}
799797

800798
/** Given a CdkTreeNode, gets the node that renders that node's parent's data. */
@@ -900,12 +898,12 @@ export class CdkTree<T, K = T>
900898
return this.expansionKey?.(dataNode) ?? (dataNode as unknown as K);
901899
}
902900

903-
private _getNodeGroup(node: T) {
901+
private _getAriaSet(node: T) {
904902
const key = this._getExpansionKey(node);
905903
const parent = this._parents.get(key);
906904
const parentKey = parent ? this._getExpansionKey(parent) : null;
907-
const group = this._groups.get(parentKey);
908-
return group ?? [node];
905+
const set = this._ariaSets.get(parentKey);
906+
return set ?? [node];
909907
}
910908

911909
/**
@@ -961,7 +959,7 @@ export class CdkTree<T, K = T>
961959
children.pipe(
962960
take(1),
963961
tap(childNodes => {
964-
this._groups.set(parentKey, [...(childNodes ?? [])]);
962+
this._ariaSets.set(parentKey, [...(childNodes ?? [])]);
965963
for (const child of childNodes ?? []) {
966964
const childKey = this._getExpansionKey(child);
967965
this._parents.set(childKey, node);
@@ -1004,7 +1002,7 @@ export class CdkTree<T, K = T>
10041002
// nested.
10051003
if (this.childrenAccessor && nodeType === 'flat') {
10061004
// This flattens children into a single array.
1007-
this._groups.set(null, [...nodes]);
1005+
this._ariaSets.set(null, [...nodes]);
10081006
return this._flattenNestedNodesWithExpansion(nodes).pipe(
10091007
map(flattenedNodes => ({
10101008
renderNodes: flattenedNodes,
@@ -1037,7 +1035,7 @@ export class CdkTree<T, K = T>
10371035
} else {
10381036
// For nested nodes, we still need to perform the node flattening in order
10391037
// to maintain our caches for various tree operations.
1040-
this._groups.set(null, [...nodes]);
1038+
this._ariaSets.set(null, [...nodes]);
10411039
return this._flattenNestedNodesWithExpansion(nodes).pipe(
10421040
map(flattenedNodes => ({
10431041
renderNodes: nodes,
@@ -1063,7 +1061,7 @@ export class CdkTree<T, K = T>
10631061
}
10641062

10651063
this._parents.clear();
1066-
this._groups.clear();
1064+
this._ariaSets.clear();
10671065

10681066
for (let index = 0; index < flattenedNodes.length; index++) {
10691067
const dataNode = flattenedNodes[index];
@@ -1073,9 +1071,9 @@ export class CdkTree<T, K = T>
10731071
this._parents.set(key, parent);
10741072
const parentKey = parent ? this._getExpansionKey(parent) : null;
10751073

1076-
const group = this._groups.get(parentKey) ?? [];
1074+
const group = this._ariaSets.get(parentKey) ?? [];
10771075
group.splice(index, 0, dataNode);
1078-
this._groups.set(parentKey, group);
1076+
this._ariaSets.set(parentKey, group);
10791077
}
10801078
}
10811079
}

tools/public_api_guard/cdk/a11y.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,8 @@ export interface TreeKeyManagerItem {
502502

503503
// @public
504504
export interface TreeKeyManagerOptions<T extends TreeKeyManagerItem> {
505-
activationFollowsFocus?: boolean;
506505
horizontalOrientation?: 'rtl' | 'ltr';
506+
shouldActivationFollowFocus?: boolean;
507507
skipPredicate?: (item: T) => boolean;
508508
trackBy?: (treeItem: T) => unknown;
509509
typeAheadDebounceInterval?: true | number;

0 commit comments

Comments
 (0)