Skip to content

Commit 8f07db6

Browse files
committed
fixup! feat(cdk-experimental/ui-patterns): listbox ui pattern
1 parent b6e4cf7 commit 8f07db6

File tree

2 files changed

+20
-24
lines changed

2 files changed

+20
-24
lines changed

src/cdk-experimental/listbox/listbox.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ export class CdkOption {
126126
/** A unique identifier for the option. */
127127
private readonly _generatedId = inject(_IdGenerator).getId('cdk-option-');
128128

129+
// TODO(wagnermaciel): https://github.com/angular/components/pull/30495#discussion_r1972601144.
129130
/** A unique identifier for the option. */
130131
protected id = computed(() => this._generatedId);
131132

src/cdk-experimental/ui-patterns/behaviors/list-navigation/list-navigation.ts

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,31 +55,12 @@ export class ListNavigation<T extends ListNavigationItem> {
5555

5656
/** Navigates to the next item in the list. */
5757
next() {
58-
const items = this.inputs.items();
59-
const itemCount = items.length;
60-
const startIndex = this.inputs.activeIndex();
61-
const step = (i: number) => this._stepIndex(i, 1);
62-
63-
for (let i = step(startIndex); i !== startIndex && i < itemCount; i = step(i)) {
64-
if (this.isFocusable(items[i])) {
65-
this.goto(items[i]);
66-
return;
67-
}
68-
}
58+
this.advance(1);
6959
}
7060

7161
/** Navigates to the previous item in the list. */
7262
prev() {
73-
const items = this.inputs.items();
74-
const startIndex = this.inputs.activeIndex();
75-
const step = (i: number) => this._stepIndex(i, -1);
76-
77-
for (let i = step(startIndex); i !== startIndex && i >= 0; i = step(i)) {
78-
if (this.isFocusable(items[i])) {
79-
this.goto(items[i]);
80-
return;
81-
}
82-
}
63+
this.advance(-1);
8364
}
8465

8566
/** Navigates to the first item in the list. */
@@ -107,8 +88,22 @@ export class ListNavigation<T extends ListNavigationItem> {
10788
return !item.disabled() || !this.inputs.skipDisabled();
10889
}
10990

110-
private _stepIndex(index: number, step: -1 | 1) {
111-
const itemCount = this.inputs.items().length;
112-
return this.inputs.wrap() ? (index + step + itemCount) % itemCount : index + step;
91+
/** Advances to the next or previous focusable item in the list based on the given delta. */
92+
private advance(delta: 1 | -1) {
93+
const items = this.inputs.items();
94+
const itemCount = items.length;
95+
const startIndex = this.inputs.activeIndex();
96+
const step = (i: number) =>
97+
this.inputs.wrap() ? (i + delta + itemCount) % itemCount : i + delta;
98+
99+
// If wrapping is enabled, this loop ultimately terminates when `i` gets back to `startIndex`
100+
// in the case that all options are disabled. If wrapping is disabled, the loop terminates
101+
// when the index goes out of bounds.
102+
for (let i = step(startIndex); i !== startIndex && i < itemCount && i >= 0; i = step(i)) {
103+
if (this.isFocusable(items[i])) {
104+
this.goto(items[i]);
105+
return;
106+
}
107+
}
113108
}
114109
}

0 commit comments

Comments
 (0)