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