8
8
9
9
import { ElementRef , QueryList } from '@angular/core' ;
10
10
import {
11
- MDCTabIndicatorFoundation ,
12
11
MDCSlidingTabIndicatorFoundation ,
13
- MDCTabIndicatorAdapter
12
+ MDCTabIndicatorAdapter ,
13
+ MDCTabIndicatorFoundation
14
14
} from '@material/tab-indicator' ;
15
15
16
16
/**
@@ -23,7 +23,7 @@ export interface MatInkBarItem {
23
23
}
24
24
25
25
/**
26
- * Abstraction around the MDC tab indicator that manages the ink bar of a tab header.
26
+ * Abstraction around the MDC tab indicator that acts as the tab header's ink bar .
27
27
* @docs -private
28
28
*/
29
29
export class MatInkBar {
@@ -50,49 +50,47 @@ export class MatInkBar {
50
50
const clientRect = currentItem ?
51
51
currentItem . _foundation . computeContentClientRect ( ) : undefined ;
52
52
53
- // The MDC indicator won't animate unless we give it the `ClientRect` of the previous item.
53
+ // The ink bar won't animate unless we give it the `ClientRect` of the previous item.
54
54
correspondingItem . _foundation . activate ( clientRect ) ;
55
55
this . _currentItem = correspondingItem ;
56
56
}
57
57
}
58
58
}
59
59
60
60
/**
61
- * Implementation of MDC's sliding tab indicator foundation.
61
+ * Implementation of MDC's sliding tab indicator (ink bar) foundation.
62
62
* @docs -private
63
63
*/
64
64
export class MatInkBarFoundation {
65
65
private _destroyed : boolean ;
66
66
private _foundation : MDCTabIndicatorFoundation ;
67
- private _element : HTMLElement ;
68
- private _indicator : HTMLElement ;
69
- private _indicatorContent : HTMLElement ;
67
+ private _inkBarElement : HTMLElement ;
68
+ private _inkBarContentElement : HTMLElement ;
69
+ private _fitToContent = false ;
70
70
private _adapter : MDCTabIndicatorAdapter = {
71
71
addClass : className => {
72
72
if ( ! this . _destroyed ) {
73
- this . _element . classList . add ( className ) ;
73
+ this . _hostElement . classList . add ( className ) ;
74
74
}
75
75
} ,
76
76
removeClass : className => {
77
77
if ( ! this . _destroyed ) {
78
- this . _element . classList . remove ( className ) ;
78
+ this . _hostElement . classList . remove ( className ) ;
79
79
}
80
80
} ,
81
81
setContentStyleProperty : ( propName , value ) => {
82
- this . _indicatorContent . style . setProperty ( propName , value ) ;
82
+ this . _inkBarContentElement . style . setProperty ( propName , value ) ;
83
83
} ,
84
84
computeContentClientRect : ( ) => {
85
85
// `getBoundingClientRect` isn't available on the server.
86
- return this . _destroyed || ! this . _indicatorContent . getBoundingClientRect ? {
86
+ return this . _destroyed || ! this . _inkBarContentElement . getBoundingClientRect ? {
87
87
width : 0 , height : 0 , top : 0 , left : 0 , right : 0 , bottom : 0
88
- } : this . _indicatorContent . getBoundingClientRect ( ) ;
88
+ } : this . _inkBarContentElement . getBoundingClientRect ( ) ;
89
89
}
90
90
} ;
91
91
92
- constructor ( elementRef : ElementRef < HTMLElement > , document : Document ) {
93
- this . _element = elementRef . nativeElement ;
92
+ constructor ( private _hostElement : HTMLElement , private _document : Document ) {
94
93
this . _foundation = new MDCSlidingTabIndicatorFoundation ( this . _adapter ) ;
95
- this . _createIndicator ( document ) ;
96
94
}
97
95
98
96
/** Aligns the ink bar to the current item. */
@@ -105,39 +103,78 @@ export class MatInkBarFoundation {
105
103
this . _foundation . deactivate ( ) ;
106
104
}
107
105
108
- /** Gets the ClientRect of the indicator . */
106
+ /** Gets the ClientRect of the ink bar . */
109
107
computeContentClientRect ( ) {
110
108
return this . _foundation . computeContentClientRect ( ) ;
111
109
}
112
110
113
111
/** Initializes the foundation. */
114
112
init ( ) {
113
+ this . _createInkBarElement ( ) ;
115
114
this . _foundation . init ( ) ;
116
115
}
117
116
118
117
/** Destroys the foundation. */
119
118
destroy ( ) {
120
- const indicator = this . _indicator ;
121
-
122
- if ( indicator . parentNode ) {
123
- indicator . parentNode . removeChild ( indicator ) ;
119
+ if ( this . _inkBarElement . parentNode ) {
120
+ this . _inkBarElement . parentNode . removeChild ( this . _inkBarElement ) ;
124
121
}
125
122
126
- this . _element = this . _indicator = this . _indicatorContent = null ! ;
123
+ this . _hostElement = this . _inkBarElement = this . _inkBarContentElement = null ! ;
127
124
this . _foundation . destroy ( ) ;
128
125
this . _destroyed = true ;
129
126
}
130
127
131
- private _createIndicator ( document : Document ) {
132
- if ( ! this . _indicator ) {
133
- const indicator = this . _indicator = document . createElement ( 'span' ) ;
134
- const content = this . _indicatorContent = document . createElement ( 'span' ) ;
128
+ /**
129
+ * Sets whether the ink bar should be appended to the content, which will cause the ink bar
130
+ * to match the width of the content rather than the tab host element.
131
+ */
132
+ setFitToContent ( fitToContent : boolean ) {
133
+ if ( this . _fitToContent !== fitToContent ) {
134
+ this . _fitToContent = fitToContent ;
135
+ if ( this . _inkBarElement ) {
136
+ this . _appendInkBarElement ( ) ;
137
+ }
138
+ }
139
+ }
140
+
141
+
142
+ /**
143
+ * Gets whether the ink bar should be appended to the content, which will cause the ink bar
144
+ * to match the width of the content rather than the tab host element.
145
+ */
146
+ getFitToContent ( ) : boolean { return this . _fitToContent ; }
147
+
148
+ /** Creates and appends the ink bar element. */
149
+ private _createInkBarElement ( ) {
150
+ this . _inkBarElement = this . _document . createElement ( 'span' ) ;
151
+ this . _inkBarContentElement = this . _document . createElement ( 'span' ) ;
135
152
136
- indicator . className = 'mdc-tab-indicator' ;
137
- content . className = 'mdc-tab-indicator__content mdc-tab-indicator__content--underline' ;
153
+ this . _inkBarElement . className = 'mdc-tab-indicator' ;
154
+ this . _inkBarContentElement . className = 'mdc-tab-indicator__content' +
155
+ ' mdc-tab-indicator__content--underline' ;
138
156
139
- indicator . appendChild ( content ) ;
140
- this . _element . appendChild ( indicator ) ;
157
+ this . _inkBarElement . appendChild ( this . _inkBarContentElement ) ;
158
+ this . _appendInkBarElement ( ) ;
159
+ }
160
+
161
+ /**
162
+ * Appends the ink bar to the tab host element or content, depending on whether
163
+ * the ink bar should fit to content.
164
+ */
165
+ private _appendInkBarElement ( ) {
166
+ if ( ! this . _inkBarElement ) {
167
+ throw Error ( 'Ink bar element has not been created and cannot be appended' ) ;
168
+ }
169
+
170
+ const parentElement = this . _fitToContent ?
171
+ this . _hostElement . querySelector ( '.mdc-tab__content' ) :
172
+ this . _hostElement ;
173
+
174
+ if ( ! parentElement ) {
175
+ throw Error ( 'Missing element to host the ink bar' ) ;
141
176
}
177
+
178
+ parentElement . appendChild ( this . _inkBarElement ) ;
142
179
}
143
180
}
0 commit comments