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