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-allocation-select') 19export class LitAllocationSelect extends BaseElement { 20 private inputElement: HTMLInputElement | null | undefined; 21 private inputContent: HTMLDivElement | undefined; 22 private options: any; 23 24 static get observedAttributes() { 25 return [ 26 'value','disabled','placeholder' 27 ]; 28 } 29 30 get defaultPlaceholder() { 31 return this.getAttribute('placeholder') || ''; 32 } 33 34 get placeholder() { 35 return this.getAttribute('placeholder') || this.defaultPlaceholder; 36 } 37 38 set placeholder(value) { 39 this.setAttribute('placeholder', value); 40 } 41 42 get value() { 43 return this.getAttribute('value') || ""; 44 } 45 46 set value(value: string) { 47 this.setAttribute('value', value); 48 } 49 50 set processData(value: Array<string>) { 51 this.options.innerHTML = ''; 52 value.forEach( 53 item => { 54 let option = document.createElement("div"); 55 option.className = 'option'; 56 option.innerHTML = item; 57 option.style.padding = '8px 10px'; 58 this.options.appendChild(option); 59 this.inputElement?.focus(); 60 } 61 ) 62 } 63 64 get placement(): string { 65 return this.getAttribute("placement") || ""; 66 } 67 68 set placement(placement: string) { 69 if (placement) { 70 this.setAttribute("placement", placement); 71 } else { 72 this.removeAttribute("placement"); 73 } 74 } 75 76 get listHeight() { 77 return this.getAttribute('list-height') || '256px'; 78 } 79 80 set listHeight(value) { 81 this.setAttribute('list-height', value); 82 } 83 84 initElements(): void { 85 this.inputContent = this.shadowRoot!.querySelector('.multipleSelect') as HTMLDivElement; 86 this.addEventListener('click', () => { 87 if (this.options.style.visibility == 'visible') { 88 this.options.style.visibility = 'hidden'; 89 this.options.style.opacity = '0'; 90 } else { 91 this.options.style.visibility = 'visible'; 92 this.options.style.opacity = '1'; 93 } 94 this.inputContent!.dispatchEvent(new CustomEvent('inputClick', {})); 95 }) 96 this.addEventListener('focusout', (e) => { 97 setTimeout(()=>{ 98 this.options.style.visibility = 'hidden'; 99 this.options.style.opacity = '0'; 100 }, 200) 101 }) 102 this.initData(); 103 } 104 105 initHtml() { 106 return ` 107 <style> 108 :host{ 109 display: inline-flex; 110 position: relative; 111 overflow: visible; 112 cursor: pointer; 113 border-radius: 16px; 114 outline: none; 115 -webkit-user-select:none ; 116 -moz-user-select:none; 117 user-select:none; 118 width: 75%; 119 } 120 :host(:not([border])), 121 :host([border='true']){ 122 border: 1px solid var(--bark-prompt,#dcdcdc); 123 } 124 input{ 125 border: 0; 126 outline: none; 127 background-color: transparent; 128 cursor: pointer; 129 -webkit-user-select:none ; 130 -moz-user-select:none; 131 user-select:none; 132 display: inline-flex; 133 color: var(--dark-color2,rgba(0,0,0,0.9)); 134 z-index: 8999; 135 width:100%; 136 } 137 .multipleSelect{ 138 position: relative; 139 padding: 3px 6px; 140 display: flex; 141 align-items: center; 142 justify-content: space-between; 143 transition: all .3s; 144 outline: none; 145 font-size: 1rem; 146 z-index: 2999; 147 -webkit-user-select:none ; 148 -moz-user-select:none; 149 user-select:none; 150 width: 100%; 151 } 152 .body{ 153 max-height: ${this.listHeight}; 154 position: absolute; 155 bottom: 100%; 156 z-index: 99; 157 padding-top: 5px; 158 margin-top: 2px; 159 background-color: var(--dark-background4,#fff); 160 width: 100%; 161 transition: all 0.2s; 162 visibility: hidden; 163 164 opacity: 0; 165 transform-origin: bottom center; 166 display: block; 167 flex-direction: column; 168 box-shadow: 0 5px 15px 0px #00000033; 169 border-radius: 2px; 170 overflow: auto; 171 } 172 .body-bottom{ 173 bottom: auto; 174 top: 100%; 175 transform-origin: top center; 176 } 177 :host([placement="bottom"]) .body{ 178 bottom:unset; 179 top: 100%; 180 transition: none; 181 transform: none; 182 } 183 184 :host([disabled]) { 185 pointer-events: none; 186 background-color: var(--dark-background1,#f5f5f5); 187 cursor: not-allowed; 188 } 189 190 .multipleRoot input::-webkit-input-placeholder { 191 color: var(--dark-color,#aab2bd); 192 } 193 </style> 194 <div class="multipleSelect" tabindex="0"> 195 <div class="multipleRoot" id="select" style="width:100%"> 196 <input id="input" placeholder="${this.placeholder}"/> 197 </div> 198 <lit-icon class="icon" name='down' color="#c3c3c3"></lit-icon> 199 </div> 200 <div class="body body-bottom"> 201 <slot></slot> 202 <slot name="footer"></slot> 203 </div> 204 ` 205 } 206 207 connectedCallback() { 208 } 209 210 initData() { 211 this.inputElement = this.shadowRoot!.querySelector('input'); 212 this.options = this.shadowRoot!.querySelector('.body') as HTMLDivElement; 213 this.inputElement?.addEventListener('keyup', () => { 214 let filter = [...this.shadowRoot!.querySelectorAll<HTMLDivElement>('.option')].filter((a: HTMLDivElement) => { 215 if (a.textContent!.indexOf(this.inputElement!.value) <= -1) { 216 a.style.display = "none"; 217 } else { 218 a.style.display = "block"; 219 } 220 }); 221 this.value = this.inputElement!.value 222 this.inputContent!.dispatchEvent(new CustomEvent('valuable', {})); 223 }) 224 this.shadowRoot?.querySelectorAll('.option').forEach(a => { 225 a.addEventListener('click', (e) => { 226 a.dispatchEvent(new CustomEvent('onSelected', { 227 detail: { 228 selected: true, 229 text: a.textContent 230 } 231 })) 232 }) 233 a.addEventListener('onSelected', (e: any) => { 234 this.inputElement!.value = e.detail.text; 235 this.value = e.detail.text; 236 this.inputContent!.dispatchEvent(new CustomEvent('valuable', {})); 237 }) 238 }) 239 } 240 241} 242