()
| 204 | } |
| 205 | |
| 206 | ngAfterContentInit() { |
| 207 | const dirChange = this._dir ? this._dir.change : observableOf('ltr'); |
| 208 | // We need to debounce resize events because the alignment logic is expensive. |
| 209 | // If someone animates the width of tabs, we don't want to realign on every animation frame. |
| 210 | // Once we haven't seen any more resize events in the last 32ms (~2 animaion frames) we can |
| 211 | // re-align. |
| 212 | const resize = this._sharedResizeObserver |
| 213 | .observe(this._elementRef.nativeElement) |
| 214 | .pipe(debounceTime(32), takeUntil(this._destroyed)); |
| 215 | // Note: We do not actually need to watch these events for proper functioning of the tabs, |
| 216 | // the resize events above should capture any viewport resize that we care about. However, |
| 217 | // removing this is fairly breaking for screenshot tests, so we're leaving it here for now. |
| 218 | const viewportResize = this._viewportRuler.change(150).pipe(takeUntil(this._destroyed)); |
| 219 | |
| 220 | const realign = () => { |
| 221 | this.updatePagination(); |
| 222 | this._alignInkBarToSelectedTab(); |
| 223 | }; |
| 224 | |
| 225 | this._keyManager = new FocusKeyManager<MatPaginatedTabHeaderItem>(this._items) |
| 226 | .withHorizontalOrientation(this._getLayoutDirection()) |
| 227 | .withHomeAndEnd() |
| 228 | .withWrap() |
| 229 | // Allow focus to land on disabled tabs, as per https://w3c.github.io/aria-practices/#kbd_disabled_controls |
| 230 | .skipPredicate(() => false); |
| 231 | |
| 232 | // Fall back to the first link as being active if there isn't a selected one. |
| 233 | // This is relevant primarily for the tab nav bar. |
| 234 | this._keyManager.updateActiveItem(Math.max(this._selectedIndex, 0)); |
| 235 | |
| 236 | // Note: We do not need to realign after the first render for proper functioning of the tabs |
| 237 | // the resize events above should fire when we first start observing the element. However, |
| 238 | // removing this is fairly breaking for screenshot tests, so we're leaving it here for now. |
| 239 | afterNextRender(realign, {injector: this._injector}); |
| 240 | |
| 241 | // On dir change or resize, realign the ink bar and update the orientation of |
| 242 | // the key manager if the direction has changed. |
| 243 | merge(dirChange, viewportResize, resize, this._items.changes, this._itemsResized()) |
| 244 | .pipe(takeUntil(this._destroyed)) |
| 245 | .subscribe(() => { |
| 246 | // We need to defer this to give the browser some time to recalculate |
| 247 | // the element dimensions. The call has to be wrapped in `NgZone.run`, |
| 248 | // because the viewport change handler runs outside of Angular. |
| 249 | this._ngZone.run(() => { |
| 250 | Promise.resolve().then(() => { |
| 251 | // Clamp the scroll distance, because it can change with the number of tabs. |
| 252 | this._scrollDistance = Math.max( |
| 253 | 0, |
| 254 | Math.min(this._getMaxScrollDistance(), this._scrollDistance), |
| 255 | ); |
| 256 | realign(); |
| 257 | }); |
| 258 | }); |
| 259 | this._keyManager?.withHorizontalOrientation(this._getLayoutDirection()); |
| 260 | }); |
| 261 | |
| 262 | // If there is a change in the focus key manager we need to emit the `indexFocused` |
| 263 | // event in order to provide a public event that notifies about focus changes. Also we realign |
nothing calls this directly
no test coverage detected