A. js / lib / custom / md-app-bar.js

1
import { ES_APPLE } from "../ES_APPLE.js"
2
import { getAttribute } from "../getAttribute.js"
3
import { querySelector } from "../querySelector.js"
4
5
class MdAppBar extends HTMLElement {
6
7
 getContent() {
8
  return /* HTML */`
9
   <style>
10
11
    :host {
12
     display: flex;
13
     box-sizing: border-box;
14
     align-items: center;
15
     padding: 0 0.25rem;
16
     background-color: var(--md-sys-color-surface);
17
     position: sticky;
18
     z-index: 1;
19
     left: env(titlebar-area-x, 0);
20
     top: env(titlebar-area-y, 0);
21
     height: env(titlebar-area-height, 4rem);
22
     width: env(titlebar-area-width, 100%);
23
    }
24
    
25
    :host(.apple) {
26
     height: env(titlebar-area-height, 3rem);
27
    }
28
29
    :host(.scroll) {
30
     background-color: var(--md-sys-color-surface-container-low);
31
    }
32
33
    #navigation {
34
     flex: 0 0 auto;
35
     overflow: hidden
36
    }
37
38
    #navigation ::slotted(*) {
39
     color: var(--md-sys-color-on-surface);
40
    }
41
42
    #acciones {
43
     margin-left: auto;
44
     flex: 0 0 auto;
45
     overflow: hidden
46
    }
47
48
    :host(.centered) #navigation,
49
    :host(.centered) #acciones {
50
     flex: 0 0 6rem;
51
     overflow: hidden
52
    }
53
54
    #headline::slotted(*) {
55
     -webkit-app-region: drag;
56
     flex: 1 1 auto;
57
     white-space: nowrap;
58
     text-overflow: ellipsis;
59
     overflow: hidden;
60
     font-family: var(--md-sys-typescale-title-large-font);
61
     font-weight: var(--md-sys-typescale-title-large-weight);
62
     font-size: var(--md-sys-typescale-title-large-size);
63
     font-style: var(--md-sys-typescale-title-large-font-style);
64
     letter-spacing: var(--md-sys-typescale-title-large-tracking);
65
     line-height: var(--md-sys-typescale-title-large-line-height);
66
     text-transform: var(--md-sys-typescale-title-large-text-transform);
67
     text-decoration: var(--md-sys-typescale-title-large-text-decoration);
68
     color: var(--md-sys-color-on-surface);
69
    }
70
71
    :host(.centered) #headline::slotted(*) {
72
     flex: 1 1 auto;
73
     text-align: center
74
    }
75
76
   </style>
77
78
   <span id="navigation">
79
    <slot name="navigation"></slot>
80
   </span>
81
   <slot id="headline"></slot>
82
   <span id="acciones">
83
    <slot name="action"></slot>
84
   </span>`
85
 }
86
87
 constructor() {
88
  super()
89
  if (ES_APPLE) {
90
   document.body.classList.add("apple")
91
   document.body.classList.remove("material")
92
  } else {
93
   document.body.classList.add("material")
94
   document.body.classList.remove("apple")
95
  }
96
97
  /**
98
   * @private
99
   * @readonly
100
   */
101
  const shadow = this.attachShadow({ mode: "open" })
102
  shadow.innerHTML = this.getContent()
103
  this._configuraAction = this._configuraAction.bind(this)
104
  /**
105
   * @private
106
   * @type {number}
107
   */
108
  this._posY = 0
109
  /**
110
   * @private
111
   * @type {boolean}
112
   */
113
  this._scrolling = false
114
  /**
115
    * @private
116
    * @type { HTMLSlotElement }
117
    */
118
  this._navigation = querySelector(shadow, '[name="navigation"]')
119
  /**
120
    * @private
121
    * @type { HTMLSlotElement }
122
    */
123
  this._action = querySelector(shadow, '[name="action"]')
124
  /**
125
    * @private
126
    * @type { HTMLHeadingElement | null }
127
    */
128
  this._headline = null
129
  /**
130
    * @private
131
    * @type { HTMLElement | null }
132
    */
133
  this._adicional = null
134
  this._action.addEventListener("slotchange", this._configuraAction)
135
  addEventListener("scroll", () => this._onScroll())
136
  addEventListener("load", () => this.configurOtros())
137
 }
138
139
 connectedCallback() {
140
  this.role = "toolbar"
141
  this._configuraAction()
142
 }
143
144
 configurOtros() {
145
  const idHeadline = getAttribute(this, "headline")
146
  if (idHeadline !== "") {
147
   const headline = document.getElementById(idHeadline)
148
   if (headline instanceof HTMLHeadingElement) {
149
    this._headline = headline
150
    if (this.classList.contains("apple") || this.classList.contains("medium")) {
151
     headline.classList.add("md-headline", "headline-small")
152
    } else {
153
     headline.classList.add("md-headline", "headline-medium")
154
    }
155
   }
156
  }
157
  const idAdicional = getAttribute(this, "adicional")
158
  if (idAdicional !== "") {
159
   this._adicional = document.getElementById(idAdicional)
160
   if (this._adicional !== null) {
161
    if (this.classList.contains("apple")) {
162
     this._adicional.style.top = "env(titlebar-area-height, 3rem)"
163
    } else {
164
     this._adicional.style.top = "env(titlebar-area-height, 4rem)"
165
    }
166
   }
167
  }
168
 }
169
170
 _configuraAction() {
171
  const assignedElements = this._action.assignedElements()
172
  if (this.isConnected) {
173
   if (ES_APPLE) {
174
    this.classList.add("apple")
175
    this.classList.remove("material")
176
   } else {
177
    this.classList.add("material")
178
    this.classList.remove("apple")
179
   }
180
   if (this.classList.contains("centered")) {
181
    this.classList.remove("centrado")
182
    this.classList.remove("justificado")
183
   } else {
184
    if (ES_APPLE && assignedElements.length <= 1) {
185
     this.classList.add("centrado")
186
     this.classList.remove("justificado")
187
    } else {
188
     this.classList.add("justificado")
189
     this.classList.remove("centrado")
190
    }
191
   }
192
  }
193
 }
194
195
 /** @private */
196
 _onScroll() {
197
  this._posY = scrollY
198
  if (!this._scrolling) {
199
   requestAnimationFrame(() => this._avanza())
200
  }
201
  this._scrolling = true
202
 }
203
204
 /** @private */
205
 _avanza() {
206
  if (this._posY === 0) {
207
   this.classList.remove("scroll")
208
   if (this._headline !== null) {
209
    if (this._adicional === null) {
210
     this._headline.classList.remove("scroll")
211
    } else {
212
     this._headline.classList.remove("scroll-adicional")
213
    }
214
   }
215
   if (this._adicional !== null) {
216
    this._adicional.classList.remove("scroll")
217
   }
218
  } else {
219
   this.classList.add("scroll")
220
   if (this._headline !== null) {
221
    if (this._adicional === null) {
222
     this._headline.classList.add("scroll")
223
    } else {
224
     this._headline.classList.add("scroll-adicional")
225
    }
226
   }
227
   if (this._adicional !== null) {
228
    this._adicional.classList.add("scroll")
229
   }
230
  }
231
  this._scrolling = false
232
 }
233
234
}
235
236
customElements.define("md-app-bar", MdAppBar)
skip_previous skip_next