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';
|
---|
3 | import { FocusMonitor, AriaDescriber } from '@angular/cdk/a11y';
|
---|
4 | import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
---|
5 | import { SPACE, ENTER } from '@angular/cdk/keycodes';
|
---|
6 | import { mixinInitialized, mixinDisabled, AnimationDurations, AnimationCurves, MatCommonModule } from '@angular/material/core';
|
---|
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
|
---|
317 | _sort, _columnDef, _focusMonitor, _elementRef,
|
---|
318 | /** @breaking-change 14.0.0 _ariaDescriber will be required. */
|
---|
319 | _ariaDescriber) {
|
---|
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;
|
---|
331 | this._ariaDescriber = _ariaDescriber;
|
---|
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';
|
---|
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';
|
---|
355 | if (!_sort && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
---|
356 | throw getSortHeaderNotContainedWithinSortError();
|
---|
357 | }
|
---|
358 | this._handleStateChanges();
|
---|
359 | }
|
---|
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 | }
|
---|
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);
|
---|
381 | this._sortButton = this._elementRef.nativeElement.querySelector('[role="button"]');
|
---|
382 | this._updateSortActionDescription(this._sortActionDescription);
|
---|
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 | }
|
---|
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 | }
|
---|
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 },
|
---|
571 | { type: ElementRef },
|
---|
572 | { type: AriaDescriber, decorators: [{ type: Inject, args: [AriaDescriber,] }, { type: Optional }] }
|
---|
573 | ];
|
---|
574 | MatSortHeader.propDecorators = {
|
---|
575 | id: [{ type: Input, args: ['mat-sort-header',] }],
|
---|
576 | arrowPosition: [{ type: Input }],
|
---|
577 | start: [{ type: Input }],
|
---|
578 | sortActionDescription: [{ type: Input }],
|
---|
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
|
---|