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';
17import { LitPopContent } from './LitPopContent';
18import { LitPopoverTitle } from './LitPopoverTitle';
19import { LitRadioGroup } from '../radiobox/LitRadioGroup';
20import { LitRadioBox } from '../radiobox/LitRadioBox';
21import { LitCheckBox } from '../checkbox/LitCheckBox';
22import { LitCheckGroup } from '../checkbox/LitCheckGroup';
23import { LitCheckBoxWithText } from '../checkbox/LitCheckBoxWithText';
24
25const initHtmlStyle = `
26    <style>
27        :host {
28            display:inline-block;
29            position:relative;
30            overflow:visible;
31        }
32        :host([direction="top"]) ::slotted(lit-pop-content){
33            bottom:100%;
34            left:50%;
35            transform:translate(-50%,-10px) scale(0);
36            transform-origin: center bottom;
37        }
38        :host([direction="top"]) ::slotted(lit-pop-content)::after{
39            content: '';
40            position: absolute; 
41            top: 100%;
42            left: 50%;
43            border-top: 10px solid #FFF;
44            border-right: 10px solid transparent;
45            border-left: 10px solid transparent;
46
47        }
48        :host([direction="top"]) ::slotted(lit-pop-content[open]),
49        :host([direction="top"][trigger="hover"]:hover) ::slotted(lit-pop-content),
50        :host([direction="top"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
51            transform:translate(-50%,-10px) scale(1);
52        }
53        
54        :host([direction="bottom"]) ::slotted(lit-pop-content){
55            top:100%;
56            left:50%;
57            transform:translate(-50%,10px) scale(0);
58            transform-origin: center top;
59        }
60        :host([direction="bottom"]) ::slotted(lit-pop-content)::after{
61            content: '';
62            position: absolute;
63            bottom: 100%;
64            left: 50%;
65            border-bottom: 10px solid #FFF; 
66            border-right: 10px solid transparent;
67            border-left: 10px solid transparent;
68        }
69        :host([direction="bottom"]) ::slotted(lit-pop-content[open]),
70        :host([direction="bottom"][trigger="hover"]:hover) ::slotted(lit-pop-content),
71        :host([direction="bottom"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
72            transform:translate(-50%,10px) scale(1);
73        }
74        
75        
76        :host([direction="left"]) ::slotted(lit-pop-content){
77            right:100%;
78            top:50%;
79            transform:translate(-10px,-50%) scale(0);
80            transform-origin: right;
81        }
82        :host([direction="left"]) ::slotted(lit-pop-content)::after{
83            content: '';
84            position: absolute;
85            bottom: 40%;
86            left: 100%;
87            border-left: 10px solid #FFF; 
88            border-bottom: 10px solid transparent;
89            border-top: 10px solid transparent;
90        }
91        :host([direction="left"]) ::slotted(lit-pop-content[open]),
92        :host([direction="left"][trigger="hover"]:hover) ::slotted(lit-pop-content),
93        :host([direction="left"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
94            transform:translate(-10px,-50%) scale(1);
95        }
96        :host([direction="right"]) ::slotted(lit-pop-content){
97            left:100%;
98            top:50%;
99            transform:translate(10px,-50%) scale(0);
100            transform-origin: left;
101        }
102        :host([direction="right"]) ::slotted(lit-pop-content)::after{
103            content: '';
104            position: absolute;
105            bottom: 40%;
106            right: 100%;
107            border-right: 10px solid #FFF; 
108            border-bottom: 10px solid transparent;
109            border-top: 10px solid transparent;
110        }
111        :host([direction="right"]) ::slotted(lit-pop-content[open]),
112        :host([direction="right"][trigger="hover"]:hover) ::slotted(lit-pop-content),
113        :host([direction="right"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
114            transform:translate(10px,-50%) scale(1);
115        }
116        
117        
118        
119        :host([direction="leftbottom"]) ::slotted(lit-pop-content){
120            right:100%;
121            top:0;
122            transform:translate(-10px) scale(0);
123        }
124        :host([direction="leftbottom"]) ::slotted(lit-pop-content[open]),
125        :host([direction="leftbottom"][trigger="hover"]:hover) ::slotted(lit-pop-content),
126        :host([direction="leftbottom"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
127            transform:translate(-10px) scale(1);
128        }
129        
130        :host([direction="leftbottom"]) ::slotted(lit-pop-content)::after{
131            content: '';
132            position: absolute;
133            top: 10%;
134            left: 100%;
135            border-left: 10px solid #FFF; 
136            border-bottom: 10px solid transparent;
137        }
138        
139        :host([direction="lefttop"]) ::slotted(lit-pop-content){
140            right:100%;
141            bottom:0;
142            transform:translate(-10px) scale(0);
143            transform-origin: right bottom;
144        }
145        :host([direction="lefttop"]) ::slotted(lit-pop-content)::after{
146            content: '';
147            position: absolute;
148            bottom: 10%;
149            left: 100%;
150            border-left: 10px solid #FFF; 
151            border-top: 10px solid transparent;
152        }
153        :host([direction="lefttop"]) ::slotted(lit-pop-content[open]),
154        :host([direction="lefttop"][trigger="hover"]:hover) ::slotted(lit-pop-content),
155        :host([direction="lefttop"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
156            transform:translate(-10px) scale(1);
157        }
158        :host([direction="topright"]) ::slotted(lit-pop-content){
159            bottom:100%;
160            left:50%;
161            transform:translate(0,-10px) scale(0);
162            transform-origin: left bottom;
163        }
164        :host([direction="topright"]) ::slotted(lit-pop-content)::after{
165            content: '';
166            position: absolute; 
167            top: 100%;
168            left: 0%;
169            border-top: 10px solid #FFF;
170            border-right: 10px solid transparent;
171        }
172        :host([direction="topright"]) ::slotted(lit-pop-content[open]),
173        :host([direction="topright"][trigger="hover"]:hover) ::slotted(lit-pop-content),
174        :host([direction="topright"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
175            transform:translate(0,-10px) scale(1);
176        }
177        
178        
179        :host([direction="topleft"]) ::slotted(lit-pop-content){
180            bottom:100%;
181            right:50%;
182            transform:translate(0,-10px) scale(0);
183            transform-origin: right bottom;
184        }
185        :host([direction="topleft"]) ::slotted(lit-pop-content)::after{
186            content: '';
187            position: absolute; 
188            top: 100%;
189            right: 0%;
190            border-top: 10px solid #FFF;
191            border-left: 10px solid transparent;
192        }
193        :host([direction="topleft"]) ::slotted(lit-pop-content[open]),
194        :host([direction="topleft"][trigger="hover"]:hover) ::slotted(lit-pop-content),
195        :host([direction="topleft"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
196            transform:translate(0,-10px) scale(1);
197        }
198        
199       
200        :host([direction="rightbottom"]) ::slotted(lit-pop-content){
201            left:100%;
202            top:0;
203            transform:translate(10px) scale(0);
204            transform-origin: left top;
205        }
206        :host([direction="rightbottom"]) ::slotted(lit-pop-content)::after{
207            content: '';
208            position: absolute; 
209            top: 10%;
210            right: 100%;
211            border-top: 10px solid #FFF;
212            border-left: 10px solid transparent;
213        }
214        :host([direction="rightbottom"]) ::slotted(lit-pop-content[open]),
215        :host([direction="rightbottom"][trigger="hover"]:hover) ::slotted(lit-pop-content),
216        :host([direction="rightbottom"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
217            transform:translate(10px) scale(1);
218        }
219        :host([direction="righttop"]) ::slotted(lit-pop-content){
220            left:100%;
221            bottom:0;
222            transform:translate(10px) scale(0);
223            transform-origin: left bottom;
224        }
225        :host([direction="righttop"]) ::slotted(lit-pop-content[open]),
226        :host([direction="righttop"][trigger="hover"]:hover) ::slotted(lit-pop-content),
227        :host([direction="righttop"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
228            transform:translate(10px) scale(1);
229        }
230        :host([direction="righttop"]) ::slotted(lit-pop-content)::after{
231            content: '';
232            position: absolute; 
233            bottom: 10%;
234            right: 100%;
235            border-bottom: 10px solid #FFF;
236            border-left: 10px solid transparent;
237        }
238        
239        :host([direction="bottomright"]) ::slotted(lit-pop-content),
240        :host(:not([direction])) ::slotted(lit-pop-content){
241            left:0;
242            top:100%;
243            transform:translate(0,10px) scale(0);
244            transform-origin: left top;
245        }
246        :host([direction="bottomright"]) ::slotted(lit-pop-content)::after,
247        :host(:not([direction])) ::slotted(lit-pop-content)::after{
248            content: '';
249            position: absolute; 
250            left: 10%;
251            bottom: 100%;
252            border-bottom: 10px solid #FFF;
253            border-right: 10px solid transparent;
254        }
255        :host(:not([direction])) ::slotted(lit-pop-content[open]),
256        :host(:not([direction])[trigger="hover"]:hover) ::slotted(lit-pop-content),
257        :host(:not([direction])[trigger="focus"]:focus-within) ::slotted(lit-pop-content),
258        :host([direction="bottomright"]) ::slotted(lit-pop-content[open]),
259        :host([direction="bottomright"][trigger="hover"]:hover) ::slotted(lit-pop-content),
260        :host([direction="bottomright"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
261            transform:translate(0,10px) scale(1);
262        }
263        
264        :host([direction="bottomleft"]) ::slotted(lit-pop-content){
265            right:0;
266            top:100%;
267            transform:translate(0,10px) scale(0);
268            transform-origin: right top;
269        }
270        :host([direction="bottomleft"]) ::slotted(lit-pop-content)::after,
271        :host(:not([direction])) ::slotted(lit-pop-content)::after{
272            content: '';
273            position: absolute; 
274            right: 10%;
275            bottom: 100%;
276            border-bottom: 10px solid #FFF;
277            border-left: 10px solid transparent;
278        }
279        :host([direction="bottomleft"]) ::slotted(lit-pop-content[open]),
280        :host([direction="bottomleft"][trigger="hover"]:hover) ::slotted(lit-pop-content),
281        :host([direction="bottomleft"][trigger="focus"]:focus-within) ::slotted(lit-pop-content){
282            transform:translate(0,10px) scale(1);
283        }
284        
285        :host ::slotted(lit-pop-content[open]),
286        :host([trigger="hover"]:hover) ::slotted(lit-pop-content),
287        :host([trigger="focus"]:focus-within) ::slotted(lit-pop-content){
288            opacity:1;
289            visibility:visible;
290        }
291        slot{
292        }
293        </style>
294    `;
295
296@element('lit-popover')
297export class LitPopover extends BaseElement {
298  private popContent: LitPopContent | null | undefined;
299  private litGroup: LitRadioGroup | LitCheckGroup | undefined;
300  private _texBox: LitCheckBoxWithText | undefined;
301
302  static get observedAttributes(): string[] {
303    return [];
304  }
305
306  get type(): string {
307    return this.getAttribute('type') || '';
308  }
309
310  set type(type: string) {
311    this.setAttribute('type', type);
312  }
313
314  get title(): string {
315    return this.getAttribute('title') || '';
316  }
317
318  set title(title: string) {
319    this.setAttribute('title', title);
320  }
321
322  get limit(): LimitText {
323    if (this._texBox?.checked) {
324      return {
325        textLowerLimit: this._texBox.lowerLimit,
326        textUpperLimit: this._texBox.upLimit,
327      };
328    }
329    return { textLowerLimit: '', textUpperLimit: '' };
330  }
331
332  set dataSource(dataSource: Array<SelectBean>) {
333    this.popContent = this.querySelector<LitPopContent>('lit-pop-content');
334    if (!this.popContent) {
335      this.popContent = new LitPopContent();
336      this.appendChild(this.popContent);
337    }
338    switch (this.type) {
339      case 'multiple':
340        this.setMultiple(dataSource);
341        break;
342      case 'radio':
343        this.litGroup = new LitRadioGroup();
344        if (this.title !== '') {
345          let title = new LitPopoverTitle();
346          title.setAttribute('title', this.title || '');
347          this.popContent!.appendChild(title);
348          this.litGroup.setAttribute('layout', 'compact');
349        } else {
350          this.litGroup.setAttribute('layout', 'dispersion');
351        }
352        this.popContent!.appendChild(this.litGroup);
353        dataSource.forEach((data) => {
354          let litRadioBox = new LitRadioBox();
355          if (this.title === '') {
356            litRadioBox.setAttribute('dis', 'round');
357          } else {
358            litRadioBox.setAttribute('dis', 'check');
359          }
360          if (data.isSelected) {
361            litRadioBox.setAttribute('checked', 'true');
362          }
363          this.litGroup?.appendChild(litRadioBox);
364          litRadioBox.setAttribute('value', data.text);
365        });
366        break;
367      case 'multiple-text':
368        dataSource.forEach((data) => {
369          this._texBox = new LitCheckBoxWithText();
370          this._texBox.setAttribute('text', data.text);
371          this._texBox.setAttribute('checked', '');
372          this.popContent!.appendChild(this._texBox);
373        });
374        break;
375      case 'data-ming':
376        break;
377    }
378  }
379
380  setMultiple(dataSource: Array<SelectBean>): void {
381    this.litGroup = new LitCheckGroup();
382    this.litGroup.setAttribute('layout', 'dispersion');
383    this.popContent!.appendChild(this.litGroup);
384    dataSource.forEach((data) => {
385      let litCheckBox = new LitCheckBox();
386      this.litGroup?.appendChild(litCheckBox);
387      if (data.isSelected) {
388        litCheckBox.setAttribute('checked', 'true');
389      }
390      litCheckBox.setAttribute('value', data.text);
391    });
392  }
393
394  get select(): Array<string> | undefined {
395    if (this._texBox?.checked) {
396      return [this._texBox!.text];
397    }
398    return this.litGroup?.value;
399  }
400
401  get trigger(): string | null {
402    return this.getAttribute('trigger');
403  }
404
405  get direction(): string {
406    return this.getAttribute('direction') || 'topright';
407  }
408
409  set direction(value: string) {
410    this.setAttribute('direction', value);
411  }
412
413  get open(): boolean {
414    return this.getAttribute('open') !== null;
415  }
416
417  set open(value: boolean) {
418    if (value === null || value === false) {
419      this.removeAttribute('open');
420    } else {
421      this.setAttribute('open', '');
422    }
423  }
424
425  initElements(): void {}
426
427  initHtml(): string {
428    return `
429        ${initHtmlStyle}
430        <slot></slot>
431      `;
432  }
433
434  connectedCallback(): void {
435    if (!(this.trigger && this.trigger !== 'click')) {
436      this.addEventListener('click', () => {
437        this.popContent = this.querySelector<LitPopContent>('lit-pop-content');
438        if (!this.popContent) {
439          this.popContent = new LitPopContent();
440          this.appendChild(this.popContent);
441        }
442        this.popContent?.setAttribute('open', 'true');
443      });
444    }
445    document.addEventListener('mousedown', (ev) => {
446      const path = ev.composedPath && ev.composedPath();
447      if (
448        // @ts-ignore
449        this.popContent &&
450        !path.includes(this.popContent) &&
451        !path.includes(this.children[0]) &&
452        !path.includes(this.popContent)
453      ) {
454        this.popContent!.open = false;
455      }
456    });
457  }
458}
459
460export interface SelectBean {
461  text: string;
462  isSelected: boolean;
463  limitText?: LimitText;
464}
465
466export interface LimitText {
467  textUpperLimit: string;
468  textLowerLimit: string;
469}
470
471export interface Charge {
472  text: string;
473  isSelected: boolean;
474}
475