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