• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BaseElement, element } from '../BaseElement';
17
18let contentPadding = '';
19let contentWidth = '';
20let css = `
21<style>
22      :host{
23          display: flex;
24          position: absolute;
25          top: 0;
26          bottom: 0;
27          left: 0;
28          right: 0;
29          width: 100%;
30          height: 100%;
31          overflow: hidden;
32          z-index: 2001;
33          pointer-events: none;
34       }
35       :host([mask]) .bg{
36          position:absolute;
37          top: 0;
38          right: 0;
39          left: 0;
40          bottom: 0;
41          width: 100%;
42          height: 100%;
43          background-color: #00000055;
44       }
45       :host(:not([mask])) .bg{
46          display: none;
47       }
48
49
50       .title{
51          display: flex;
52          justify-content: space-between;
53          align-items: center;
54          padding: 12px 20px;
55          border-bottom: var(--dark-border1,#f0f0f0) 1px solid;
56          font-size: 18px;
57          font-weight: bold;
58          color: var(--dark-color1,#262626);
59       }
60       slot{
61          padding: ${contentPadding};
62          display: block;
63       }
64       :host([visible]) .bg{
65          transition: all .3s;
66          opacity: 1;
67          visibility: visible;
68       }
69       :host(:not([visible])) .bg{
70          transition: all .3s;
71          opacity: 0;
72          visibility: hidden;
73       }
74       /*
75          right(默认)
76       */
77       :host(:not([placement])) .drawer,
78       :host([placement='right']) .drawer{
79          width: ${contentWidth};
80          box-sizing: border-box;
81          position: absolute;
82          display: flex;
83          flex-direction: column;
84          right: 0px;
85          top: 0px;
86          bottom: 0px;
87          height: 100%;
88          overflow: auto;
89          background-color: var(--dark-background,#FFFFFF);
90          -webkit-transform: translateZ(0);
91          -moz-transform: translateZ(0);
92          -ms-transform: translateZ(0);
93          -o-transform: translateZ(0);
94          transform: translateZ(0);
95          transform: translateX(100%);
96          transition: transform .3s;
97       }
98       :host(:not([placement])[visible]) .drawer,
99       :host([placement='right'][visible]) .drawer{
100          transform: translateX(0%);
101          box-shadow: 0px 0 20px 0px #00000055;
102       }
103       :host(:not([visible]):not([placement])) .drawer,
104       :host(:not([visible])[placement='right']) .drawer{
105          transform: translateX(100%);
106       }
107       /*
108          左边
109       */
110       :host([placement='left']) .drawer{
111          width: ${contentWidth};
112          box-sizing: border-box;
113          position: absolute;
114          display: flex;
115          flex-direction: column;
116          left: 0px;
117          top: 0px;
118          bottom: 0px;
119          right: auto;
120          height: 100%;
121          background-color: var(--dark-background,#FFFFFF);
122          webkit-transform: translate3d(0,0,0);
123          -moz-transform: translate3d(0,0,0);
124          -ms-transform: translate3d(0,0,0);
125          -o-transform: translate3d(0,0,0);
126          transform: translate3d(0,0,0);
127          transform: translate(0%,0%);
128       }
129       :host([placement='left']) .drawer{
130          transition: transform .3s;
131       }
132       :host([placement='left'][visible]) .drawer{
133          box-shadow: 0px 0 60px 0px #00000055;
134          transform: translate(0%,0%);
135       }
136       :host(:not([visible])[placement='left']) .drawer{
137          transform: translate(-100%,0%);
138       }
139
140       /*
141          top
142       */
143       :host([placement='top']) .drawer{
144          box-sizing: border-box;
145          position: absolute;
146          display: flex;
147          flex-direction: column;
148          left: 0px;
149          top: 0px;
150          right: 0px;
151          width: 100%;
152          background-color: var(--dark-background,#FFFFFF);
153          webkit-transform: translate3d(0,0,0);
154          -moz-transform: translate3d(0,0,0);
155          -ms-transform: translate3d(0,0,0);
156          -o-transform: translate3d(0,0,0);
157          transform: translate3d(0,0,0);
158       }
159       :host([placement='top']) .drawer{
160          transform: translateY(-100%);
161          transition: transform .3s;
162       }
163       :host([placement='top'][visible]) .drawer{
164          box-shadow: 0px 0 60px 0px #00000055;
165          transform: translateY(0%);
166       }
167       :host(:not([visible])[placement='top']) .drawer{
168          transform: translateY(-100%);
169       }
170
171       /*
172          bottom
173       */
174       :host([placement='bottom']) .drawer{
175          box-sizing: border-box;
176          position: absolute;
177          display: flex;
178          flex-direction: column;
179          left: 0px;
180          bottom: 0px;
181          right: 0px;
182          top: auto;
183          width: 100%;
184          background-color: var(--dark-background,#FFFFFF);
185          webkit-transform: translate3d(0,0,0);
186          -moz-transform: translate3d(0,0,0);
187          -ms-transform: translate3d(0,0,0);
188          -o-transform: translate3d(0,0,0);
189          transform: translate3d(0,0,0);
190          transform: translate(0%,0%);
191          transition: transform .3s;
192       }
193       :host([placement='bottom'][visible]) .drawer{
194          box-shadow: 0px 0 60px 0px #00000055;
195          transform: translate(0%,0%);
196       }
197       :host(:not([visible])[placement='bottom']) .drawer{
198          transform: translate(0%,100%);
199       }
200
201       :host([closeable]) .close-icon{
202          display: flex;
203          color: #8c8c8c;
204          padding: 5px;
205       }
206       :host([closeable]) .close-icon:hover{
207          color: #414141;
208       }
209       :host(:not([closeable])) .close-icon{
210          display: none;
211       }
212      </style>
213`;
214
215const initHtmlStyle = (padding: string, width: string) => {
216  contentPadding = padding;
217  contentWidth = width;
218  return css;
219};
220
221@element('lit-drawer')
222export class LitDrawer extends BaseElement {
223  static get observedAttributes() {
224    return ['title', 'visible', 'placement', 'mask', 'mask-closable', 'closeable', 'content-padding', 'content-width'];
225  }
226
227  initHtml(): string {
228    return `
229        ${initHtmlStyle(this.contentPadding, this.contentWidth)}
230        <div class="bg"></div>
231        <div class="drawer">
232            <div class="title">
233                <label id="drawer-tittle-text">${this.title}</label>
234                <lit-icon class="close-icon" name="close"></lit-icon>
235            </div>
236            <div style="overflow-x: hidden;overflow-y: auto">
237                <slot></slot>
238            </div>
239        </div>
240        `;
241  }
242  get contentWidth() {
243    return this.getAttribute('content-width') || '400px';
244  }
245  set contentWidth(value) {
246    this.shadowRoot!.querySelector<HTMLDivElement>('.drawer')!.style.width = value;
247    this.setAttribute('content-width', value);
248  }
249  get contentPadding() {
250    return this.getAttribute('content-padding') || '20px';
251  }
252  set contentPadding(value) {
253    this.shadowRoot!.querySelector('slot')!.style.padding = value;
254    this.setAttribute('content-padding', value);
255  }
256  get placement() {
257    return this.getAttribute('placement');
258  }
259  set placement(value: any) {
260    this.setAttribute('placement', value);
261  }
262  get title() {
263    return this.getAttribute('title') || '';
264  }
265  set title(value) {
266    this.shadowRoot!.querySelector('#drawer-tittle-text')!.textContent = value;
267    this.setAttribute('title', value);
268  }
269  get visible() {
270    return this.getAttribute('visible') !== null;
271  }
272  set visible(value: any) {
273    if (value) {
274      this.setAttribute('visible', value);
275    } else {
276      this.removeAttribute('visible');
277    }
278  }
279  get mask() {
280    return this.getAttribute('mask') !== null;
281  }
282  set mask(value) {
283    if (value) {
284      this.setAttribute('mask', '');
285    } else {
286      this.removeAttribute('mask');
287    }
288  }
289  get maskCloseable() {
290    return this.getAttribute('mask-closeable') !== null;
291  }
292  set maskCloseable(value) {
293    if (value) {
294      this.setAttribute('mask-closeable', '');
295    } else {
296      this.removeAttribute('mask-closeable');
297    }
298  }
299  get closeable() {
300    return this.getAttribute('closeable') !== null;
301  }
302
303  set closeable(value) {
304    if (value) {
305      this.setAttribute('closeable', '');
306    } else {
307      this.removeAttribute('closeable');
308    }
309  }
310
311  //当 custom element首次被插入文档DOM时,被调用。
312  initElements(): void {
313    let bg: HTMLDivElement | null = this.shadowRoot!.querySelector('.bg');
314    if (this.maskCloseable) {
315      bg!.onclick = (e: any) => {
316        e.stopPropagation();
317        this.visible = false;
318        this.dispatchEvent(new CustomEvent('onClose', e));
319      };
320    }
321    if (this.closeable) {
322      (this.shadowRoot!.querySelector('.close-icon') as any).onclick = (e: any) => {
323        this.visible = false;
324        this.dispatchEvent(new CustomEvent('onClose', e));
325      };
326    }
327  }
328  set onClose(fn: any) {
329    this.addEventListener('onClose', fn);
330  }
331  //当 custom element从文档DOM中删除时,被调用。
332  disconnectedCallback() {}
333
334  //当 custom element被移动到新的文档时,被调用。
335  adoptedCallback() {}
336
337  //当 custom element增加、删除、修改自身属性时,被调用。
338  attributeChangedCallback(name: string, oldValue: string, newValue: string) {
339    if (this.mask) {
340      if (name === 'visible') {
341        if (newValue !== null) {
342          this.style.pointerEvents = 'all';
343        } else {
344          this.style.pointerEvents = 'none';
345        }
346      } else if (name === 'placement') {
347        if (newValue === 'bottom') {
348          let el = this.shadowRoot!.querySelector('.drawer');
349        }
350      }
351    }
352  }
353}
354
355if (!customElements.get('lit-drawer')) {
356  customElements.define('lit-drawer', LitDrawer);
357}
358