@angular/cdk 21.0.0-next.9 → 21.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/_adev_assets/cdk_drag_drop.json +13 -12
  2. package/_adev_assets/cdk_testing.json +9 -9
  3. package/_adev_assets/cdk_testing_protractor.json +1 -1
  4. package/_adev_assets/cdk_testing_selenium_webdriver.json +1 -1
  5. package/_adev_assets/cdk_testing_testbed.json +1 -1
  6. package/fesm2022/_a11y-module-chunk.mjs +755 -869
  7. package/fesm2022/_a11y-module-chunk.mjs.map +1 -1
  8. package/fesm2022/_activedescendant-key-manager-chunk.mjs +8 -8
  9. package/fesm2022/_activedescendant-key-manager-chunk.mjs.map +1 -1
  10. package/fesm2022/_array-chunk.mjs +1 -1
  11. package/fesm2022/_array-chunk.mjs.map +1 -1
  12. package/fesm2022/_breakpoints-observer-chunk.mjs +149 -152
  13. package/fesm2022/_breakpoints-observer-chunk.mjs.map +1 -1
  14. package/fesm2022/_css-pixel-value-chunk.mjs +4 -5
  15. package/fesm2022/_css-pixel-value-chunk.mjs.map +1 -1
  16. package/fesm2022/_data-source-chunk.mjs +2 -8
  17. package/fesm2022/_data-source-chunk.mjs.map +1 -1
  18. package/fesm2022/_directionality-chunk.mjs +54 -54
  19. package/fesm2022/_directionality-chunk.mjs.map +1 -1
  20. package/fesm2022/_dispose-view-repeater-strategy-chunk.mjs +25 -36
  21. package/fesm2022/_dispose-view-repeater-strategy-chunk.mjs.map +1 -1
  22. package/fesm2022/_element-chunk.mjs +6 -17
  23. package/fesm2022/_element-chunk.mjs.map +1 -1
  24. package/fesm2022/_fake-event-detection-chunk.mjs +3 -17
  25. package/fesm2022/_fake-event-detection-chunk.mjs.map +1 -1
  26. package/fesm2022/_focus-key-manager-chunk.mjs +10 -14
  27. package/fesm2022/_focus-key-manager-chunk.mjs.map +1 -1
  28. package/fesm2022/_focus-monitor-chunk.mjs +376 -566
  29. package/fesm2022/_focus-monitor-chunk.mjs.map +1 -1
  30. package/fesm2022/_id-generator-chunk.mjs +36 -27
  31. package/fesm2022/_id-generator-chunk.mjs.map +1 -1
  32. package/fesm2022/_keycodes-chunk.mjs +9 -9
  33. package/fesm2022/_keycodes-chunk.mjs.map +1 -1
  34. package/fesm2022/_list-key-manager-chunk.mjs +248 -336
  35. package/fesm2022/_list-key-manager-chunk.mjs.map +1 -1
  36. package/fesm2022/_overlay-module-chunk.mjs +2534 -2948
  37. package/fesm2022/_overlay-module-chunk.mjs.map +1 -1
  38. package/fesm2022/_passive-listeners-chunk.mjs +10 -22
  39. package/fesm2022/_passive-listeners-chunk.mjs.map +1 -1
  40. package/fesm2022/_platform-chunk.mjs +42 -65
  41. package/fesm2022/_platform-chunk.mjs.map +1 -1
  42. package/fesm2022/_recycle-view-repeater-strategy-chunk.mjs +78 -134
  43. package/fesm2022/_recycle-view-repeater-strategy-chunk.mjs.map +1 -1
  44. package/fesm2022/_scrolling-chunk.mjs +44 -85
  45. package/fesm2022/_scrolling-chunk.mjs.map +1 -1
  46. package/fesm2022/_selection-model-chunk.mjs +138 -209
  47. package/fesm2022/_selection-model-chunk.mjs.map +1 -1
  48. package/fesm2022/_shadow-dom-chunk.mjs +21 -35
  49. package/fesm2022/_shadow-dom-chunk.mjs.map +1 -1
  50. package/fesm2022/_style-loader-chunk.mjs +50 -37
  51. package/fesm2022/_style-loader-chunk.mjs.map +1 -1
  52. package/fesm2022/_test-environment-chunk.mjs +2 -14
  53. package/fesm2022/_test-environment-chunk.mjs.map +1 -1
  54. package/fesm2022/_tree-key-manager-chunk.mjs +229 -308
  55. package/fesm2022/_tree-key-manager-chunk.mjs.map +1 -1
  56. package/fesm2022/_typeahead-chunk.mjs +52 -74
  57. package/fesm2022/_typeahead-chunk.mjs.map +1 -1
  58. package/fesm2022/_unique-selection-dispatcher-chunk.mjs +43 -40
  59. package/fesm2022/_unique-selection-dispatcher-chunk.mjs.map +1 -1
  60. package/fesm2022/a11y.mjs +351 -449
  61. package/fesm2022/a11y.mjs.map +1 -1
  62. package/fesm2022/accordion.mjs +254 -192
  63. package/fesm2022/accordion.mjs.map +1 -1
  64. package/fesm2022/bidi.mjs +121 -64
  65. package/fesm2022/bidi.mjs.map +1 -1
  66. package/fesm2022/cdk.mjs +1 -2
  67. package/fesm2022/cdk.mjs.map +1 -1
  68. package/fesm2022/clipboard.mjs +208 -186
  69. package/fesm2022/clipboard.mjs.map +1 -1
  70. package/fesm2022/coercion-private.mjs +4 -8
  71. package/fesm2022/coercion-private.mjs.map +1 -1
  72. package/fesm2022/coercion.mjs +11 -29
  73. package/fesm2022/coercion.mjs.map +1 -1
  74. package/fesm2022/dialog.mjs +660 -808
  75. package/fesm2022/dialog.mjs.map +1 -1
  76. package/fesm2022/drag-drop.mjs +3347 -4286
  77. package/fesm2022/drag-drop.mjs.map +1 -1
  78. package/fesm2022/keycodes.mjs +4 -8
  79. package/fesm2022/keycodes.mjs.map +1 -1
  80. package/fesm2022/layout.mjs +44 -26
  81. package/fesm2022/layout.mjs.map +1 -1
  82. package/fesm2022/listbox.mjs +841 -895
  83. package/fesm2022/listbox.mjs.map +1 -1
  84. package/fesm2022/menu.mjs +1942 -1858
  85. package/fesm2022/menu.mjs.map +1 -1
  86. package/fesm2022/observers-private.mjs +88 -106
  87. package/fesm2022/observers-private.mjs.map +1 -1
  88. package/fesm2022/observers.mjs +262 -184
  89. package/fesm2022/observers.mjs.map +1 -1
  90. package/fesm2022/overlay.mjs +72 -68
  91. package/fesm2022/overlay.mjs.map +1 -1
  92. package/fesm2022/platform.mjs +43 -54
  93. package/fesm2022/platform.mjs.map +1 -1
  94. package/fesm2022/portal.mjs +402 -560
  95. package/fesm2022/portal.mjs.map +1 -1
  96. package/fesm2022/private.mjs +38 -10
  97. package/fesm2022/private.mjs.map +1 -1
  98. package/fesm2022/scrolling.mjs +1323 -1400
  99. package/fesm2022/scrolling.mjs.map +1 -1
  100. package/fesm2022/stepper.mjs +758 -590
  101. package/fesm2022/stepper.mjs.map +1 -1
  102. package/fesm2022/table.mjs +2327 -2319
  103. package/fesm2022/table.mjs.map +1 -1
  104. package/fesm2022/testing-selenium-webdriver.mjs +252 -325
  105. package/fesm2022/testing-selenium-webdriver.mjs.map +1 -1
  106. package/fesm2022/testing-testbed.mjs +592 -709
  107. package/fesm2022/testing-testbed.mjs.map +1 -1
  108. package/fesm2022/testing.mjs +368 -889
  109. package/fesm2022/testing.mjs.map +1 -1
  110. package/fesm2022/text-field.mjs +459 -388
  111. package/fesm2022/text-field.mjs.map +1 -1
  112. package/fesm2022/tree.mjs +1483 -1731
  113. package/fesm2022/tree.mjs.map +1 -1
  114. package/overlay/_index.scss +28 -0
  115. package/overlay-prebuilt.css +1 -1
  116. package/package.json +1 -1
  117. package/schematics/ng-add/index.js +1 -1
  118. package/types/_overlay-module-chunk.d.ts +59 -7
  119. package/types/_portal-directives-chunk.d.ts +2 -18
  120. package/types/accordion.d.ts +3 -1
  121. package/types/dialog.d.ts +1 -1
  122. package/types/overlay.d.ts +6 -2
  123. package/types/portal.d.ts +1 -1
@@ -4,339 +4,260 @@ import { take } from 'rxjs/operators';
4
4
  import { Typeahead } from './_typeahead-chunk.mjs';
5
5
  import { coerceObservable } from './coercion-private.mjs';
6
6
 
7
- /**
8
- * This class manages keyboard events for trees. If you pass it a QueryList or other list of tree
9
- * items, it will set the active item, focus, handle expansion and typeahead correctly when
10
- * keyboard events occur.
11
- */
12
7
  class TreeKeyManager {
13
- /** The index of the currently active (focused) item. */
14
- _activeItemIndex = -1;
15
- /** The currently active (focused) item. */
16
- _activeItem = null;
17
- /** Whether or not we activate the item when it's focused. */
18
- _shouldActivationFollowFocus = false;
19
- /**
20
- * The orientation that the tree is laid out in. In `rtl` mode, the behavior of Left and
21
- * Right arrow are switched.
22
- */
23
- _horizontalOrientation = 'ltr';
24
- /**
25
- * Predicate function that can be used to check whether an item should be skipped
26
- * by the key manager.
27
- *
28
- * The default value for this doesn't skip any elements in order to keep tree items focusable
29
- * when disabled. This aligns with ARIA guidelines:
30
- * https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols.
31
- */
32
- _skipPredicateFn = (_item) => false;
33
- /** Function to determine equivalent items. */
34
- _trackByFn = (item) => item;
35
- /** Synchronous cache of the items to manage. */
36
- _items = [];
37
- _typeahead;
38
- _typeaheadSubscription = Subscription.EMPTY;
39
- _hasInitialFocused = false;
40
- _initializeFocus() {
41
- if (this._hasInitialFocused || this._items.length === 0) {
42
- return;
43
- }
44
- let activeIndex = 0;
45
- for (let i = 0; i < this._items.length; i++) {
46
- if (!this._skipPredicateFn(this._items[i]) && !this._isItemDisabled(this._items[i])) {
47
- activeIndex = i;
48
- break;
49
- }
50
- }
51
- const activeItem = this._items[activeIndex];
52
- // Use `makeFocusable` here, because we want the item to just be focusable, not actually
53
- // capture the focus since the user isn't interacting with it. See #29628.
54
- if (activeItem.makeFocusable) {
55
- this._activeItem?.unfocus();
56
- this._activeItemIndex = activeIndex;
57
- this._activeItem = activeItem;
58
- this._typeahead?.setCurrentSelectedItemIndex(activeIndex);
59
- activeItem.makeFocusable();
60
- }
61
- else {
62
- // Backwards compatibility for items that don't implement `makeFocusable`.
63
- this.focusItem(activeIndex);
64
- }
65
- this._hasInitialFocused = true;
66
- }
67
- /**
68
- *
69
- * @param items List of TreeKeyManager options. Can be synchronous or asynchronous.
70
- * @param config Optional configuration options. By default, use 'ltr' horizontal orientation. By
71
- * default, do not skip any nodes. By default, key manager only calls `focus` method when items
72
- * are focused and does not call `activate`. If `typeaheadDefaultInterval` is `true`, use a
73
- * default interval of 200ms.
74
- */
75
- constructor(items, config) {
76
- // We allow for the items to be an array or Observable because, in some cases, the consumer may
77
- // not have access to a QueryList of the items they want to manage (e.g. when the
78
- // items aren't being collected via `ViewChildren` or `ContentChildren`).
79
- if (items instanceof QueryList) {
80
- this._items = items.toArray();
81
- items.changes.subscribe((newItems) => {
82
- this._items = newItems.toArray();
83
- this._typeahead?.setItems(this._items);
84
- this._updateActiveItemIndex(this._items);
85
- this._initializeFocus();
86
- });
87
- }
88
- else if (isObservable(items)) {
89
- items.subscribe(newItems => {
90
- this._items = newItems;
91
- this._typeahead?.setItems(newItems);
92
- this._updateActiveItemIndex(newItems);
93
- this._initializeFocus();
94
- });
95
- }
96
- else {
97
- this._items = items;
98
- this._initializeFocus();
99
- }
100
- if (typeof config.shouldActivationFollowFocus === 'boolean') {
101
- this._shouldActivationFollowFocus = config.shouldActivationFollowFocus;
102
- }
103
- if (config.horizontalOrientation) {
104
- this._horizontalOrientation = config.horizontalOrientation;
105
- }
106
- if (config.skipPredicate) {
107
- this._skipPredicateFn = config.skipPredicate;
108
- }
109
- if (config.trackBy) {
110
- this._trackByFn = config.trackBy;
111
- }
112
- if (typeof config.typeAheadDebounceInterval !== 'undefined') {
113
- this._setTypeAhead(config.typeAheadDebounceInterval);
114
- }
8
+ _activeItemIndex = -1;
9
+ _activeItem = null;
10
+ _shouldActivationFollowFocus = false;
11
+ _horizontalOrientation = 'ltr';
12
+ _skipPredicateFn = _item => false;
13
+ _trackByFn = item => item;
14
+ _items = [];
15
+ _typeahead;
16
+ _typeaheadSubscription = Subscription.EMPTY;
17
+ _hasInitialFocused = false;
18
+ _initializeFocus() {
19
+ if (this._hasInitialFocused || this._items.length === 0) {
20
+ return;
115
21
  }
116
- /** Stream that emits any time the focused item changes. */
117
- change = new Subject();
118
- /** Cleans up the key manager. */
119
- destroy() {
120
- this._typeaheadSubscription.unsubscribe();
121
- this._typeahead?.destroy();
122
- this.change.complete();
22
+ let activeIndex = 0;
23
+ for (let i = 0; i < this._items.length; i++) {
24
+ if (!this._skipPredicateFn(this._items[i]) && !this._isItemDisabled(this._items[i])) {
25
+ activeIndex = i;
26
+ break;
27
+ }
123
28
  }
124
- /**
125
- * Handles a keyboard event on the tree.
126
- * @param event Keyboard event that represents the user interaction with the tree.
127
- */
128
- onKeydown(event) {
129
- const key = event.key;
130
- switch (key) {
131
- case 'Tab':
132
- // Return early here, in order to allow Tab to actually tab out of the tree
133
- return;
134
- case 'ArrowDown':
135
- this._focusNextItem();
136
- break;
137
- case 'ArrowUp':
138
- this._focusPreviousItem();
139
- break;
140
- case 'ArrowRight':
141
- this._horizontalOrientation === 'rtl'
142
- ? this._collapseCurrentItem()
143
- : this._expandCurrentItem();
144
- break;
145
- case 'ArrowLeft':
146
- this._horizontalOrientation === 'rtl'
147
- ? this._expandCurrentItem()
148
- : this._collapseCurrentItem();
149
- break;
150
- case 'Home':
151
- this._focusFirstItem();
152
- break;
153
- case 'End':
154
- this._focusLastItem();
155
- break;
156
- case 'Enter':
157
- case ' ':
158
- this._activateCurrentItem();
159
- break;
160
- default:
161
- if (event.key === '*') {
162
- this._expandAllItemsAtCurrentItemLevel();
163
- break;
164
- }
165
- this._typeahead?.handleKey(event);
166
- // Return here, in order to avoid preventing the default action of non-navigational
167
- // keys or resetting the buffer of pressed letters.
168
- return;
169
- }
170
- // Reset the typeahead since the user has used a navigational key.
171
- this._typeahead?.reset();
172
- event.preventDefault();
29
+ const activeItem = this._items[activeIndex];
30
+ if (activeItem.makeFocusable) {
31
+ this._activeItem?.unfocus();
32
+ this._activeItemIndex = activeIndex;
33
+ this._activeItem = activeItem;
34
+ this._typeahead?.setCurrentSelectedItemIndex(activeIndex);
35
+ activeItem.makeFocusable();
36
+ } else {
37
+ this.focusItem(activeIndex);
173
38
  }
174
- /** Index of the currently active item. */
175
- getActiveItemIndex() {
176
- return this._activeItemIndex;
39
+ this._hasInitialFocused = true;
40
+ }
41
+ constructor(items, config) {
42
+ if (items instanceof QueryList) {
43
+ this._items = items.toArray();
44
+ items.changes.subscribe(newItems => {
45
+ this._items = newItems.toArray();
46
+ this._typeahead?.setItems(this._items);
47
+ this._updateActiveItemIndex(this._items);
48
+ this._initializeFocus();
49
+ });
50
+ } else if (isObservable(items)) {
51
+ items.subscribe(newItems => {
52
+ this._items = newItems;
53
+ this._typeahead?.setItems(newItems);
54
+ this._updateActiveItemIndex(newItems);
55
+ this._initializeFocus();
56
+ });
57
+ } else {
58
+ this._items = items;
59
+ this._initializeFocus();
177
60
  }
178
- /** The currently active item. */
179
- getActiveItem() {
180
- return this._activeItem;
61
+ if (typeof config.shouldActivationFollowFocus === 'boolean') {
62
+ this._shouldActivationFollowFocus = config.shouldActivationFollowFocus;
181
63
  }
182
- /** Focus the first available item. */
183
- _focusFirstItem() {
184
- this.focusItem(this._findNextAvailableItemIndex(-1));
64
+ if (config.horizontalOrientation) {
65
+ this._horizontalOrientation = config.horizontalOrientation;
185
66
  }
186
- /** Focus the last available item. */
187
- _focusLastItem() {
188
- this.focusItem(this._findPreviousAvailableItemIndex(this._items.length));
67
+ if (config.skipPredicate) {
68
+ this._skipPredicateFn = config.skipPredicate;
189
69
  }
190
- /** Focus the next available item. */
191
- _focusNextItem() {
192
- this.focusItem(this._findNextAvailableItemIndex(this._activeItemIndex));
70
+ if (config.trackBy) {
71
+ this._trackByFn = config.trackBy;
193
72
  }
194
- /** Focus the previous available item. */
195
- _focusPreviousItem() {
196
- this.focusItem(this._findPreviousAvailableItemIndex(this._activeItemIndex));
73
+ if (typeof config.typeAheadDebounceInterval !== 'undefined') {
74
+ this._setTypeAhead(config.typeAheadDebounceInterval);
197
75
  }
198
- focusItem(itemOrIndex, options = {}) {
199
- // Set default options
200
- options.emitChangeEvent ??= true;
201
- let index = typeof itemOrIndex === 'number'
202
- ? itemOrIndex
203
- : this._items.findIndex(item => this._trackByFn(item) === this._trackByFn(itemOrIndex));
204
- if (index < 0 || index >= this._items.length) {
205
- return;
206
- }
207
- const activeItem = this._items[index];
208
- // If we're just setting the same item, don't re-call activate or focus
209
- if (this._activeItem !== null &&
210
- this._trackByFn(activeItem) === this._trackByFn(this._activeItem)) {
211
- return;
212
- }
213
- const previousActiveItem = this._activeItem;
214
- this._activeItem = activeItem ?? null;
215
- this._activeItemIndex = index;
216
- this._typeahead?.setCurrentSelectedItemIndex(index);
217
- this._activeItem?.focus();
218
- previousActiveItem?.unfocus();
219
- if (options.emitChangeEvent) {
220
- this.change.next(this._activeItem);
221
- }
222
- if (this._shouldActivationFollowFocus) {
223
- this._activateCurrentItem();
76
+ }
77
+ change = new Subject();
78
+ destroy() {
79
+ this._typeaheadSubscription.unsubscribe();
80
+ this._typeahead?.destroy();
81
+ this.change.complete();
82
+ }
83
+ onKeydown(event) {
84
+ const key = event.key;
85
+ switch (key) {
86
+ case 'Tab':
87
+ return;
88
+ case 'ArrowDown':
89
+ this._focusNextItem();
90
+ break;
91
+ case 'ArrowUp':
92
+ this._focusPreviousItem();
93
+ break;
94
+ case 'ArrowRight':
95
+ this._horizontalOrientation === 'rtl' ? this._collapseCurrentItem() : this._expandCurrentItem();
96
+ break;
97
+ case 'ArrowLeft':
98
+ this._horizontalOrientation === 'rtl' ? this._expandCurrentItem() : this._collapseCurrentItem();
99
+ break;
100
+ case 'Home':
101
+ this._focusFirstItem();
102
+ break;
103
+ case 'End':
104
+ this._focusLastItem();
105
+ break;
106
+ case 'Enter':
107
+ case ' ':
108
+ this._activateCurrentItem();
109
+ break;
110
+ default:
111
+ if (event.key === '*') {
112
+ this._expandAllItemsAtCurrentItemLevel();
113
+ break;
224
114
  }
115
+ this._typeahead?.handleKey(event);
116
+ return;
225
117
  }
226
- _updateActiveItemIndex(newItems) {
227
- const activeItem = this._activeItem;
228
- if (!activeItem) {
229
- return;
230
- }
231
- const newIndex = newItems.findIndex(item => this._trackByFn(item) === this._trackByFn(activeItem));
232
- if (newIndex > -1 && newIndex !== this._activeItemIndex) {
233
- this._activeItemIndex = newIndex;
234
- this._typeahead?.setCurrentSelectedItemIndex(newIndex);
235
- }
118
+ this._typeahead?.reset();
119
+ event.preventDefault();
120
+ }
121
+ getActiveItemIndex() {
122
+ return this._activeItemIndex;
123
+ }
124
+ getActiveItem() {
125
+ return this._activeItem;
126
+ }
127
+ _focusFirstItem() {
128
+ this.focusItem(this._findNextAvailableItemIndex(-1));
129
+ }
130
+ _focusLastItem() {
131
+ this.focusItem(this._findPreviousAvailableItemIndex(this._items.length));
132
+ }
133
+ _focusNextItem() {
134
+ this.focusItem(this._findNextAvailableItemIndex(this._activeItemIndex));
135
+ }
136
+ _focusPreviousItem() {
137
+ this.focusItem(this._findPreviousAvailableItemIndex(this._activeItemIndex));
138
+ }
139
+ focusItem(itemOrIndex, options = {}) {
140
+ options.emitChangeEvent ??= true;
141
+ let index = typeof itemOrIndex === 'number' ? itemOrIndex : this._items.findIndex(item => this._trackByFn(item) === this._trackByFn(itemOrIndex));
142
+ if (index < 0 || index >= this._items.length) {
143
+ return;
236
144
  }
237
- _setTypeAhead(debounceInterval) {
238
- this._typeahead = new Typeahead(this._items, {
239
- debounceInterval: typeof debounceInterval === 'number' ? debounceInterval : undefined,
240
- skipPredicate: item => this._skipPredicateFn(item),
241
- });
242
- this._typeaheadSubscription = this._typeahead.selectedItem.subscribe(item => {
243
- this.focusItem(item);
244
- });
145
+ const activeItem = this._items[index];
146
+ if (this._activeItem !== null && this._trackByFn(activeItem) === this._trackByFn(this._activeItem)) {
147
+ return;
245
148
  }
246
- _findNextAvailableItemIndex(startingIndex) {
247
- for (let i = startingIndex + 1; i < this._items.length; i++) {
248
- if (!this._skipPredicateFn(this._items[i])) {
249
- return i;
250
- }
251
- }
252
- return startingIndex;
149
+ const previousActiveItem = this._activeItem;
150
+ this._activeItem = activeItem ?? null;
151
+ this._activeItemIndex = index;
152
+ this._typeahead?.setCurrentSelectedItemIndex(index);
153
+ this._activeItem?.focus();
154
+ previousActiveItem?.unfocus();
155
+ if (options.emitChangeEvent) {
156
+ this.change.next(this._activeItem);
253
157
  }
254
- _findPreviousAvailableItemIndex(startingIndex) {
255
- for (let i = startingIndex - 1; i >= 0; i--) {
256
- if (!this._skipPredicateFn(this._items[i])) {
257
- return i;
258
- }
259
- }
260
- return startingIndex;
158
+ if (this._shouldActivationFollowFocus) {
159
+ this._activateCurrentItem();
261
160
  }
262
- /**
263
- * If the item is already expanded, we collapse the item. Otherwise, we will focus the parent.
264
- */
265
- _collapseCurrentItem() {
266
- if (!this._activeItem) {
267
- return;
268
- }
269
- if (this._isCurrentItemExpanded()) {
270
- this._activeItem.collapse();
271
- }
272
- else {
273
- const parent = this._activeItem.getParent();
274
- if (!parent || this._skipPredicateFn(parent)) {
275
- return;
276
- }
277
- this.focusItem(parent);
278
- }
161
+ }
162
+ _updateActiveItemIndex(newItems) {
163
+ const activeItem = this._activeItem;
164
+ if (!activeItem) {
165
+ return;
279
166
  }
280
- /**
281
- * If the item is already collapsed, we expand the item. Otherwise, we will focus the first child.
282
- */
283
- _expandCurrentItem() {
284
- if (!this._activeItem) {
285
- return;
286
- }
287
- if (!this._isCurrentItemExpanded()) {
288
- this._activeItem.expand();
289
- }
290
- else {
291
- coerceObservable(this._activeItem.getChildren())
292
- .pipe(take(1))
293
- .subscribe(children => {
294
- const firstChild = children.find(child => !this._skipPredicateFn(child));
295
- if (!firstChild) {
296
- return;
297
- }
298
- this.focusItem(firstChild);
299
- });
300
- }
167
+ const newIndex = newItems.findIndex(item => this._trackByFn(item) === this._trackByFn(activeItem));
168
+ if (newIndex > -1 && newIndex !== this._activeItemIndex) {
169
+ this._activeItemIndex = newIndex;
170
+ this._typeahead?.setCurrentSelectedItemIndex(newIndex);
301
171
  }
302
- _isCurrentItemExpanded() {
303
- if (!this._activeItem) {
304
- return false;
305
- }
306
- return typeof this._activeItem.isExpanded === 'boolean'
307
- ? this._activeItem.isExpanded
308
- : this._activeItem.isExpanded();
172
+ }
173
+ _setTypeAhead(debounceInterval) {
174
+ this._typeahead = new Typeahead(this._items, {
175
+ debounceInterval: typeof debounceInterval === 'number' ? debounceInterval : undefined,
176
+ skipPredicate: item => this._skipPredicateFn(item)
177
+ });
178
+ this._typeaheadSubscription = this._typeahead.selectedItem.subscribe(item => {
179
+ this.focusItem(item);
180
+ });
181
+ }
182
+ _findNextAvailableItemIndex(startingIndex) {
183
+ for (let i = startingIndex + 1; i < this._items.length; i++) {
184
+ if (!this._skipPredicateFn(this._items[i])) {
185
+ return i;
186
+ }
309
187
  }
310
- _isItemDisabled(item) {
311
- return typeof item.isDisabled === 'boolean' ? item.isDisabled : item.isDisabled?.();
188
+ return startingIndex;
189
+ }
190
+ _findPreviousAvailableItemIndex(startingIndex) {
191
+ for (let i = startingIndex - 1; i >= 0; i--) {
192
+ if (!this._skipPredicateFn(this._items[i])) {
193
+ return i;
194
+ }
312
195
  }
313
- /** For all items that are the same level as the current item, we expand those items. */
314
- _expandAllItemsAtCurrentItemLevel() {
315
- if (!this._activeItem) {
316
- return;
317
- }
318
- const parent = this._activeItem.getParent();
319
- let itemsToExpand;
320
- if (!parent) {
321
- itemsToExpand = of(this._items.filter(item => item.getParent() === null));
322
- }
323
- else {
324
- itemsToExpand = coerceObservable(parent.getChildren());
196
+ return startingIndex;
197
+ }
198
+ _collapseCurrentItem() {
199
+ if (!this._activeItem) {
200
+ return;
201
+ }
202
+ if (this._isCurrentItemExpanded()) {
203
+ this._activeItem.collapse();
204
+ } else {
205
+ const parent = this._activeItem.getParent();
206
+ if (!parent || this._skipPredicateFn(parent)) {
207
+ return;
208
+ }
209
+ this.focusItem(parent);
210
+ }
211
+ }
212
+ _expandCurrentItem() {
213
+ if (!this._activeItem) {
214
+ return;
215
+ }
216
+ if (!this._isCurrentItemExpanded()) {
217
+ this._activeItem.expand();
218
+ } else {
219
+ coerceObservable(this._activeItem.getChildren()).pipe(take(1)).subscribe(children => {
220
+ const firstChild = children.find(child => !this._skipPredicateFn(child));
221
+ if (!firstChild) {
222
+ return;
325
223
  }
326
- itemsToExpand.pipe(take(1)).subscribe(items => {
327
- for (const item of items) {
328
- item.expand();
329
- }
330
- });
224
+ this.focusItem(firstChild);
225
+ });
226
+ }
227
+ }
228
+ _isCurrentItemExpanded() {
229
+ if (!this._activeItem) {
230
+ return false;
231
+ }
232
+ return typeof this._activeItem.isExpanded === 'boolean' ? this._activeItem.isExpanded : this._activeItem.isExpanded();
233
+ }
234
+ _isItemDisabled(item) {
235
+ return typeof item.isDisabled === 'boolean' ? item.isDisabled : item.isDisabled?.();
236
+ }
237
+ _expandAllItemsAtCurrentItemLevel() {
238
+ if (!this._activeItem) {
239
+ return;
331
240
  }
332
- _activateCurrentItem() {
333
- this._activeItem?.activate();
241
+ const parent = this._activeItem.getParent();
242
+ let itemsToExpand;
243
+ if (!parent) {
244
+ itemsToExpand = of(this._items.filter(item => item.getParent() === null));
245
+ } else {
246
+ itemsToExpand = coerceObservable(parent.getChildren());
334
247
  }
248
+ itemsToExpand.pipe(take(1)).subscribe(items => {
249
+ for (const item of items) {
250
+ item.expand();
251
+ }
252
+ });
253
+ }
254
+ _activateCurrentItem() {
255
+ this._activeItem?.activate();
256
+ }
335
257
  }
336
- /** Injection token that determines the key manager to use. */
337
258
  const TREE_KEY_MANAGER = new InjectionToken('tree-key-manager', {
338
- providedIn: 'root',
339
- factory: () => (items, options) => new TreeKeyManager(items, options),
259
+ providedIn: 'root',
260
+ factory: () => (items, options) => new TreeKeyManager(items, options)
340
261
  });
341
262
 
342
263
  export { TREE_KEY_MANAGER, TreeKeyManager };