diff --git a/src/material/sort/sort-animations.ts b/src/material/sort/sort-animations.ts index 2107cc36b3f0..155a46c7b35c 100644 --- a/src/material/sort/sort-animations.ts +++ b/src/material/sort/sort-animations.ts @@ -24,6 +24,8 @@ const SORT_ANIMATION_TRANSITION = /** * Animations used by MatSort. * @docs-private + * @deprecated No longer being used, to be removed. + * @breaking-change 21.0.0 */ export const matSortAnimations: { readonly indicator: AnimationTriggerMetadata; diff --git a/src/material/sort/sort-header.html b/src/material/sort/sort-header.html index 93cf5d902690..ecfae9ac0294 100644 --- a/src/material/sort/sort-header.html +++ b/src/material/sort/sort-header.html @@ -11,6 +11,11 @@
@@ -26,18 +31,10 @@ @if (_renderArrow()) { -
-
-
-
-
-
-
+
+
}
diff --git a/src/material/sort/sort-header.scss b/src/material/sort/sort-header.scss index 0e1818717f69..575439384539 100644 --- a/src/material/sort/sort-header.scss +++ b/src/material/sort/sort-header.scss @@ -1,16 +1,7 @@ -@use '@angular/cdk'; - @use '../core/tokens/m2/mat/sort' as tokens-mat-sort; @use '../core/tokens/token-utils'; @use '../core/focus-indicators/private'; -$header-arrow-margin: 6px; -$header-arrow-container-size: 12px; -$header-arrow-stem-size: 10px; -$header-arrow-pointer-length: 6px; -$header-arrow-thickness: 2px; -$header-arrow-hint-opacity: 0.38; - .mat-sort-header-container { display: flex; cursor: pointer; @@ -51,93 +42,96 @@ $header-arrow-hint-opacity: 0.38; flex-direction: row-reverse; } +@keyframes _mat-sort-header-recently-cleared-ascending { + from { + transform: translateY(0); + opacity: 1; + } + + to { + transform: translateY(-25%); + opacity: 0; + } +} + +@keyframes _mat-sort-header-recently-cleared-descending { + from { + transform: translateY(0) rotate(180deg); + opacity: 1; + } + + to { + transform: translateY(25%) rotate(180deg); + opacity: 0; + } +} + .mat-sort-header-arrow { - height: $header-arrow-container-size; - width: $header-arrow-container-size; - min-width: $header-arrow-container-size; + $timing: 225ms cubic-bezier(0.4, 0, 0.2, 1); + height: 12px; + width: 12px; position: relative; - display: flex; + transition: transform $timing, opacity $timing; + opacity: 0; + overflow: visible; @include token-utils.use-tokens(tokens-mat-sort.$prefix, tokens-mat-sort.get-token-slots()) { @include token-utils.create-token-slot(color, arrow-color); } - // Start off at 0 since the arrow may become visible while parent are animating. - // This will be overwritten when the arrow animations kick in. See #11819. - opacity: 0; - - &, - [dir='rtl'] .mat-sort-header-position-before & { - margin: 0 0 0 $header-arrow-margin; + .mat-sort-header:hover & { + opacity: 0.54; } - .mat-sort-header-position-before &, - [dir='rtl'] & { - margin: 0 $header-arrow-margin 0 0; + .mat-sort-header .mat-sort-header-sorted & { + opacity: 1; } -} -.mat-sort-header-stem { - background: currentColor; - height: $header-arrow-stem-size; - width: $header-arrow-thickness; - margin: auto; - display: flex; - align-items: center; - - @include cdk.high-contrast { - width: 0; - border-left: solid $header-arrow-thickness; + .mat-sort-header-descending & { + transform: rotate(180deg); } -} -.mat-sort-header-indicator { - width: 100%; - height: $header-arrow-thickness; - display: flex; - align-items: center; - position: absolute; - top: 0; - left: 0; -} + .mat-sort-header-recently-cleared-ascending & { + transform: translateY(-25%); + } -.mat-sort-header-pointer-middle { - margin: auto; - height: $header-arrow-thickness; - width: $header-arrow-thickness; - background: currentColor; - transform: rotate(45deg); + .mat-sort-header-recently-cleared-ascending & { + transition: none; // Without this the animation looks glitchy on Safari. + animation: _mat-sort-header-recently-cleared-ascending $timing forwards; + } - @include cdk.high-contrast { - width: 0; - height: 0; - border-top: solid $header-arrow-thickness; - border-left: solid $header-arrow-thickness; + .mat-sort-header-recently-cleared-descending & { + transition: none; // Without this the animation looks glitchy on Safari. + animation: _mat-sort-header-recently-cleared-descending $timing forwards; } -} -.mat-sort-header-pointer-left, -.mat-sort-header-pointer-right { - background: currentColor; - width: $header-arrow-pointer-length; - height: $header-arrow-thickness; - position: absolute; - top: 0; + // Set the durations to 0, but keep the actual animation, since we still want it to play. + .mat-sort-header-animations-disabled & { + transition-duration: 0ms; + animation-duration: 0ms; + } - @include cdk.high-contrast { - width: 0; - height: 0; - border-left: solid $header-arrow-pointer-length; - border-top: solid $header-arrow-thickness; + svg { + // Even though this is 24x24, the actual `path` inside ends up being 12x12. + width: 24px; + height: 24px; + fill: currentColor; + position: absolute; + top: 50%; + left: 50%; + margin: -12px 0 0 -12px; + + // Without this transform the element twitches at the end of the transition on Safari. + transform: translateZ(0); } -} -.mat-sort-header-pointer-left { - transform-origin: right; - left: 0; -} + &, + [dir='rtl'] .mat-sort-header-position-before & { + margin: 0 0 0 6px; + } -.mat-sort-header-pointer-right { - transform-origin: left; - right: 0; + .mat-sort-header-position-before &, + [dir='rtl'] & { + margin: 0 6px 0 0; + } } diff --git a/src/material/sort/sort-header.ts b/src/material/sort/sort-header.ts index 75fc440a882e..51d529b0fcbd 100644 --- a/src/material/sort/sort-header.ts +++ b/src/material/sort/sort-header.ts @@ -11,7 +11,6 @@ import {ENTER, SPACE} from '@angular/cdk/keycodes'; import { AfterViewInit, ChangeDetectionStrategy, - ChangeDetectorRef, Component, ElementRef, Input, @@ -20,6 +19,9 @@ import { ViewEncapsulation, booleanAttribute, inject, + signal, + ANIMATION_MODULE_TYPE, + ChangeDetectorRef, } from '@angular/core'; import {merge, Subscription} from 'rxjs'; import { @@ -29,7 +31,6 @@ import { MatSortDefaultOptions, SortHeaderArrowPosition, } from './sort'; -import {matSortAnimations} from './sort-animations'; import {SortDirection} from './sort-direction'; import {getSortHeaderNotContainedWithinSortError} from './sort-errors'; import {MatSortHeaderIntl} from './sort-header-intl'; @@ -43,6 +44,8 @@ import {_StructuralStylesLoader} from '@angular/material/core'; * be fully opaque in the center. * * @docs-private + * @deprecated No longer being used, to be removed. + * @breaking-change 21.0.0 */ export type ArrowViewState = SortDirection | 'hint' | 'active'; @@ -50,6 +53,8 @@ export type ArrowViewState = SortDirection | 'hint' | 'active'; * States describing the arrow's animated position (animating fromState to toState). * If the fromState is not defined, there will be no animated transition to the toState. * @docs-private + * @deprecated No longer being used, to be removed. + * @breaking-change 21.0.0 */ export interface ArrowViewStateTransition { fromState?: ArrowViewState; @@ -77,36 +82,33 @@ interface MatSortHeaderColumnDef { styleUrl: 'sort-header.css', host: { 'class': 'mat-sort-header', - '(click)': '_handleClick()', + '(click)': '_toggleOnInteraction()', '(keydown)': '_handleKeydown($event)', - '(mouseenter)': '_setIndicatorHintVisible(true)', - '(mouseleave)': '_setIndicatorHintVisible(false)', + '(mouseleave)': '_recentlyCleared.set(false)', '[attr.aria-sort]': '_getAriaSortAttribute()', '[class.mat-sort-header-disabled]': '_isDisabled()', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, - animations: [ - matSortAnimations.indicator, - matSortAnimations.leftPointer, - matSortAnimations.rightPointer, - matSortAnimations.arrowOpacity, - matSortAnimations.arrowPosition, - matSortAnimations.allowChildren, - ], }) export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewInit { _intl = inject(MatSortHeaderIntl); - private _changeDetectorRef = inject(ChangeDetectorRef); _sort = inject(MatSort, {optional: true})!; _columnDef = inject('MAT_SORT_HEADER_COLUMN_DEF' as any, { optional: true, }); + private _changeDetectorRef = inject(ChangeDetectorRef); private _focusMonitor = inject(FocusMonitor); private _elementRef = inject>(ElementRef); private _ariaDescriber = inject(AriaDescriber, {optional: true}); + private _renderChanges: Subscription | undefined; + protected _animationModule = inject(ANIMATION_MODULE_TYPE, {optional: true}); - private _rerenderSubscription: Subscription; + /** + * Indicates which state was just cleared from the sort header. + * Will be reset on the next interaction. Used for coordinating animations. + */ + protected _recentlyCleared = signal(null); /** * The element with role="button" inside this component's view. We need this @@ -114,27 +116,6 @@ export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewI */ private _sortButton: HTMLElement; - /** - * Flag set to true when the indicator should be displayed while the sort is not active. Used to - * provide an affordance that the header is sortable by showing on focus and hover. - */ - _showIndicatorHint: boolean = false; - - /** - * The view transition state of the arrow (translation/ opacity) - indicates its `from` and `to` - * position through the animation. If animations are currently disabled, the fromState is removed - * so that there is no animation displayed. - */ - _viewState: ArrowViewStateTransition = {}; - - /** The direction the arrow should be facing according to the current state. */ - _arrowDirection: SortDirection = ''; - - /** - * Whether the view state animation should show the transition between the `from` and `to` states. - */ - _disableViewStateAnimation = false; - /** * ID of this sort header. If used within the context of a CdkColumnDef, this will default to * the column's name. @@ -190,8 +171,6 @@ export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewI if (defaultOptions?.arrowPosition) { this.arrowPosition = defaultOptions?.arrowPosition; } - - this._handleStateChanges(); } ngOnInit() { @@ -199,14 +178,10 @@ export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewI this.id = this._columnDef.name; } - // Initialize the direction of the arrow and set the view state to be immediately that state. - this._updateArrowDirection(); - this._setAnimationTransitionState({ - toState: this._isSorted() ? 'active' : this._arrowDirection, - }); - this._sort.register(this); - + this._renderChanges = merge(this._sort._stateChanges, this._sort.sortChange).subscribe(() => + this._changeDetectorRef.markForCheck(), + ); this._sortButton = this._elementRef.nativeElement.querySelector('.mat-sort-header-container')!; this._updateSortActionDescription(this._sortActionDescription); } @@ -214,80 +189,33 @@ export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewI ngAfterViewInit() { // We use the focus monitor because we also want to style // things differently based on the focus origin. - this._focusMonitor.monitor(this._elementRef, true).subscribe(origin => { - const newState = !!origin; - if (newState !== this._showIndicatorHint) { - this._setIndicatorHintVisible(newState); - this._changeDetectorRef.markForCheck(); - } - }); + this._focusMonitor + .monitor(this._elementRef, true) + .subscribe(() => this._recentlyCleared.set(null)); } ngOnDestroy() { this._focusMonitor.stopMonitoring(this._elementRef); this._sort.deregister(this); - this._rerenderSubscription.unsubscribe(); + this._renderChanges?.unsubscribe(); if (this._sortButton) { this._ariaDescriber?.removeDescription(this._sortButton, this._sortActionDescription); } } - /** - * Sets the "hint" state such that the arrow will be semi-transparently displayed as a hint to the - * user showing what the active sort will become. If set to false, the arrow will fade away. - */ - _setIndicatorHintVisible(visible: boolean) { - // No-op if the sort header is disabled - should not make the hint visible. - if (this._isDisabled() && visible) { - return; - } - - this._showIndicatorHint = visible; - - if (!this._isSorted()) { - this._updateArrowDirection(); - if (this._showIndicatorHint) { - this._setAnimationTransitionState({fromState: this._arrowDirection, toState: 'hint'}); - } else { - this._setAnimationTransitionState({fromState: 'hint', toState: this._arrowDirection}); - } - } - } - - /** - * Sets the animation transition view state for the arrow's position and opacity. If the - * `disableViewStateAnimation` flag is set to true, the `fromState` will be ignored so that - * no animation appears. - */ - _setAnimationTransitionState(viewState: ArrowViewStateTransition) { - this._viewState = viewState || {}; - - // If the animation for arrow position state (opacity/translation) should be disabled, - // remove the fromState so that it jumps right to the toState. - if (this._disableViewStateAnimation) { - this._viewState = {toState: viewState.toState}; - } - } - /** Triggers the sort on this sort header and removes the indicator hint. */ _toggleOnInteraction() { - this._sort.sort(this); - - // Do not show the animation if the header was already shown in the right position. - if (this._viewState.toState === 'hint' || this._viewState.toState === 'active') { - this._disableViewStateAnimation = true; - } - } - - _handleClick() { if (!this._isDisabled()) { + const wasSorted = this._isSorted(); + const prevDirection = this._sort.direction; this._sort.sort(this); + this._recentlyCleared.set(wasSorted && !this._isSorted() ? prevDirection : null); } } _handleKeydown(event: KeyboardEvent) { - if (!this._isDisabled() && (event.keyCode === SPACE || event.keyCode === ENTER)) { + if (event.keyCode === SPACE || event.keyCode === ENTER) { event.preventDefault(); this._toggleOnInteraction(); } @@ -301,31 +229,6 @@ export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewI ); } - /** Returns the animation state for the arrow direction (indicator and pointers). */ - _getArrowDirectionState() { - return `${this._isSorted() ? 'active-' : ''}${this._arrowDirection}`; - } - - /** Returns the arrow position state (opacity, translation). */ - _getArrowViewState() { - const fromState = this._viewState.fromState; - return (fromState ? `${fromState}-to-` : '') + this._viewState.toState; - } - - /** - * Updates the direction the arrow should be pointing. If it is not sorted, the arrow should be - * facing the start direction. Otherwise if it is sorted, the arrow should point in the currently - * active sorted direction. The reason this is updated through a function is because the direction - * should only be changed at specific times - when deactivated but the hint is displayed and when - * the sort is active and the direction changes. Otherwise the arrow's direction should linger - * in cases such as the sort becoming deactivated but we want to animate the arrow away while - * preserving its direction, even though the next sort direction is actually different and should - * only be changed once the arrow displays again (hint or activation). - */ - _updateArrowDirection() { - this._arrowDirection = this._isSorted() ? this._sort.direction : this.start || this._sort.start; - } - _isDisabled() { return this._sort.disabled || this.disabled; } @@ -365,33 +268,4 @@ export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewI this._sortActionDescription = newDescription; } - - /** Handles changes in the sorting state. */ - private _handleStateChanges() { - this._rerenderSubscription = merge( - this._sort.sortChange, - this._sort._stateChanges, - this._intl.changes, - ).subscribe(() => { - if (this._isSorted()) { - this._updateArrowDirection(); - - // Do not show the animation if the header was already shown in the right position. - if (this._viewState.toState === 'hint' || this._viewState.toState === 'active') { - this._disableViewStateAnimation = true; - } - - this._setAnimationTransitionState({fromState: this._arrowDirection, toState: 'active'}); - this._showIndicatorHint = false; - } - - // If this header was recently active and now no longer sorted, animate away the arrow. - if (!this._isSorted() && this._viewState && this._viewState.toState === 'active') { - this._disableViewStateAnimation = false; - this._setAnimationTransitionState({fromState: 'active', toState: this._arrowDirection}); - } - - this._changeDetectorRef.markForCheck(); - }); - } } diff --git a/src/material/sort/sort.spec.ts b/src/material/sort/sort.spec.ts index 08bf17a48219..383721086209 100644 --- a/src/material/sort/sort.spec.ts +++ b/src/material/sort/sort.spec.ts @@ -1,11 +1,6 @@ import {CollectionViewer, DataSource} from '@angular/cdk/collections'; import {CdkTableModule} from '@angular/cdk/table'; -import { - createFakeEvent, - createMouseEvent, - dispatchMouseEvent, - wrappedErrorMessage, -} from '@angular/cdk/testing/private'; +import {dispatchMouseEvent, wrappedErrorMessage} from '@angular/cdk/testing/private'; import {Component, ElementRef, ViewChild, inject} from '@angular/core'; import {ComponentFixture, TestBed, fakeAsync, tick, waitForAsync} from '@angular/core/testing'; import {MatTableModule} from '@angular/material/table'; @@ -103,116 +98,6 @@ describe('MatSort', () => { expect(sortables.has('column_c')).toBe(true); }); - describe('checking correct arrow direction and view state for its various states', () => { - let expectedStates: Map; - - beforeEach(() => { - // Starting state for the view and directions - note that overrideStart is reversed to be - // desc - expectedStates = new Map([ - ['defaultA', {viewState: 'asc', arrowDirection: 'asc'}], - ['defaultB', {viewState: 'asc', arrowDirection: 'asc'}], - ['overrideStart', {viewState: 'desc', arrowDirection: 'desc'}], - ['overrideDisableClear', {viewState: 'asc', arrowDirection: 'asc'}], - ]); - component.expectViewAndDirectionStates(expectedStates); - }); - - it('should be correct when mousing over headers and leaving on mouseleave', () => { - // Mousing over the first sort should set the view state to hint (asc) - component.dispatchMouseEvent('defaultA', 'mouseenter'); - expectedStates.set('defaultA', {viewState: 'asc-to-hint', arrowDirection: 'asc'}); - component.expectViewAndDirectionStates(expectedStates); - - // Mousing away from the first sort should hide the arrow - component.dispatchMouseEvent('defaultA', 'mouseleave'); - expectedStates.set('defaultA', {viewState: 'hint-to-asc', arrowDirection: 'asc'}); - component.expectViewAndDirectionStates(expectedStates); - - // Mousing over another sort should set the view state to hint (desc) - component.dispatchMouseEvent('overrideStart', 'mouseenter'); - expectedStates.set('overrideStart', {viewState: 'desc-to-hint', arrowDirection: 'desc'}); - component.expectViewAndDirectionStates(expectedStates); - }); - - it('should be correct when mousing over header and then sorting', () => { - // Mousing over the first sort should set the view state to hint - component.dispatchMouseEvent('defaultA', 'mouseenter'); - expectedStates.set('defaultA', {viewState: 'asc-to-hint', arrowDirection: 'asc'}); - component.expectViewAndDirectionStates(expectedStates); - - // Clicking sort on the header should set it to be active immediately - // (since it was already hinted) - component.dispatchMouseEvent('defaultA', 'click'); - expectedStates.set('defaultA', {viewState: 'active', arrowDirection: 'active-asc'}); - component.expectViewAndDirectionStates(expectedStates); - }); - - it('should be correct when cycling through a default sort header', () => { - // Sort the header to set it to the active start state - component.sort('defaultA'); - expectedStates.set('defaultA', {viewState: 'asc-to-active', arrowDirection: 'active-asc'}); - component.expectViewAndDirectionStates(expectedStates); - - // Sorting again will reverse its direction - component.dispatchMouseEvent('defaultA', 'click'); - expectedStates.set('defaultA', {viewState: 'active', arrowDirection: 'active-desc'}); - component.expectViewAndDirectionStates(expectedStates); - - // Sorting again will remove the sort and animate away the view - component.dispatchMouseEvent('defaultA', 'click'); - expectedStates.set('defaultA', {viewState: 'active-to-desc', arrowDirection: 'desc'}); - component.expectViewAndDirectionStates(expectedStates); - }); - - it('should not enter sort with animations if an animations is disabled', () => { - // Sort the header to set it to the active start state - component.defaultA._disableViewStateAnimation = true; - component.sort('defaultA'); - expectedStates.set('defaultA', {viewState: 'active', arrowDirection: 'active-asc'}); - component.expectViewAndDirectionStates(expectedStates); - - // Sorting again will reverse its direction - component.defaultA._disableViewStateAnimation = true; - component.dispatchMouseEvent('defaultA', 'click'); - expectedStates.set('defaultA', {viewState: 'active', arrowDirection: 'active-desc'}); - component.expectViewAndDirectionStates(expectedStates); - }); - - it('should be correct when sort has changed while a header is active', () => { - // Sort the first header to set up - component.sort('defaultA'); - expectedStates.set('defaultA', {viewState: 'asc-to-active', arrowDirection: 'active-asc'}); - component.expectViewAndDirectionStates(expectedStates); - - // Sort the second header and verify that the first header animated away - component.dispatchMouseEvent('defaultB', 'click'); - expectedStates.set('defaultA', {viewState: 'active-to-asc', arrowDirection: 'asc'}); - expectedStates.set('defaultB', {viewState: 'asc-to-active', arrowDirection: 'active-asc'}); - component.expectViewAndDirectionStates(expectedStates); - }); - - it('should be correct when sort has been disabled', () => { - // Mousing over the first sort should set the view state to hint - component.disabledColumnSort = true; - fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - - component.dispatchMouseEvent('defaultA', 'mouseenter'); - component.expectViewAndDirectionStates(expectedStates); - }); - - it('should be correct when sorting programmatically', () => { - component.active = 'defaultB'; - component.direction = 'asc'; - fixture.changeDetectorRef.markForCheck(); - fixture.detectChanges(); - - expectedStates.set('defaultB', {viewState: 'asc-to-active', arrowDirection: 'active-asc'}); - component.expectViewAndDirectionStates(expectedStates); - }); - }); - it('should be able to cycle from asc -> desc from either start point', () => { component.disableClear = true; @@ -328,54 +213,6 @@ describe('MatSort', () => { testSingleColumnSortDirectionSequence(fixture, ['asc', 'desc'], 'overrideDisableClear'); }); - it('should toggle indicator hint on button focus/blur and hide on click', () => { - const header = fixture.componentInstance.defaultA; - const container = fixture.nativeElement.querySelector('#defaultA .mat-sort-header-container'); - const focusEvent = createFakeEvent('focus'); - const blurEvent = createFakeEvent('blur'); - - // Should start without a displayed hint - expect(header._showIndicatorHint).toBeFalsy(); - - // Focusing the button should show the hint, blurring should hide it - container.dispatchEvent(focusEvent); - expect(header._showIndicatorHint).toBeTruthy(); - - container.dispatchEvent(blurEvent); - expect(header._showIndicatorHint).toBeFalsy(); - - // Show the indicator hint. On click the hint should be hidden - container.dispatchEvent(focusEvent); - expect(header._showIndicatorHint).toBeTruthy(); - - header._handleClick(); - expect(header._showIndicatorHint).toBeFalsy(); - }); - - it('should toggle indicator hint on mouseenter/mouseleave and hide on click', () => { - const header = fixture.componentInstance.defaultA; - const headerElement = fixture.nativeElement.querySelector('#defaultA'); - const mouseenterEvent = createMouseEvent('mouseenter'); - const mouseleaveEvent = createMouseEvent('mouseleave'); - - // Should start without a displayed hint - expect(header._showIndicatorHint).toBeFalsy(); - - // Mouse enter should show the hint, blurring should hide it - headerElement.dispatchEvent(mouseenterEvent); - expect(header._showIndicatorHint).toBeTruthy(); - - headerElement.dispatchEvent(mouseleaveEvent); - expect(header._showIndicatorHint).toBeFalsy(); - - // Show the indicator hint. On click the hint should be hidden - headerElement.dispatchEvent(mouseenterEvent); - expect(header._showIndicatorHint).toBeTruthy(); - - header._handleClick(); - expect(header._showIndicatorHint).toBeFalsy(); - }); - it('should apply the aria-sort label to the header when sorted', () => { const sortHeaderElement = fixture.nativeElement.querySelector('#defaultA'); expect(sortHeaderElement.getAttribute('aria-sort')).toBe('none'); @@ -701,27 +538,6 @@ class SimpleMatSortApp { const sortElement = this.elementRef.nativeElement.querySelector(`#${id}`)!; dispatchMouseEvent(sortElement, event); } - - /** - * Checks expectations for each sort header's view state and arrow direction states. Receives a - * map that is keyed by each sort header's ID and contains the expectation for that header's - * states. - */ - expectViewAndDirectionStates( - viewStates: Map, - ) { - const sortHeaders = new Map([ - ['defaultA', this.defaultA], - ['defaultB', this.defaultB], - ['overrideStart', this.overrideStart], - ['overrideDisableClear', this.overrideDisableClear], - ]); - - viewStates.forEach((viewState, id) => { - expect(sortHeaders.get(id)!._getArrowViewState()).toEqual(viewState.viewState); - expect(sortHeaders.get(id)!._getArrowDirectionState()).toEqual(viewState.arrowDirection); - }); - } } class FakeDataSource extends DataSource { diff --git a/tools/public_api_guard/material/sort.md b/tools/public_api_guard/material/sort.md index d1a5a95a515e..78eeabc38186 100644 --- a/tools/public_api_guard/material/sort.md +++ b/tools/public_api_guard/material/sort.md @@ -16,11 +16,12 @@ import { OnDestroy } from '@angular/core'; import { OnInit } from '@angular/core'; import { Optional } from '@angular/core'; import { Subject } from 'rxjs'; +import { WritableSignal } from '@angular/core'; -// @public +// @public @deprecated export type ArrowViewState = SortDirection | 'hint' | 'active'; -// @public +// @public @deprecated export interface ArrowViewStateTransition { // (undocumented) fromState?: ArrowViewState; @@ -81,7 +82,7 @@ export interface MatSortable { start: SortDirection; } -// @public +// @public @deprecated export const matSortAnimations: { readonly indicator: AnimationTriggerMetadata; readonly leftPointer: AnimationTriggerMetadata; @@ -100,18 +101,14 @@ export interface MatSortDefaultOptions { // @public export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewInit { constructor(...args: unknown[]); - _arrowDirection: SortDirection; + // (undocumented) + protected _animationModule: "NoopAnimations" | "BrowserAnimations" | null; arrowPosition: SortHeaderArrowPosition; // (undocumented) _columnDef: MatSortHeaderColumnDef | null; disableClear: boolean; disabled: boolean; - _disableViewStateAnimation: boolean; _getAriaSortAttribute(): "none" | "ascending" | "descending"; - _getArrowDirectionState(): string; - _getArrowViewState(): string; - // (undocumented) - _handleClick(): void; // (undocumented) _handleKeydown(event: KeyboardEvent): void; id: string; @@ -130,18 +127,14 @@ export class MatSortHeader implements MatSortable, OnDestroy, OnInit, AfterViewI ngOnDestroy(): void; // (undocumented) ngOnInit(): void; + protected _recentlyCleared: WritableSignal; _renderArrow(): boolean; - _setAnimationTransitionState(viewState: ArrowViewStateTransition): void; - _setIndicatorHintVisible(visible: boolean): void; - _showIndicatorHint: boolean; // (undocumented) _sort: MatSort; get sortActionDescription(): string; set sortActionDescription(value: string); start: SortDirection; _toggleOnInteraction(): void; - _updateArrowDirection(): void; - _viewState: ArrowViewStateTransition; // (undocumented) static ɵcmp: i0.ɵɵComponentDeclaration; // (undocumented)