• 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.js';
17
18@element('lit-popover')
19export class LitPopover extends BaseElement {
20  static get observedAttributes() {
21    return ['title', 'trigger', 'width', 'placement', 'visible'];
22  }
23
24  get visible() {
25    return this.getAttribute('visible') || 'false';
26  }
27
28  set visible(value) {
29    if (value) {
30      this.setAttribute('visible', 'true');
31    } else {
32      this.setAttribute('visible', 'false');
33    }
34  }
35
36  get trigger() {
37    return this.getAttribute('trigger') || 'hover';
38  }
39
40  set trigger(value) {
41    this.setAttribute('trigger', value);
42  }
43
44  get title() {
45    return this.getAttribute('title');
46  }
47
48  set title(value: any) {
49    this.setAttribute('title', value);
50  }
51
52  get width() {
53    return this.getAttribute('width') || 'max-content';
54  }
55
56  set width(value) {
57    this.setAttribute('width', value);
58  }
59
60  get haveRadio() {
61    return this.getAttribute('haveRadio');
62  }
63
64  initElements(): void {}
65
66  initHtml() {
67    return `
68        <style>
69        :host{
70            outline: none;
71            display:inline-block;
72            position: relative;
73            overflow: visible;
74        }
75
76        .title{
77            padding: 6px 15px;
78            font-weight: bold;
79            font-size: 0.9rem;
80            border-bottom: 1px solid #f0f0f0;
81        }
82        .content{
83            padding: 10px 15px;
84        }
85       .trigger-click {
86            position: absolute;
87            visibility: hidden;
88            z-index: -100;
89            width: 100%;
90            height: 100%;
91        }
92        /*通用*/
93        .popover{
94            width: ${this.width};
95            min-width: 160px;
96            display: flex;
97            flex-direction: column;
98            visibility: hidden;
99            opacity: 0;
100            transition: all 0.3s;
101            z-index: 1;
102            position: absolute;
103            border-radius: 2px;
104            background-color: var(--dark-background3,#fff);
105            box-shadow: 0 0 20px #00000044;
106        }
107        .popover:after{
108            content: '';
109            display: flex;
110            position: absolute;
111            width: 12px;
112            height: 12px;
113            background: linear-gradient(45deg, var(--dark-background3,#FFFFFF),
114            var(--dark-background3,#FFFFFF) 50%, transparent 50%, transparent 100%);
115        }
116        :host(:not([placement])) .popover,
117        :host([placement='top']) .popover{
118            top: 0;
119            left: 50%;
120            right: 0;
121            transform: translate(-50%,calc(-100% - 12px)) scale(0.5);
122            transform-origin: bottom;
123        }
124        :host(:not([placement])) .popover:after,
125        :host([placement='top']) .popover:after{
126            border-top: 6px solid #fff;
127            left: 0;
128            top: calc(100%);
129            transform: translate(-50%,0%);
130            left: 50%;
131        }
132        :host(:not([placement])[trigger='hover']:hover)  .popover,
133        :host(:not([placement]):not([trigger]):hover)  .popover,
134        :host([placement='top'][trigger='hover']:hover)  .popover,
135        :host([placement='top']:not([trigger]):hover)  .popover {
136            visibility: visible;
137            opacity: 1;
138            transform: translate(-50%,calc(-100% - 12px)) scale(1);
139        }
140        :host(:not([placement])[trigger='click']) input[type=checkbox]:checked ~ .popover,
141        :host([placement='top'][trigger='click']) input[type=checkbox]:checked ~ .popover {
142            visibility: visible;
143            opacity: 1;
144            transform: translate(-50%,calc(-100% - 12px)) scale(1);
145        }
146        :host([placement='topLeft']) .popover{
147            top: 0;
148            left: 50%;
149            right: 0;
150            transform: translate(0,calc(-100% - 12px)) scale(0.5);
151            transform-origin: left bottom;
152        }
153        :host([placement='topLeft']) .popover:after{
154            top: 99%;
155            transform: rotateX(180deg);
156        }
157        :host([placement='topLeft']:not([trigger]):hover)  .popover,
158        :host([placement='topLeft'][trigger='hover']:hover)  .popover {
159            visibility: visible;
160            opacity: 1;
161            transform: translate(0%,calc(-100% - 12px)) scale(1);
162        }
163        :host([placement='topLeft'][trigger='click']) input[type=checkbox]:checked ~ .popover {
164            visibility: visible;
165            opacity: 1;
166            transform: translate(0%,calc(-100% - 12px)) scale(1);
167        }
168        :host([placement='topRight']) .popover{
169            top: 0;
170            right: 0;
171            transform: translate(0,calc(-100% - 12px)) scale(0.5);
172            transform-origin: right bottom;
173        }
174        :host([placement='topRight']) .popover:after{
175            border-top: 6px solid #fff;
176            top: calc(100%);
177            transform: translate(0%,0%);
178            right: 20px;
179        }
180        :host([placement='topRight']:not([trigger]):hover)  .popover,
181        :host([placement='topRight'][trigger='hover']:hover)  .popover {
182            visibility: visible;
183            opacity: 1;
184            transform: translate(0%,calc(-100% - 12px)) scale(1);
185        }
186        :host([placement='topRight'][trigger='click']) input[type=checkbox]:checked ~ .popover {
187            visibility: visible;
188            opacity: 1;
189            transform: translate(0%,calc(-100% - 12px)) scale(1);
190        }
191        :host([placement='leftTop']) .popover{
192            top: 0;
193            right: 100%;
194            transform: translate(-12px,0) scale(0.5);
195            transform-origin: right top;
196        }
197        :host([placement='leftTop']) .popover:after{
198            border-left: 6px solid #fff;
199            top: 10px;
200            right: -12px;
201            transform: translate(0px,0%);
202        }
203        :host([placement='leftTop']:not([trigger]):hover)  .popover,
204        :host([placement='leftTop'][trigger='hover']:hover)  .popover {
205            visibility: visible;
206            opacity: 1;
207            right: 100%;
208            transform: translate(-12px,0) scale(1);
209        }
210        :host([placement='leftTop'][trigger='click']) input[type=checkbox]:checked ~ .popover {
211            visibility: visible;
212            opacity: 1;
213            transform: translate(-12px,0) scale(1);
214        }
215        :host([placement='left']) .popover{
216            right: 100%;
217            top: 50%;
218            transform: translate(-12px,-50%) scale(0.5);
219            transform-origin: right center;
220        }
221        :host([placement='left']) .popover:after{
222            border-left: 6px solid #fff;
223            top: 50%;
224            right: -12px;
225            transform: translate(0px,-50%);
226        }
227        :host([placement='left']:not([trigger]):hover)  .popover,
228        :host([placement='left'][trigger='hover']:hover)  .popover {
229            visibility: visible;
230            opacity: 1;
231            right: 100%;
232            transform: translate(-12px,-50%) scale(1);
233        }
234        :host([placement='left'][trigger='click']) input[type=checkbox]:checked ~ .popover {
235            visibility: visible;
236            opacity: 1;
237            transform: translate(-12px,-50%) scale(1);
238        }
239        :host([placement='leftBottom']) .popover{
240            right: 100%;
241            bottom: 0;
242            transform: translate(-12px,0%) scale(0.5);
243            transform-origin: right bottom;
244        }
245        :host([placement='leftBottom']) .popover:after{
246            border-left: 6px solid #fff;
247            bottom: 10px;
248            right: -12px;
249            transform: translate(0px,-50%);
250        }
251        :host([placement='leftBottom']:not([trigger]):hover)  .popover,
252        :host([placement='leftBottom'][trigger='hover']:hover)  .popover {
253            visibility: visible;
254            opacity: 1;
255            right: 100%;
256            transform: translate(-12px,0%) scale(1);
257        }
258        :host([placement='leftBottom'][trigger='click']) input[type=checkbox]:checked ~ .popover {
259            visibility: visible;
260            opacity: 1;
261            transform: translate(-12px,0%) scale(1);
262        }
263        :host([placement='rightTop']) .popover{
264            top: 0;
265            left: 100%;
266            transform: translate(12px,0) scale(0.5);
267            transform-origin: left top;
268        }
269        :host([placement='rightTop']) .popover:after{
270            border-right: 6px solid #fff;
271            top: 10px;
272            left: -12px;
273            transform: translate(0px,0%);
274        }
275        :host([placement='rightTop']:not([trigger]):hover)  .popover,
276        :host([placement='rightTop'][trigger='hover']:hover)  .popover {
277            visibility: visible;
278            opacity: 1;
279            left: 100%;
280            transform: translate(12px,0) scale(1);
281        }
282        :host([placement='rightTop'][trigger='click']) input[type=checkbox]:checked ~ .popover {
283            visibility: visible;
284            opacity: 1;
285            transform: translate(12px,0) scale(1);
286        }
287        :host([placement='right']) .popover{
288            top: 50%;
289            left: 100%;
290            transform: translate(12px,-50%) scale(0.5);
291            transform-origin: left center;
292        }
293        :host([placement='right']) .popover:after{
294            border-right: 6px solid #fff;
295            top: 50%;
296            left: -12px;
297            transform: translate(0px,-50%);
298        }
299        :host([placement='right']:not([trigger]):hover)  .popover,
300        :host([placement='right'][trigger='hover']:hover)  .popover {
301            visibility: visible;
302            opacity: 1;
303            left: 100%;
304            transform: translate(12px,-50%) scale(1);
305        }
306        :host([placement='right'][trigger='click']) input[type=checkbox]:checked ~ .popover {
307            visibility: visible;
308            opacity: 1;
309            transform: translate(12px,-50%) scale(1);
310        }
311        :host([placement='rightBottom']) .popover{
312            bottom: 0;
313            left: 100%;
314            transform: translate(12px,0%) scale(0.5);
315            transform-origin: left bottom;
316        }
317        :host([placement='rightBottom']) .popover:after{
318            border-right: 6px solid #fff;
319            left: -12px;
320            bottom: 10px;
321            transform: translate(0px,0);
322        }
323        :host([placement='rightBottom']:not([trigger]):hover)  .popover,
324        :host([placement='rightBottom'][trigger='hover']:hover)  .popover {
325            visibility: visible;
326            opacity: 1;
327            bottom: 0;
328            transform: translate(12px,0%) scale(1);
329        }
330        :host([placement='rightBottom'][trigger='click']) input[type=checkbox]:checked ~ .popover {
331            visibility: visible;
332            opacity: 1;
333            transform: translate(12px,0%) scale(1);
334        }
335
336        :host([placement='bottomLeft']) .popover{
337            bottom: 0;
338            /*left: 0;*/
339            left: 8px;
340            right: 0;
341            transform: translate(0,calc(100% + 12px)) scale(0.5);
342            transform-origin: top left;
343        }
344        :host([placement='bottomLeft']) .popover:after{
345            bottom: calc(100%);
346            transform: translate(0%,0%);
347            left: 0;
348        }
349        :host([placement='bottomLeft']:not([trigger]):hover)  .popover,
350        :host([placement='bottomLeft'][trigger='hover']:hover)  .popover {
351            visibility: visible;
352            opacity: 1;
353            transform: translate(0%,calc(100% + 12px)) scale(1);
354        }
355        :host([placement='bottomLeft'][trigger='click']) input[type=checkbox]:checked ~ .popover {
356            visibility: visible;
357            opacity: 1;
358            transform: translate(0%,calc(100% + 12px)) scale(1);
359        }
360        :host([placement='bottom']) .popover{
361            bottom: 0;
362            left: 50%;
363            right: 0;
364            transform: translate(-50%,calc(100% + 12px)) scale(0.5);
365            transform-origin: top center;
366        }
367        :host([placement='bottom']) .popover:after{
368            border-bottom: 6px solid #fff;
369            bottom: calc(100%);
370            transform: translate(-50%,0%);
371            left: 50%;
372        }
373        :host([placement='bottom']:not([trigger]):hover)  .popover,
374        :host([placement='bottom'][trigger='hover']:hover)  .popover {
375            visibility: visible;
376            opacity: 1;
377            transform: translate(-50%,calc(100% + 12px)) scale(1);
378        }
379        :host([placement='bottom'][trigger='click']) input[type=checkbox]:checked ~ .popover {
380            visibility: visible;
381            opacity: 1;
382            transform: translate(-50%,calc(100% + 12px)) scale(1);
383        }
384        /*bottomRight*/
385        :host([placement='bottomRight']) .popover{
386            bottom: 0;
387            right: 0;
388            transform: translate(0%,calc(100% + 12px)) scale(0.5);
389            transform-origin: top right;
390        }
391        :host([placement='bottomRight']) .popover:after{
392            border-bottom: 6px solid #fff;
393            bottom: calc(100%);
394            transform: translate(-50%,0%);
395            right: 10px;
396        }
397        :host([placement='bottomRight']:not([trigger]):hover)  .popover,
398        :host([placement='bottomRight'][trigger='hover']:hover)  .popover {
399            visibility: visible;
400            opacity: 1;
401            transform: translate(0,calc(100% + 12px)) scale(1);
402        }
403        :host([placement='bottomRight'][trigger='click']) input[type=checkbox]:checked ~ .popover {
404            visibility: visible;
405            opacity: 1;
406            transform: translate(0%,calc(100% + 12px)) scale(1);
407        }
408        :host(:not([title])) .title{
409            display: none;
410        }
411        </style>
412        <input class="trigger-click" type="checkbox">
413        <div class="popover" title="">
414            <div class="title">${this.title}</div>
415            <div class="content"><slot name="content" ></slot></div>
416        </div>
417        <slot></slot>
418        `;
419  }
420
421  connectedCallback() {
422    let popover: any = this.shadowRoot!.querySelector('.popover');
423    let checkbox: any = this.shadowRoot!.querySelector('.trigger-click');
424    this.setAttribute('tabindex', '1');
425    popover.onclick = (e: any) => {
426      e.stopPropagation();
427    };
428    popover.addEventListener('mousemove', (e: any) => {
429      e.stopPropagation();
430    });
431    this.onclick = (e: any) => {
432      e.stopPropagation();
433      if (e.relatedTarget?.hasAttribute('not-close')) {
434        this.focus();
435      }
436      checkbox.checked = !checkbox.checked;
437      this.visible = checkbox.checked;
438    };
439    popover.onmouseleave = () => {
440      this.focus();
441    };
442    this.onblur = (ev: any) => {
443      if (ev.relatedTarget && this.haveRadio) {
444        if (ev.relatedTarget.hasAttribute('not-close')) {
445        } else if (ev.relatedTarget.type === 'radio') {
446          this.focus();
447        } else {
448          // @ts-ignore
449          this.visible = false;
450        }
451      } else {
452        // @ts-ignore
453        this.visible = false;
454      }
455    };
456  }
457
458  disconnectedCallback() {}
459
460  adoptedCallback() {}
461
462  attributeChangedCallback(name: any, oldValue: any, newValue: any) {
463    if (name === 'visible') {
464      if (newValue === 'false') {
465        // @ts-ignore
466        this.shadowRoot!.querySelector('.trigger-click')!.checked = false;
467      } else {
468        // @ts-ignore
469        this.shadowRoot!.querySelector('.trigger-click')!.checked = true;
470      }
471    }
472  }
473}
474