[6a3a178] | 1 | import * as i0 from '@angular/core';
|
---|
| 2 | import { InjectionToken, EventEmitter, Directive, Optional, Inject, Input, Output, Injectable, SkipSelf, Component, ViewEncapsulation, ChangeDetectionStrategy, ChangeDetectorRef, ElementRef, NgModule } from '@angular/core';
|
---|
[fa375fe] | 3 | import { FocusMonitor, AriaDescriber } from '@angular/cdk/a11y';
|
---|
[6a3a178] | 4 | import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
---|
| 5 | import { SPACE, ENTER } from '@angular/cdk/keycodes';
|
---|
[fa375fe] | 6 | import { mixinInitialized, mixinDisabled, AnimationDurations, AnimationCurves, MatCommonModule } from '@angular/material/core';
|
---|
[6a3a178] | 7 | import { Subject, merge } from 'rxjs';
|
---|
| 8 | import { trigger, state, style, transition, animate, keyframes, query, animateChild } from '@angular/animations';
|
---|
| 9 | import { CommonModule } from '@angular/common';
|
---|
| 10 |
|
---|
| 11 | /**
|
---|
| 12 | * @license
|
---|
| 13 | * Copyright Google LLC All Rights Reserved.
|
---|
| 14 | *
|
---|
| 15 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 16 | * found in the LICENSE file at https://angular.io/license
|
---|
| 17 | */
|
---|
| 18 | /** @docs-private */
|
---|
| 19 | function getSortDuplicateSortableIdError(id) {
|
---|
| 20 | return Error(`Cannot have two MatSortables with the same id (${id}).`);
|
---|
| 21 | }
|
---|
| 22 | /** @docs-private */
|
---|
| 23 | function getSortHeaderNotContainedWithinSortError() {
|
---|
| 24 | return Error(`MatSortHeader must be placed within a parent element with the MatSort directive.`);
|
---|
| 25 | }
|
---|
| 26 | /** @docs-private */
|
---|
| 27 | function getSortHeaderMissingIdError() {
|
---|
| 28 | return Error(`MatSortHeader must be provided with a unique id.`);
|
---|
| 29 | }
|
---|
| 30 | /** @docs-private */
|
---|
| 31 | function getSortInvalidDirectionError(direction) {
|
---|
| 32 | return Error(`${direction} is not a valid sort direction ('asc' or 'desc').`);
|
---|
| 33 | }
|
---|
| 34 |
|
---|
| 35 | /**
|
---|
| 36 | * @license
|
---|
| 37 | * Copyright Google LLC All Rights Reserved.
|
---|
| 38 | *
|
---|
| 39 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 40 | * found in the LICENSE file at https://angular.io/license
|
---|
| 41 | */
|
---|
| 42 | /** Injection token to be used to override the default options for `mat-sort`. */
|
---|
| 43 | const MAT_SORT_DEFAULT_OPTIONS = new InjectionToken('MAT_SORT_DEFAULT_OPTIONS');
|
---|
| 44 | // Boilerplate for applying mixins to MatSort.
|
---|
| 45 | /** @docs-private */
|
---|
| 46 | const _MatSortBase = mixinInitialized(mixinDisabled(class {
|
---|
| 47 | }));
|
---|
| 48 | /** Container for MatSortables to manage the sort state and provide default sort parameters. */
|
---|
| 49 | class MatSort extends _MatSortBase {
|
---|
| 50 | constructor(_defaultOptions) {
|
---|
| 51 | super();
|
---|
| 52 | this._defaultOptions = _defaultOptions;
|
---|
| 53 | /** Collection of all registered sortables that this directive manages. */
|
---|
| 54 | this.sortables = new Map();
|
---|
| 55 | /** Used to notify any child components listening to state changes. */
|
---|
| 56 | this._stateChanges = new Subject();
|
---|
| 57 | /**
|
---|
| 58 | * The direction to set when an MatSortable is initially sorted.
|
---|
| 59 | * May be overriden by the MatSortable's sort start.
|
---|
| 60 | */
|
---|
| 61 | this.start = 'asc';
|
---|
| 62 | this._direction = '';
|
---|
| 63 | /** Event emitted when the user changes either the active sort or sort direction. */
|
---|
| 64 | this.sortChange = new EventEmitter();
|
---|
| 65 | }
|
---|
| 66 | /** The sort direction of the currently active MatSortable. */
|
---|
| 67 | get direction() { return this._direction; }
|
---|
| 68 | set direction(direction) {
|
---|
| 69 | if (direction && direction !== 'asc' && direction !== 'desc' &&
|
---|
| 70 | (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
---|
| 71 | throw getSortInvalidDirectionError(direction);
|
---|
| 72 | }
|
---|
| 73 | this._direction = direction;
|
---|
| 74 | }
|
---|
| 75 | /**
|
---|
| 76 | * Whether to disable the user from clearing the sort by finishing the sort direction cycle.
|
---|
| 77 | * May be overriden by the MatSortable's disable clear input.
|
---|
| 78 | */
|
---|
| 79 | get disableClear() { return this._disableClear; }
|
---|
| 80 | set disableClear(v) { this._disableClear = coerceBooleanProperty(v); }
|
---|
| 81 | /**
|
---|
| 82 | * Register function to be used by the contained MatSortables. Adds the MatSortable to the
|
---|
| 83 | * collection of MatSortables.
|
---|
| 84 | */
|
---|
| 85 | register(sortable) {
|
---|
| 86 | if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
---|
| 87 | if (!sortable.id) {
|
---|
| 88 | throw getSortHeaderMissingIdError();
|
---|
| 89 | }
|
---|
| 90 | if (this.sortables.has(sortable.id)) {
|
---|
| 91 | throw getSortDuplicateSortableIdError(sortable.id);
|
---|
| 92 | }
|
---|
| 93 | }
|
---|
| 94 | this.sortables.set(sortable.id, sortable);
|
---|
| 95 | }
|
---|
| 96 | /**
|
---|
| 97 | * Unregister function to be used by the contained MatSortables. Removes the MatSortable from the
|
---|
| 98 | * collection of contained MatSortables.
|
---|
| 99 | */
|
---|
| 100 | deregister(sortable) {
|
---|
| 101 | this.sortables.delete(sortable.id);
|
---|
| 102 | }
|
---|
| 103 | /** Sets the active sort id and determines the new sort direction. */
|
---|
| 104 | sort(sortable) {
|
---|
| 105 | if (this.active != sortable.id) {
|
---|
| 106 | this.active = sortable.id;
|
---|
| 107 | this.direction = sortable.start ? sortable.start : this.start;
|
---|
| 108 | }
|
---|
| 109 | else {
|
---|
| 110 | this.direction = this.getNextSortDirection(sortable);
|
---|
| 111 | }
|
---|
| 112 | this.sortChange.emit({ active: this.active, direction: this.direction });
|
---|
| 113 | }
|
---|
| 114 | /** Returns the next sort direction of the active sortable, checking for potential overrides. */
|
---|
| 115 | getNextSortDirection(sortable) {
|
---|
| 116 | var _a, _b, _c;
|
---|
| 117 | if (!sortable) {
|
---|
| 118 | return '';
|
---|
| 119 | }
|
---|
| 120 | // Get the sort direction cycle with the potential sortable overrides.
|
---|
| 121 | const disableClear = (_b = (_a = sortable === null || sortable === void 0 ? void 0 : sortable.disableClear) !== null && _a !== void 0 ? _a : this.disableClear) !== null && _b !== void 0 ? _b : !!((_c = this._defaultOptions) === null || _c === void 0 ? void 0 : _c.disableClear);
|
---|
| 122 | let sortDirectionCycle = getSortDirectionCycle(sortable.start || this.start, disableClear);
|
---|
| 123 | // Get and return the next direction in the cycle
|
---|
| 124 | let nextDirectionIndex = sortDirectionCycle.indexOf(this.direction) + 1;
|
---|
| 125 | if (nextDirectionIndex >= sortDirectionCycle.length) {
|
---|
| 126 | nextDirectionIndex = 0;
|
---|
| 127 | }
|
---|
| 128 | return sortDirectionCycle[nextDirectionIndex];
|
---|
| 129 | }
|
---|
| 130 | ngOnInit() {
|
---|
| 131 | this._markInitialized();
|
---|
| 132 | }
|
---|
| 133 | ngOnChanges() {
|
---|
| 134 | this._stateChanges.next();
|
---|
| 135 | }
|
---|
| 136 | ngOnDestroy() {
|
---|
| 137 | this._stateChanges.complete();
|
---|
| 138 | }
|
---|
| 139 | }
|
---|
| 140 | MatSort.decorators = [
|
---|
| 141 | { type: Directive, args: [{
|
---|
| 142 | selector: '[matSort]',
|
---|
| 143 | exportAs: 'matSort',
|
---|
| 144 | host: { 'class': 'mat-sort' },
|
---|
| 145 | inputs: ['disabled: matSortDisabled']
|
---|
| 146 | },] }
|
---|
| 147 | ];
|
---|
| 148 | MatSort.ctorParameters = () => [
|
---|
| 149 | { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [MAT_SORT_DEFAULT_OPTIONS,] }] }
|
---|
| 150 | ];
|
---|
| 151 | MatSort.propDecorators = {
|
---|
| 152 | active: [{ type: Input, args: ['matSortActive',] }],
|
---|
| 153 | start: [{ type: Input, args: ['matSortStart',] }],
|
---|
| 154 | direction: [{ type: Input, args: ['matSortDirection',] }],
|
---|
| 155 | disableClear: [{ type: Input, args: ['matSortDisableClear',] }],
|
---|
| 156 | sortChange: [{ type: Output, args: ['matSortChange',] }]
|
---|
| 157 | };
|
---|
| 158 | /** Returns the sort direction cycle to use given the provided parameters of order and clear. */
|
---|
| 159 | function getSortDirectionCycle(start, disableClear) {
|
---|
| 160 | let sortOrder = ['asc', 'desc'];
|
---|
| 161 | if (start == 'desc') {
|
---|
| 162 | sortOrder.reverse();
|
---|
| 163 | }
|
---|
| 164 | if (!disableClear) {
|
---|
| 165 | sortOrder.push('');
|
---|
| 166 | }
|
---|
| 167 | return sortOrder;
|
---|
| 168 | }
|
---|
| 169 |
|
---|
| 170 | /**
|
---|
| 171 | * @license
|
---|
| 172 | * Copyright Google LLC All Rights Reserved.
|
---|
| 173 | *
|
---|
| 174 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 175 | * found in the LICENSE file at https://angular.io/license
|
---|
| 176 | */
|
---|
| 177 | const SORT_ANIMATION_TRANSITION = AnimationDurations.ENTERING + ' ' +
|
---|
| 178 | AnimationCurves.STANDARD_CURVE;
|
---|
| 179 | /**
|
---|
| 180 | * Animations used by MatSort.
|
---|
| 181 | * @docs-private
|
---|
| 182 | */
|
---|
| 183 | const matSortAnimations = {
|
---|
| 184 | /** Animation that moves the sort indicator. */
|
---|
| 185 | indicator: trigger('indicator', [
|
---|
| 186 | state('active-asc, asc', style({ transform: 'translateY(0px)' })),
|
---|
| 187 | // 10px is the height of the sort indicator, minus the width of the pointers
|
---|
| 188 | state('active-desc, desc', style({ transform: 'translateY(10px)' })),
|
---|
| 189 | transition('active-asc <=> active-desc', animate(SORT_ANIMATION_TRANSITION))
|
---|
| 190 | ]),
|
---|
| 191 | /** Animation that rotates the left pointer of the indicator based on the sorting direction. */
|
---|
| 192 | leftPointer: trigger('leftPointer', [
|
---|
| 193 | state('active-asc, asc', style({ transform: 'rotate(-45deg)' })),
|
---|
| 194 | state('active-desc, desc', style({ transform: 'rotate(45deg)' })),
|
---|
| 195 | transition('active-asc <=> active-desc', animate(SORT_ANIMATION_TRANSITION))
|
---|
| 196 | ]),
|
---|
| 197 | /** Animation that rotates the right pointer of the indicator based on the sorting direction. */
|
---|
| 198 | rightPointer: trigger('rightPointer', [
|
---|
| 199 | state('active-asc, asc', style({ transform: 'rotate(45deg)' })),
|
---|
| 200 | state('active-desc, desc', style({ transform: 'rotate(-45deg)' })),
|
---|
| 201 | transition('active-asc <=> active-desc', animate(SORT_ANIMATION_TRANSITION))
|
---|
| 202 | ]),
|
---|
| 203 | /** Animation that controls the arrow opacity. */
|
---|
| 204 | arrowOpacity: trigger('arrowOpacity', [
|
---|
| 205 | state('desc-to-active, asc-to-active, active', style({ opacity: 1 })),
|
---|
| 206 | state('desc-to-hint, asc-to-hint, hint', style({ opacity: .54 })),
|
---|
| 207 | state('hint-to-desc, active-to-desc, desc, hint-to-asc, active-to-asc, asc, void', style({ opacity: 0 })),
|
---|
| 208 | // Transition between all states except for immediate transitions
|
---|
| 209 | transition('* => asc, * => desc, * => active, * => hint, * => void', animate('0ms')),
|
---|
| 210 | transition('* <=> *', animate(SORT_ANIMATION_TRANSITION)),
|
---|
| 211 | ]),
|
---|
| 212 | /**
|
---|
| 213 | * Animation for the translation of the arrow as a whole. States are separated into two
|
---|
| 214 | * groups: ones with animations and others that are immediate. Immediate states are asc, desc,
|
---|
| 215 | * peek, and active. The other states define a specific animation (source-to-destination)
|
---|
| 216 | * and are determined as a function of their prev user-perceived state and what the next state
|
---|
| 217 | * should be.
|
---|
| 218 | */
|
---|
| 219 | arrowPosition: trigger('arrowPosition', [
|
---|
| 220 | // Hidden Above => Hint Center
|
---|
| 221 | transition('* => desc-to-hint, * => desc-to-active', animate(SORT_ANIMATION_TRANSITION, keyframes([
|
---|
| 222 | style({ transform: 'translateY(-25%)' }),
|
---|
| 223 | style({ transform: 'translateY(0)' })
|
---|
| 224 | ]))),
|
---|
| 225 | // Hint Center => Hidden Below
|
---|
| 226 | transition('* => hint-to-desc, * => active-to-desc', animate(SORT_ANIMATION_TRANSITION, keyframes([
|
---|
| 227 | style({ transform: 'translateY(0)' }),
|
---|
| 228 | style({ transform: 'translateY(25%)' })
|
---|
| 229 | ]))),
|
---|
| 230 | // Hidden Below => Hint Center
|
---|
| 231 | transition('* => asc-to-hint, * => asc-to-active', animate(SORT_ANIMATION_TRANSITION, keyframes([
|
---|
| 232 | style({ transform: 'translateY(25%)' }),
|
---|
| 233 | style({ transform: 'translateY(0)' })
|
---|
| 234 | ]))),
|
---|
| 235 | // Hint Center => Hidden Above
|
---|
| 236 | transition('* => hint-to-asc, * => active-to-asc', animate(SORT_ANIMATION_TRANSITION, keyframes([
|
---|
| 237 | style({ transform: 'translateY(0)' }),
|
---|
| 238 | style({ transform: 'translateY(-25%)' })
|
---|
| 239 | ]))),
|
---|
| 240 | state('desc-to-hint, asc-to-hint, hint, desc-to-active, asc-to-active, active', style({ transform: 'translateY(0)' })),
|
---|
| 241 | state('hint-to-desc, active-to-desc, desc', style({ transform: 'translateY(-25%)' })),
|
---|
| 242 | state('hint-to-asc, active-to-asc, asc', style({ transform: 'translateY(25%)' })),
|
---|
| 243 | ]),
|
---|
| 244 | /** Necessary trigger that calls animate on children animations. */
|
---|
| 245 | allowChildren: trigger('allowChildren', [
|
---|
| 246 | transition('* <=> *', [
|
---|
| 247 | query('@*', animateChild(), { optional: true })
|
---|
| 248 | ])
|
---|
| 249 | ]),
|
---|
| 250 | };
|
---|
| 251 |
|
---|
| 252 | /**
|
---|
| 253 | * @license
|
---|
| 254 | * Copyright Google LLC All Rights Reserved.
|
---|
| 255 | *
|
---|
| 256 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 257 | * found in the LICENSE file at https://angular.io/license
|
---|
| 258 | */
|
---|
| 259 | /**
|
---|
| 260 | * To modify the labels and text displayed, create a new instance of MatSortHeaderIntl and
|
---|
| 261 | * include it in a custom provider.
|
---|
| 262 | */
|
---|
| 263 | class MatSortHeaderIntl {
|
---|
| 264 | constructor() {
|
---|
| 265 | /**
|
---|
| 266 | * Stream that emits whenever the labels here are changed. Use this to notify
|
---|
| 267 | * components if the labels have changed after initialization.
|
---|
| 268 | */
|
---|
| 269 | this.changes = new Subject();
|
---|
| 270 | }
|
---|
| 271 | }
|
---|
| 272 | MatSortHeaderIntl.ɵprov = i0.ɵɵdefineInjectable({ factory: function MatSortHeaderIntl_Factory() { return new MatSortHeaderIntl(); }, token: MatSortHeaderIntl, providedIn: "root" });
|
---|
| 273 | MatSortHeaderIntl.decorators = [
|
---|
| 274 | { type: Injectable, args: [{ providedIn: 'root' },] }
|
---|
| 275 | ];
|
---|
| 276 | /** @docs-private */
|
---|
| 277 | function MAT_SORT_HEADER_INTL_PROVIDER_FACTORY(parentIntl) {
|
---|
| 278 | return parentIntl || new MatSortHeaderIntl();
|
---|
| 279 | }
|
---|
| 280 | /** @docs-private */
|
---|
| 281 | const MAT_SORT_HEADER_INTL_PROVIDER = {
|
---|
| 282 | // If there is already an MatSortHeaderIntl available, use that. Otherwise, provide a new one.
|
---|
| 283 | provide: MatSortHeaderIntl,
|
---|
| 284 | deps: [[new Optional(), new SkipSelf(), MatSortHeaderIntl]],
|
---|
| 285 | useFactory: MAT_SORT_HEADER_INTL_PROVIDER_FACTORY
|
---|
| 286 | };
|
---|
| 287 |
|
---|
| 288 | /**
|
---|
| 289 | * @license
|
---|
| 290 | * Copyright Google LLC All Rights Reserved.
|
---|
| 291 | *
|
---|
| 292 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 293 | * found in the LICENSE file at https://angular.io/license
|
---|
| 294 | */
|
---|
| 295 | // Boilerplate for applying mixins to the sort header.
|
---|
| 296 | /** @docs-private */
|
---|
| 297 | const _MatSortHeaderBase = mixinDisabled(class {
|
---|
| 298 | });
|
---|
| 299 | /**
|
---|
| 300 | * Applies sorting behavior (click to change sort) and styles to an element, including an
|
---|
| 301 | * arrow to display the current sort direction.
|
---|
| 302 | *
|
---|
| 303 | * Must be provided with an id and contained within a parent MatSort directive.
|
---|
| 304 | *
|
---|
| 305 | * If used on header cells in a CdkTable, it will automatically default its id from its containing
|
---|
| 306 | * column definition.
|
---|
| 307 | */
|
---|
| 308 | class MatSortHeader extends _MatSortHeaderBase {
|
---|
| 309 | constructor(
|
---|
| 310 | /**
|
---|
| 311 | * @deprecated `_intl` parameter isn't being used anymore and it'll be removed.
|
---|
| 312 | * @breaking-change 13.0.0
|
---|
| 313 | */
|
---|
| 314 | _intl, _changeDetectorRef,
|
---|
| 315 | // `MatSort` is not optionally injected, but just asserted manually w/ better error.
|
---|
| 316 | // tslint:disable-next-line: lightweight-tokens
|
---|
[fa375fe] | 317 | _sort, _columnDef, _focusMonitor, _elementRef,
|
---|
| 318 | /** @breaking-change 14.0.0 _ariaDescriber will be required. */
|
---|
| 319 | _ariaDescriber) {
|
---|
[6a3a178] | 320 | // Note that we use a string token for the `_columnDef`, because the value is provided both by
|
---|
| 321 | // `material/table` and `cdk/table` and we can't have the CDK depending on Material,
|
---|
| 322 | // and we want to avoid having the sort header depending on the CDK table because
|
---|
| 323 | // of this single reference.
|
---|
| 324 | super();
|
---|
| 325 | this._intl = _intl;
|
---|
| 326 | this._changeDetectorRef = _changeDetectorRef;
|
---|
| 327 | this._sort = _sort;
|
---|
| 328 | this._columnDef = _columnDef;
|
---|
| 329 | this._focusMonitor = _focusMonitor;
|
---|
| 330 | this._elementRef = _elementRef;
|
---|
[fa375fe] | 331 | this._ariaDescriber = _ariaDescriber;
|
---|
[6a3a178] | 332 | /**
|
---|
| 333 | * Flag set to true when the indicator should be displayed while the sort is not active. Used to
|
---|
| 334 | * provide an affordance that the header is sortable by showing on focus and hover.
|
---|
| 335 | */
|
---|
| 336 | this._showIndicatorHint = false;
|
---|
| 337 | /**
|
---|
| 338 | * The view transition state of the arrow (translation/ opacity) - indicates its `from` and `to`
|
---|
| 339 | * position through the animation. If animations are currently disabled, the fromState is removed
|
---|
| 340 | * so that there is no animation displayed.
|
---|
| 341 | */
|
---|
| 342 | this._viewState = {};
|
---|
| 343 | /** The direction the arrow should be facing according to the current state. */
|
---|
| 344 | this._arrowDirection = '';
|
---|
| 345 | /**
|
---|
| 346 | * Whether the view state animation should show the transition between the `from` and `to` states.
|
---|
| 347 | */
|
---|
| 348 | this._disableViewStateAnimation = false;
|
---|
| 349 | /** Sets the position of the arrow that displays when sorted. */
|
---|
| 350 | this.arrowPosition = 'after';
|
---|
[fa375fe] | 351 | // Default the action description to "Sort" because it's better than nothing.
|
---|
| 352 | // Without a description, the button's label comes from the sort header text content,
|
---|
| 353 | // which doesn't give any indication that it performs a sorting operation.
|
---|
| 354 | this._sortActionDescription = 'Sort';
|
---|
[6a3a178] | 355 | if (!_sort && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
---|
| 356 | throw getSortHeaderNotContainedWithinSortError();
|
---|
| 357 | }
|
---|
| 358 | this._handleStateChanges();
|
---|
| 359 | }
|
---|
[fa375fe] | 360 | /**
|
---|
| 361 | * Description applied to MatSortHeader's button element with aria-describedby. This text should
|
---|
| 362 | * describe the action that will occur when the user clicks the sort header.
|
---|
| 363 | */
|
---|
| 364 | get sortActionDescription() {
|
---|
| 365 | return this._sortActionDescription;
|
---|
| 366 | }
|
---|
| 367 | set sortActionDescription(value) {
|
---|
| 368 | this._updateSortActionDescription(value);
|
---|
| 369 | }
|
---|
[6a3a178] | 370 | /** Overrides the disable clear value of the containing MatSort for this MatSortable. */
|
---|
| 371 | get disableClear() { return this._disableClear; }
|
---|
| 372 | set disableClear(v) { this._disableClear = coerceBooleanProperty(v); }
|
---|
| 373 | ngOnInit() {
|
---|
| 374 | if (!this.id && this._columnDef) {
|
---|
| 375 | this.id = this._columnDef.name;
|
---|
| 376 | }
|
---|
| 377 | // Initialize the direction of the arrow and set the view state to be immediately that state.
|
---|
| 378 | this._updateArrowDirection();
|
---|
| 379 | this._setAnimationTransitionState({ toState: this._isSorted() ? 'active' : this._arrowDirection });
|
---|
| 380 | this._sort.register(this);
|
---|
[fa375fe] | 381 | this._sortButton = this._elementRef.nativeElement.querySelector('[role="button"]');
|
---|
| 382 | this._updateSortActionDescription(this._sortActionDescription);
|
---|
[6a3a178] | 383 | }
|
---|
| 384 | ngAfterViewInit() {
|
---|
| 385 | // We use the focus monitor because we also want to style
|
---|
| 386 | // things differently based on the focus origin.
|
---|
| 387 | this._focusMonitor.monitor(this._elementRef, true).subscribe(origin => {
|
---|
| 388 | const newState = !!origin;
|
---|
| 389 | if (newState !== this._showIndicatorHint) {
|
---|
| 390 | this._setIndicatorHintVisible(newState);
|
---|
| 391 | this._changeDetectorRef.markForCheck();
|
---|
| 392 | }
|
---|
| 393 | });
|
---|
| 394 | }
|
---|
| 395 | ngOnDestroy() {
|
---|
| 396 | this._focusMonitor.stopMonitoring(this._elementRef);
|
---|
| 397 | this._sort.deregister(this);
|
---|
| 398 | this._rerenderSubscription.unsubscribe();
|
---|
| 399 | }
|
---|
| 400 | /**
|
---|
| 401 | * Sets the "hint" state such that the arrow will be semi-transparently displayed as a hint to the
|
---|
| 402 | * user showing what the active sort will become. If set to false, the arrow will fade away.
|
---|
| 403 | */
|
---|
| 404 | _setIndicatorHintVisible(visible) {
|
---|
| 405 | // No-op if the sort header is disabled - should not make the hint visible.
|
---|
| 406 | if (this._isDisabled() && visible) {
|
---|
| 407 | return;
|
---|
| 408 | }
|
---|
| 409 | this._showIndicatorHint = visible;
|
---|
| 410 | if (!this._isSorted()) {
|
---|
| 411 | this._updateArrowDirection();
|
---|
| 412 | if (this._showIndicatorHint) {
|
---|
| 413 | this._setAnimationTransitionState({ fromState: this._arrowDirection, toState: 'hint' });
|
---|
| 414 | }
|
---|
| 415 | else {
|
---|
| 416 | this._setAnimationTransitionState({ fromState: 'hint', toState: this._arrowDirection });
|
---|
| 417 | }
|
---|
| 418 | }
|
---|
| 419 | }
|
---|
| 420 | /**
|
---|
| 421 | * Sets the animation transition view state for the arrow's position and opacity. If the
|
---|
| 422 | * `disableViewStateAnimation` flag is set to true, the `fromState` will be ignored so that
|
---|
| 423 | * no animation appears.
|
---|
| 424 | */
|
---|
| 425 | _setAnimationTransitionState(viewState) {
|
---|
| 426 | this._viewState = viewState || {};
|
---|
| 427 | // If the animation for arrow position state (opacity/translation) should be disabled,
|
---|
| 428 | // remove the fromState so that it jumps right to the toState.
|
---|
| 429 | if (this._disableViewStateAnimation) {
|
---|
| 430 | this._viewState = { toState: viewState.toState };
|
---|
| 431 | }
|
---|
| 432 | }
|
---|
| 433 | /** Triggers the sort on this sort header and removes the indicator hint. */
|
---|
| 434 | _toggleOnInteraction() {
|
---|
| 435 | this._sort.sort(this);
|
---|
| 436 | // Do not show the animation if the header was already shown in the right position.
|
---|
| 437 | if (this._viewState.toState === 'hint' || this._viewState.toState === 'active') {
|
---|
| 438 | this._disableViewStateAnimation = true;
|
---|
| 439 | }
|
---|
| 440 | }
|
---|
| 441 | _handleClick() {
|
---|
| 442 | if (!this._isDisabled()) {
|
---|
| 443 | this._sort.sort(this);
|
---|
| 444 | }
|
---|
| 445 | }
|
---|
| 446 | _handleKeydown(event) {
|
---|
| 447 | if (!this._isDisabled() && (event.keyCode === SPACE || event.keyCode === ENTER)) {
|
---|
| 448 | event.preventDefault();
|
---|
| 449 | this._toggleOnInteraction();
|
---|
| 450 | }
|
---|
| 451 | }
|
---|
| 452 | /** Whether this MatSortHeader is currently sorted in either ascending or descending order. */
|
---|
| 453 | _isSorted() {
|
---|
| 454 | return this._sort.active == this.id &&
|
---|
| 455 | (this._sort.direction === 'asc' || this._sort.direction === 'desc');
|
---|
| 456 | }
|
---|
| 457 | /** Returns the animation state for the arrow direction (indicator and pointers). */
|
---|
| 458 | _getArrowDirectionState() {
|
---|
| 459 | return `${this._isSorted() ? 'active-' : ''}${this._arrowDirection}`;
|
---|
| 460 | }
|
---|
| 461 | /** Returns the arrow position state (opacity, translation). */
|
---|
| 462 | _getArrowViewState() {
|
---|
| 463 | const fromState = this._viewState.fromState;
|
---|
| 464 | return (fromState ? `${fromState}-to-` : '') + this._viewState.toState;
|
---|
| 465 | }
|
---|
| 466 | /**
|
---|
| 467 | * Updates the direction the arrow should be pointing. If it is not sorted, the arrow should be
|
---|
| 468 | * facing the start direction. Otherwise if it is sorted, the arrow should point in the currently
|
---|
| 469 | * active sorted direction. The reason this is updated through a function is because the direction
|
---|
| 470 | * should only be changed at specific times - when deactivated but the hint is displayed and when
|
---|
| 471 | * the sort is active and the direction changes. Otherwise the arrow's direction should linger
|
---|
| 472 | * in cases such as the sort becoming deactivated but we want to animate the arrow away while
|
---|
| 473 | * preserving its direction, even though the next sort direction is actually different and should
|
---|
| 474 | * only be changed once the arrow displays again (hint or activation).
|
---|
| 475 | */
|
---|
| 476 | _updateArrowDirection() {
|
---|
| 477 | this._arrowDirection = this._isSorted() ?
|
---|
| 478 | this._sort.direction :
|
---|
| 479 | (this.start || this._sort.start);
|
---|
| 480 | }
|
---|
| 481 | _isDisabled() {
|
---|
| 482 | return this._sort.disabled || this.disabled;
|
---|
| 483 | }
|
---|
| 484 | /**
|
---|
| 485 | * Gets the aria-sort attribute that should be applied to this sort header. If this header
|
---|
| 486 | * is not sorted, returns null so that the attribute is removed from the host element. Aria spec
|
---|
| 487 | * says that the aria-sort property should only be present on one header at a time, so removing
|
---|
| 488 | * ensures this is true.
|
---|
| 489 | */
|
---|
| 490 | _getAriaSortAttribute() {
|
---|
| 491 | if (!this._isSorted()) {
|
---|
| 492 | return 'none';
|
---|
| 493 | }
|
---|
| 494 | return this._sort.direction == 'asc' ? 'ascending' : 'descending';
|
---|
| 495 | }
|
---|
| 496 | /** Whether the arrow inside the sort header should be rendered. */
|
---|
| 497 | _renderArrow() {
|
---|
| 498 | return !this._isDisabled() || this._isSorted();
|
---|
| 499 | }
|
---|
[fa375fe] | 500 | _updateSortActionDescription(newDescription) {
|
---|
| 501 | // We use AriaDescriber for the sort button instead of setting an `aria-label` because some
|
---|
| 502 | // screen readers (notably VoiceOver) will read both the column header *and* the button's label
|
---|
| 503 | // for every *cell* in the table, creating a lot of unnecessary noise.
|
---|
| 504 | var _a, _b;
|
---|
| 505 | // If _sortButton is undefined, the component hasn't been initialized yet so there's
|
---|
| 506 | // nothing to update in the DOM.
|
---|
| 507 | if (this._sortButton) {
|
---|
| 508 | // removeDescription will no-op if there is no existing message.
|
---|
| 509 | // TODO(jelbourn): remove optional chaining when AriaDescriber is required.
|
---|
| 510 | (_a = this._ariaDescriber) === null || _a === void 0 ? void 0 : _a.removeDescription(this._sortButton, this._sortActionDescription);
|
---|
| 511 | (_b = this._ariaDescriber) === null || _b === void 0 ? void 0 : _b.describe(this._sortButton, newDescription);
|
---|
| 512 | }
|
---|
| 513 | this._sortActionDescription = newDescription;
|
---|
| 514 | }
|
---|
[6a3a178] | 515 | /** Handles changes in the sorting state. */
|
---|
| 516 | _handleStateChanges() {
|
---|
| 517 | this._rerenderSubscription =
|
---|
| 518 | merge(this._sort.sortChange, this._sort._stateChanges, this._intl.changes).subscribe(() => {
|
---|
| 519 | if (this._isSorted()) {
|
---|
| 520 | this._updateArrowDirection();
|
---|
| 521 | // Do not show the animation if the header was already shown in the right position.
|
---|
| 522 | if (this._viewState.toState === 'hint' || this._viewState.toState === 'active') {
|
---|
| 523 | this._disableViewStateAnimation = true;
|
---|
| 524 | }
|
---|
| 525 | this._setAnimationTransitionState({ fromState: this._arrowDirection, toState: 'active' });
|
---|
| 526 | this._showIndicatorHint = false;
|
---|
| 527 | }
|
---|
| 528 | // If this header was recently active and now no longer sorted, animate away the arrow.
|
---|
| 529 | if (!this._isSorted() && this._viewState && this._viewState.toState === 'active') {
|
---|
| 530 | this._disableViewStateAnimation = false;
|
---|
| 531 | this._setAnimationTransitionState({ fromState: 'active', toState: this._arrowDirection });
|
---|
| 532 | }
|
---|
| 533 | this._changeDetectorRef.markForCheck();
|
---|
| 534 | });
|
---|
| 535 | }
|
---|
| 536 | }
|
---|
| 537 | MatSortHeader.decorators = [
|
---|
| 538 | { type: Component, args: [{
|
---|
| 539 | selector: '[mat-sort-header]',
|
---|
| 540 | exportAs: 'matSortHeader',
|
---|
| 541 | template: "<!--\n We set the `tabindex` on an element inside the table header, rather than the header itself,\n because of a bug in NVDA where having a `tabindex` on a `th` breaks keyboard navigation in the\n table (see https://github.com/nvaccess/nvda/issues/7718). This allows for the header to both\n be focusable, and have screen readers read out its `aria-sort` state. We prefer this approach\n over having a button with an `aria-label` inside the header, because the button's `aria-label`\n will be read out as the user is navigating the table's cell (see #13012).\n\n The approach is based off of: https://dequeuniversity.com/library/aria/tables/sf-sortable-grid\n-->\n<div class=\"mat-sort-header-container mat-focus-indicator\"\n [class.mat-sort-header-sorted]=\"_isSorted()\"\n [class.mat-sort-header-position-before]=\"arrowPosition == 'before'\"\n [attr.tabindex]=\"_isDisabled() ? null : 0\"\n role=\"button\">\n\n <!--\n TODO(crisbeto): this div isn't strictly necessary, but we have to keep it due to a large\n number of screenshot diff failures. It should be removed eventually. Note that the difference\n isn't visible with a shorter header, but once it breaks up into multiple lines, this element\n causes it to be center-aligned, whereas removing it will keep the text to the left.\n -->\n <div class=\"mat-sort-header-content\">\n <ng-content></ng-content>\n </div>\n\n <!-- Disable animations while a current animation is running -->\n <div class=\"mat-sort-header-arrow\"\n *ngIf=\"_renderArrow()\"\n [@arrowOpacity]=\"_getArrowViewState()\"\n [@arrowPosition]=\"_getArrowViewState()\"\n [@allowChildren]=\"_getArrowDirectionState()\"\n (@arrowPosition.start)=\"_disableViewStateAnimation = true\"\n (@arrowPosition.done)=\"_disableViewStateAnimation = false\">\n <div class=\"mat-sort-header-stem\"></div>\n <div class=\"mat-sort-header-indicator\" [@indicator]=\"_getArrowDirectionState()\">\n <div class=\"mat-sort-header-pointer-left\" [@leftPointer]=\"_getArrowDirectionState()\"></div>\n <div class=\"mat-sort-header-pointer-right\" [@rightPointer]=\"_getArrowDirectionState()\"></div>\n <div class=\"mat-sort-header-pointer-middle\"></div>\n </div>\n </div>\n</div>\n",
|
---|
| 542 | host: {
|
---|
| 543 | 'class': 'mat-sort-header',
|
---|
| 544 | '(click)': '_handleClick()',
|
---|
| 545 | '(keydown)': '_handleKeydown($event)',
|
---|
| 546 | '(mouseenter)': '_setIndicatorHintVisible(true)',
|
---|
| 547 | '(mouseleave)': '_setIndicatorHintVisible(false)',
|
---|
| 548 | '[attr.aria-sort]': '_getAriaSortAttribute()',
|
---|
| 549 | '[class.mat-sort-header-disabled]': '_isDisabled()',
|
---|
| 550 | },
|
---|
| 551 | encapsulation: ViewEncapsulation.None,
|
---|
| 552 | changeDetection: ChangeDetectionStrategy.OnPush,
|
---|
| 553 | inputs: ['disabled'],
|
---|
| 554 | animations: [
|
---|
| 555 | matSortAnimations.indicator,
|
---|
| 556 | matSortAnimations.leftPointer,
|
---|
| 557 | matSortAnimations.rightPointer,
|
---|
| 558 | matSortAnimations.arrowOpacity,
|
---|
| 559 | matSortAnimations.arrowPosition,
|
---|
| 560 | matSortAnimations.allowChildren,
|
---|
| 561 | ],
|
---|
| 562 | styles: [".mat-sort-header-container{display:flex;cursor:pointer;align-items:center;letter-spacing:normal;outline:0}[mat-sort-header].cdk-keyboard-focused .mat-sort-header-container,[mat-sort-header].cdk-program-focused .mat-sort-header-container{border-bottom:solid 1px currentColor}.mat-sort-header-disabled .mat-sort-header-container{cursor:default}.mat-sort-header-content{text-align:center;display:flex;align-items:center}.mat-sort-header-position-before{flex-direction:row-reverse}.mat-sort-header-arrow{height:12px;width:12px;min-width:12px;position:relative;display:flex;opacity:0}.mat-sort-header-arrow,[dir=rtl] .mat-sort-header-position-before .mat-sort-header-arrow{margin:0 0 0 6px}.mat-sort-header-position-before .mat-sort-header-arrow,[dir=rtl] .mat-sort-header-arrow{margin:0 6px 0 0}.mat-sort-header-stem{background:currentColor;height:10px;width:2px;margin:auto;display:flex;align-items:center}.cdk-high-contrast-active .mat-sort-header-stem{width:0;border-left:solid 2px}.mat-sort-header-indicator{width:100%;height:2px;display:flex;align-items:center;position:absolute;top:0;left:0}.mat-sort-header-pointer-middle{margin:auto;height:2px;width:2px;background:currentColor;transform:rotate(45deg)}.cdk-high-contrast-active .mat-sort-header-pointer-middle{width:0;height:0;border-top:solid 2px;border-left:solid 2px}.mat-sort-header-pointer-left,.mat-sort-header-pointer-right{background:currentColor;width:6px;height:2px;position:absolute;top:0}.cdk-high-contrast-active .mat-sort-header-pointer-left,.cdk-high-contrast-active .mat-sort-header-pointer-right{width:0;height:0;border-left:solid 6px;border-top:solid 2px}.mat-sort-header-pointer-left{transform-origin:right;left:0}.mat-sort-header-pointer-right{transform-origin:left;right:0}\n"]
|
---|
| 563 | },] }
|
---|
| 564 | ];
|
---|
| 565 | MatSortHeader.ctorParameters = () => [
|
---|
| 566 | { type: MatSortHeaderIntl },
|
---|
| 567 | { type: ChangeDetectorRef },
|
---|
| 568 | { type: MatSort, decorators: [{ type: Optional }] },
|
---|
| 569 | { type: undefined, decorators: [{ type: Inject, args: ['MAT_SORT_HEADER_COLUMN_DEF',] }, { type: Optional }] },
|
---|
| 570 | { type: FocusMonitor },
|
---|
[fa375fe] | 571 | { type: ElementRef },
|
---|
| 572 | { type: AriaDescriber, decorators: [{ type: Inject, args: [AriaDescriber,] }, { type: Optional }] }
|
---|
[6a3a178] | 573 | ];
|
---|
| 574 | MatSortHeader.propDecorators = {
|
---|
| 575 | id: [{ type: Input, args: ['mat-sort-header',] }],
|
---|
| 576 | arrowPosition: [{ type: Input }],
|
---|
| 577 | start: [{ type: Input }],
|
---|
[fa375fe] | 578 | sortActionDescription: [{ type: Input }],
|
---|
[6a3a178] | 579 | disableClear: [{ type: Input }]
|
---|
| 580 | };
|
---|
| 581 |
|
---|
| 582 | /**
|
---|
| 583 | * @license
|
---|
| 584 | * Copyright Google LLC All Rights Reserved.
|
---|
| 585 | *
|
---|
| 586 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 587 | * found in the LICENSE file at https://angular.io/license
|
---|
| 588 | */
|
---|
| 589 | class MatSortModule {
|
---|
| 590 | }
|
---|
| 591 | MatSortModule.decorators = [
|
---|
| 592 | { type: NgModule, args: [{
|
---|
| 593 | imports: [CommonModule, MatCommonModule],
|
---|
| 594 | exports: [MatSort, MatSortHeader],
|
---|
| 595 | declarations: [MatSort, MatSortHeader],
|
---|
| 596 | providers: [MAT_SORT_HEADER_INTL_PROVIDER]
|
---|
| 597 | },] }
|
---|
| 598 | ];
|
---|
| 599 |
|
---|
| 600 | /**
|
---|
| 601 | * @license
|
---|
| 602 | * Copyright Google LLC All Rights Reserved.
|
---|
| 603 | *
|
---|
| 604 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 605 | * found in the LICENSE file at https://angular.io/license
|
---|
| 606 | */
|
---|
| 607 |
|
---|
| 608 | /**
|
---|
| 609 | * @license
|
---|
| 610 | * Copyright Google LLC All Rights Reserved.
|
---|
| 611 | *
|
---|
| 612 | * Use of this source code is governed by an MIT-style license that can be
|
---|
| 613 | * found in the LICENSE file at https://angular.io/license
|
---|
| 614 | */
|
---|
| 615 |
|
---|
| 616 | /**
|
---|
| 617 | * Generated bundle index. Do not edit.
|
---|
| 618 | */
|
---|
| 619 |
|
---|
| 620 | export { MAT_SORT_DEFAULT_OPTIONS, MAT_SORT_HEADER_INTL_PROVIDER, MAT_SORT_HEADER_INTL_PROVIDER_FACTORY, MatSort, MatSortHeader, MatSortHeaderIntl, MatSortModule, matSortAnimations };
|
---|
| 621 | //# sourceMappingURL=sort.js.map
|
---|