UNPKG

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