UNPKG

12.7 kBJavaScriptView Raw
1import * as i0 from '@angular/core';
2import { Directive, Optional, Inject, Input, NgModule } from '@angular/core';
3import { mixinDisabled, MatCommonModule } from '@angular/material/core';
4import * as i1 from '@angular/cdk/a11y';
5import { A11yModule } from '@angular/cdk/a11y';
6import { coerceBooleanProperty } from '@angular/cdk/coercion';
7import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';
8
9let nextId = 0;
10// Boilerplate for applying mixins to MatBadge.
11/** @docs-private */
12const _MatBadgeBase = mixinDisabled(class {
13});
14const BADGE_CONTENT_CLASS = 'mat-badge-content';
15/** Directive to display a text badge. */
16class MatBadge extends _MatBadgeBase {
17 constructor(_ngZone, _elementRef, _ariaDescriber, _renderer, _animationMode) {
18 super();
19 this._ngZone = _ngZone;
20 this._elementRef = _elementRef;
21 this._ariaDescriber = _ariaDescriber;
22 this._renderer = _renderer;
23 this._animationMode = _animationMode;
24 this._color = 'primary';
25 this._overlap = true;
26 /**
27 * Position the badge should reside.
28 * Accepts any combination of 'above'|'below' and 'before'|'after'
29 */
30 this.position = 'above after';
31 /** Size of the badge. Can be 'small', 'medium', or 'large'. */
32 this.size = 'medium';
33 /** Unique id for the badge */
34 this._id = nextId++;
35 /** Whether the OnInit lifecycle hook has run yet */
36 this._isInitialized = false;
37 if (typeof ngDevMode === 'undefined' || ngDevMode) {
38 const nativeElement = _elementRef.nativeElement;
39 if (nativeElement.nodeType !== nativeElement.ELEMENT_NODE) {
40 throw Error('matBadge must be attached to an element node.');
41 }
42 }
43 }
44 /** The color of the badge. Can be `primary`, `accent`, or `warn`. */
45 get color() {
46 return this._color;
47 }
48 set color(value) {
49 this._setColor(value);
50 this._color = value;
51 }
52 /** Whether the badge should overlap its contents or not */
53 get overlap() {
54 return this._overlap;
55 }
56 set overlap(val) {
57 this._overlap = coerceBooleanProperty(val);
58 }
59 /** The content for the badge */
60 get content() {
61 return this._content;
62 }
63 set content(newContent) {
64 this._updateRenderedContent(newContent);
65 }
66 /** Message used to describe the decorated element via aria-describedby */
67 get description() {
68 return this._description;
69 }
70 set description(newDescription) {
71 this._updateHostAriaDescription(newDescription);
72 }
73 /** Whether the badge is hidden. */
74 get hidden() {
75 return this._hidden;
76 }
77 set hidden(val) {
78 this._hidden = coerceBooleanProperty(val);
79 }
80 /** Whether the badge is above the host or not */
81 isAbove() {
82 return this.position.indexOf('below') === -1;
83 }
84 /** Whether the badge is after the host or not */
85 isAfter() {
86 return this.position.indexOf('before') === -1;
87 }
88 /**
89 * Gets the element into which the badge's content is being rendered. Undefined if the element
90 * hasn't been created (e.g. if the badge doesn't have content).
91 */
92 getBadgeElement() {
93 return this._badgeElement;
94 }
95 ngOnInit() {
96 // We may have server-side rendered badge that we need to clear.
97 // We need to do this in ngOnInit because the full content of the component
98 // on which the badge is attached won't necessarily be in the DOM until this point.
99 this._clearExistingBadges();
100 if (this.content && !this._badgeElement) {
101 this._badgeElement = this._createBadgeElement();
102 this._updateRenderedContent(this.content);
103 }
104 this._isInitialized = true;
105 }
106 ngOnDestroy() {
107 // ViewEngine only: when creating a badge through the Renderer, Angular remembers its index.
108 // We have to destroy it ourselves, otherwise it'll be retained in memory.
109 if (this._renderer.destroyNode) {
110 this._renderer.destroyNode(this._badgeElement);
111 }
112 this._ariaDescriber.removeDescription(this._elementRef.nativeElement, this.description);
113 }
114 /** Creates the badge element */
115 _createBadgeElement() {
116 const badgeElement = this._renderer.createElement('span');
117 const activeClass = 'mat-badge-active';
118 badgeElement.setAttribute('id', `mat-badge-content-${this._id}`);
119 // The badge is aria-hidden because we don't want it to appear in the page's navigation
120 // flow. Instead, we use the badge to describe the decorated element with aria-describedby.
121 badgeElement.setAttribute('aria-hidden', 'true');
122 badgeElement.classList.add(BADGE_CONTENT_CLASS);
123 if (this._animationMode === 'NoopAnimations') {
124 badgeElement.classList.add('_mat-animation-noopable');
125 }
126 this._elementRef.nativeElement.appendChild(badgeElement);
127 // animate in after insertion
128 if (typeof requestAnimationFrame === 'function' && this._animationMode !== 'NoopAnimations') {
129 this._ngZone.runOutsideAngular(() => {
130 requestAnimationFrame(() => {
131 badgeElement.classList.add(activeClass);
132 });
133 });
134 }
135 else {
136 badgeElement.classList.add(activeClass);
137 }
138 return badgeElement;
139 }
140 /** Update the text content of the badge element in the DOM, creating the element if necessary. */
141 _updateRenderedContent(newContent) {
142 const newContentNormalized = `${newContent !== null && newContent !== void 0 ? newContent : ''}`.trim();
143 // Don't create the badge element if the directive isn't initialized because we want to
144 // append the badge element to the *end* of the host element's content for backwards
145 // compatibility.
146 if (this._isInitialized && newContentNormalized && !this._badgeElement) {
147 this._badgeElement = this._createBadgeElement();
148 }
149 if (this._badgeElement) {
150 this._badgeElement.textContent = newContentNormalized;
151 }
152 this._content = newContentNormalized;
153 }
154 /** Updates the host element's aria description via AriaDescriber. */
155 _updateHostAriaDescription(newDescription) {
156 this._ariaDescriber.removeDescription(this._elementRef.nativeElement, this.description);
157 if (newDescription) {
158 this._ariaDescriber.describe(this._elementRef.nativeElement, newDescription);
159 }
160 this._description = newDescription;
161 }
162 /** Adds css theme class given the color to the component host */
163 _setColor(colorPalette) {
164 const classList = this._elementRef.nativeElement.classList;
165 classList.remove(`mat-badge-${this._color}`);
166 if (colorPalette) {
167 classList.add(`mat-badge-${colorPalette}`);
168 }
169 }
170 /** Clears any existing badges that might be left over from server-side rendering. */
171 _clearExistingBadges() {
172 // Only check direct children of this host element in order to avoid deleting
173 // any badges that might exist in descendant elements.
174 const badges = this._elementRef.nativeElement.querySelectorAll(`:scope > .${BADGE_CONTENT_CLASS}`);
175 for (const badgeElement of Array.from(badges)) {
176 if (badgeElement !== this._badgeElement) {
177 badgeElement.remove();
178 }
179 }
180 }
181}
182MatBadge.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatBadge, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }, { token: i1.AriaDescriber }, { token: i0.Renderer2 }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
183MatBadge.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.1", type: MatBadge, selector: "[matBadge]", inputs: { disabled: ["matBadgeDisabled", "disabled"], color: ["matBadgeColor", "color"], overlap: ["matBadgeOverlap", "overlap"], position: ["matBadgePosition", "position"], content: ["matBadge", "content"], description: ["matBadgeDescription", "description"], size: ["matBadgeSize", "size"], hidden: ["matBadgeHidden", "hidden"] }, host: { properties: { "class.mat-badge-overlap": "overlap", "class.mat-badge-above": "isAbove()", "class.mat-badge-below": "!isAbove()", "class.mat-badge-before": "!isAfter()", "class.mat-badge-after": "isAfter()", "class.mat-badge-small": "size === \"small\"", "class.mat-badge-medium": "size === \"medium\"", "class.mat-badge-large": "size === \"large\"", "class.mat-badge-hidden": "hidden || !content", "class.mat-badge-disabled": "disabled" }, classAttribute: "mat-badge" }, usesInheritance: true, ngImport: i0 });
184i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatBadge, decorators: [{
185 type: Directive,
186 args: [{
187 selector: '[matBadge]',
188 inputs: ['disabled: matBadgeDisabled'],
189 host: {
190 'class': 'mat-badge',
191 '[class.mat-badge-overlap]': 'overlap',
192 '[class.mat-badge-above]': 'isAbove()',
193 '[class.mat-badge-below]': '!isAbove()',
194 '[class.mat-badge-before]': '!isAfter()',
195 '[class.mat-badge-after]': 'isAfter()',
196 '[class.mat-badge-small]': 'size === "small"',
197 '[class.mat-badge-medium]': 'size === "medium"',
198 '[class.mat-badge-large]': 'size === "large"',
199 '[class.mat-badge-hidden]': 'hidden || !content',
200 '[class.mat-badge-disabled]': 'disabled',
201 },
202 }]
203 }], ctorParameters: function () {
204 return [{ type: i0.NgZone }, { type: i0.ElementRef }, { type: i1.AriaDescriber }, { type: i0.Renderer2 }, { type: undefined, decorators: [{
205 type: Optional
206 }, {
207 type: Inject,
208 args: [ANIMATION_MODULE_TYPE]
209 }] }];
210 }, propDecorators: { color: [{
211 type: Input,
212 args: ['matBadgeColor']
213 }], overlap: [{
214 type: Input,
215 args: ['matBadgeOverlap']
216 }], position: [{
217 type: Input,
218 args: ['matBadgePosition']
219 }], content: [{
220 type: Input,
221 args: ['matBadge']
222 }], description: [{
223 type: Input,
224 args: ['matBadgeDescription']
225 }], size: [{
226 type: Input,
227 args: ['matBadgeSize']
228 }], hidden: [{
229 type: Input,
230 args: ['matBadgeHidden']
231 }] } });
232
233/**
234 * @license
235 * Copyright Google LLC All Rights Reserved.
236 *
237 * Use of this source code is governed by an MIT-style license that can be
238 * found in the LICENSE file at https://angular.io/license
239 */
240class MatBadgeModule {
241}
242MatBadgeModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatBadgeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
243MatBadgeModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.1", ngImport: i0, type: MatBadgeModule, declarations: [MatBadge], imports: [A11yModule, MatCommonModule], exports: [MatBadge, MatCommonModule] });
244MatBadgeModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatBadgeModule, imports: [A11yModule, MatCommonModule, MatCommonModule] });
245i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatBadgeModule, decorators: [{
246 type: NgModule,
247 args: [{
248 imports: [A11yModule, MatCommonModule],
249 exports: [MatBadge, MatCommonModule],
250 declarations: [MatBadge],
251 }]
252 }] });
253
254/**
255 * @license
256 * Copyright Google LLC All Rights Reserved.
257 *
258 * Use of this source code is governed by an MIT-style license that can be
259 * found in the LICENSE file at https://angular.io/license
260 */
261
262/**
263 * @license
264 * Copyright Google LLC All Rights Reserved.
265 *
266 * Use of this source code is governed by an MIT-style license that can be
267 * found in the LICENSE file at https://angular.io/license
268 */
269
270/**
271 * Generated bundle index. Do not edit.
272 */
273
274export { MatBadge, MatBadgeModule };
275//# sourceMappingURL=badge.mjs.map