Skip to content

Commit

Permalink
fix(material/tree): Fix misc PR comments.
Browse files Browse the repository at this point in the history
Fix miscellaneous PR comments. Take a first pass to fix comments that
are easiest to fix. This commit message will be squashed away when
merging.
 * move type definitions in tree-key-manager.ts to a new file,
   tree-key-manager-strategy.ts
 * remove unnecessary comment
 * fix JSDoc comment syntax
 * remove isNotNullish
 * consolidate event handling code in CdkTreeNodeToggle
 * remove unnecessary type coerscion
 * simply logic for detecting TreeControlMissingError and MultipleTreeControlsError
 * adopt Input transform
 * remove unnecessary nesting in _updateActiveItemIndex
  • Loading branch information
zarend committed Nov 10, 2023
1 parent 9310d0f commit 104c403
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 237 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,30 @@
*/

import {Subject} from 'rxjs';
import {TREE_KEY_MANAGER} from './tree-key-manager';
import {
TREE_KEY_MANAGER,
TreeKeyManagerFactory,
TreeKeyManagerItem,
TreeKeyManagerStrategy,
} from './tree-key-manager';
} from './tree-key-manager-strategy';

// NoopTreeKeyManager is a "noop" implementation of TreeKeyMangerStrategy. Methods are noops. Does
// not emit to streams.
//
// Used for applications built before TreeKeyManager to opt-out of TreeKeyManager and revert to
// legacy behavior.
/**
* @docs-private
*
* @deprecated LegacyTreeKeyManager deprecated. Use TreeKeyManager or inject a
* @deprecated NoopTreeKeyManager deprecated. Use TreeKeyManager or inject a
* TreeKeyManagerStrategy instead. To be removed in a future version.
*
* @breaking-change 19.0.0
*/
// LegacyTreeKeyManager is a "noop" implementation of TreeKeyMangerStrategy. Methods are noops. Does
// not emit to streams.
//
// Used for applications built before TreeKeyManager to opt-out of TreeKeyManager and revert to
// legacy behavior.
export class LegacyTreeKeyManager<T extends TreeKeyManagerItem>
implements TreeKeyManagerStrategy<T>
{
readonly _isLegacyTreeKeyManager = true;
export class NoopTreeKeyManager<T extends TreeKeyManagerItem> implements TreeKeyManagerStrategy<T> {
readonly _isNoopTreeKeyManager = true;

// Provide change as required by TreeKeyManagerStrategy. LegacyTreeKeyManager is a "noop"
// Provide change as required by TreeKeyManagerStrategy. NoopTreeKeyManager is a "noop"
// implementation that does not emit to streams.
readonly change = new Subject<T | null>();

Expand All @@ -41,13 +39,13 @@ export class LegacyTreeKeyManager<T extends TreeKeyManagerItem>
}

getActiveItemIndex() {
// Always return null. LegacyTreeKeyManager is a "noop" implementation that does not maintain
// Always return null. NoopTreeKeyManager is a "noop" implementation that does not maintain
// the active item.
return null;
}

getActiveItem() {
// Always return null. LegacyTreeKeyManager is a "noop" implementation that does not maintain
// Always return null. NoopTreeKeyManager is a "noop" implementation that does not maintain
// the active item.
return null;
}
Expand All @@ -64,26 +62,26 @@ export class LegacyTreeKeyManager<T extends TreeKeyManagerItem>
/**
* @docs-private
*
* @deprecated LegacyTreeKeyManager deprecated. Use TreeKeyManager or inject a
* @deprecated NoopTreeKeyManager deprecated. Use TreeKeyManager or inject a
* TreeKeyManagerStrategy instead. To be removed in a future version.
*
* @breaking-change 19.0.0
*/
export function LEGACY_TREE_KEY_MANAGER_FACTORY<
export function NOOP_TREE_KEY_MANAGER_FACTORY<
T extends TreeKeyManagerItem,
>(): TreeKeyManagerFactory<T> {
return () => new LegacyTreeKeyManager<T>();
return () => new NoopTreeKeyManager<T>();
}

/**
* @docs-private
*
* @deprecated LegacyTreeKeyManager deprecated. Use TreeKeyManager or inject a
* @deprecated NoopTreeKeyManager deprecated. Use TreeKeyManager or inject a
* TreeKeyManagerStrategy instead. To be removed in a future version.
*
* @breaking-change 19.0.0
*/
export const LEGACY_TREE_KEY_MANAGER_FACTORY_PROVIDER = {
export const NOOP_TREE_KEY_MANAGER_FACTORY_PROVIDER = {
provide: TREE_KEY_MANAGER,
useFactory: LEGACY_TREE_KEY_MANAGER_FACTORY,
useFactory: NOOP_TREE_KEY_MANAGER_FACTORY,
};
135 changes: 135 additions & 0 deletions src/cdk/a11y/key-manager/tree-key-manager-strategy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {QueryList} from '@angular/core';
import {Observable, Subject} from 'rxjs';

/** Represents an item within a tree that can be passed to a TreeKeyManager. */
export interface TreeKeyManagerItem {
/** Whether the item is disabled. */
isDisabled?: (() => boolean) | boolean;

/** The user-facing label for this item. */
getLabel?(): string;

/** Perform the main action (i.e. selection) for this item. */
activate(): void;

/** Retrieves the parent for this item. This is `null` if there is no parent. */
getParent(): TreeKeyManagerItem | null;

/** Retrieves the children for this item. */
getChildren(): TreeKeyManagerItem[] | Observable<TreeKeyManagerItem[]>;

/** Determines if the item is currently expanded. */
isExpanded: (() => boolean) | boolean;

/** Collapses the item, hiding its children. */
collapse(): void;

/** Expands the item, showing its children. */
expand(): void;

/**
* Focuses the item. This should provide some indication to the user that this item is focused.
*/
focus(): void;
}

/**
* Configuration for the TreeKeyManager.
*/
export interface TreeKeyManagerOptions<T extends TreeKeyManagerItem> {
/**
* If true, then the key manager will call `activate` in addition to calling `focus` when a
* particular item is focused. By default, this is false.
*/
activationFollowsFocus?: boolean;

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

/**
* Sets the predicate function that determines which items should be skipped by the tree key
* manager. By default, disabled items are skipped.
*
* If the item is to be skipped, this function should return false.
*/
skipPredicate?: (item: T) => boolean;

/**
* If provided, determines how the key manager determines if two items are equivalent.
*
* It should provide a unique key for each unique tree item. If two tree items are equivalent,
* then this function should return the same value.
*/
trackBy?: (treeItem: T) => unknown;

/**
* If a value is provided, enables typeahead mode, which allows users to set the active item
* by typing the visible label of the item.
*
* If a number is provided, this will be the time to wait after the last keystroke before
* setting the active item. If `true` is provided, the default interval of 200ms will be used.
*/
typeAheadDebounceInterval?: true | number;
}

export interface TreeKeyManagerStrategy<T extends TreeKeyManagerItem> {
/** Stream that emits any time the focused item changes. */
readonly change: Subject<T | null>;

/**
* Handles a keyboard event on the tree.
*
* @param event Keyboard event that represents the user interaction with the tree.
*/
onKeydown(event: KeyboardEvent): void;

/** Index of the currently active item. */
getActiveItemIndex(): number | null;

/** The currently active item. */
getActiveItem(): T | null;

/**
* Called the first time the Tree component is focused. This method will only be called once over
* the lifetime of the Tree component.
*
* Intended to be used to focus the first item in the tree.
*/
onInitialFocus(): void;

/**
* Focus the provided item by index.
*
* Updates the state of the currently active item. Emits to `change` stream if active item
* Changes.
* @param index The index of the item to focus.
* @param options Additional focusing options.
*/
focusItem(index: number, options?: {emitChangeEvent?: boolean}): void;
/**
* Focus the provided item.
*
* Updates the state of the currently active item. Emits to `change` stream if active item
* Changes.
* @param item The item to focus. Equality is determined via the trackBy function.
* @param options Additional focusing options.
*/
focusItem(item: T, options?: {emitChangeEvent?: boolean}): void;
focusItem(itemOrIndex: number | T, options?: {emitChangeEvent?: boolean}): void;
}

export type TreeKeyManagerFactory<T extends TreeKeyManagerItem> = (
items: Observable<T[]> | QueryList<T> | T[],
options: TreeKeyManagerOptions<T>,
) => TreeKeyManagerStrategy<T>;
3 changes: 2 additions & 1 deletion src/cdk/a11y/key-manager/tree-key-manager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
} from '@angular/cdk/keycodes';
import {createKeyboardEvent} from '../../testing/private';
import {QueryList} from '@angular/core';
import {TreeKeyManager, TreeKeyManagerItem} from './tree-key-manager';
import {TreeKeyManager} from './tree-key-manager';
import {TreeKeyManagerItem} from './tree-key-manager-strategy';
import {Observable, of as observableOf, Subscription} from 'rxjs';
import {fakeAsync, tick} from '@angular/core/testing';

Expand Down
Loading

0 comments on commit 104c403

Please sign in to comment.