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'; 17 18const initHtmlStyle: string = ` 19 <style> 20 :host{ 21 user-select: none; 22 display: flex; 23 font-family: Helvetica; 24 font-size: 14px; 25 color: #000; 26 text-align: left; 27 line-height: 20px; 28 font-weight: 400 29 background-color: #FFFFFF; 30 transition: background-color .3s; 31 } 32 :host(:not([disabled]):hover){ 33 display: flex; 34 background-color: var(--dark-background8,#6C9BFA); 35 color: #FFFFFF; 36 cursor: pointer; 37 } 38 :host([disabled]:hover){ 39 display: flex; 40 /*background-color:#3391FF;*/ 41 /*color: #FFFFFF;*/ 42 cursor:not-allowed; 43 } 44 :host([disabled]) .root{ 45 cursor:not-allowed; 46 display: flex; 47 align-items: center; 48 padding: 10px 24px; 49 width: 100%; 50 } 51 :host(:not([disabled])) .root{ 52 cursor:pointer; 53 display: flex; 54 align-items: center; 55 padding: 10px 24px; 56 width: 100%; 57 } 58 .name{ 59 padding-left: 10px; 60 cursor: pointer; 61 overflow-wrap: anywhere; 62 } 63 .icon{ 64 pointer-events: none; 65 } 66 :host(:not([file])) .name{ 67 pointer-events: none; 68 } 69 :host(:not([file])) .root{ 70 pointer-events: none; 71 } 72 :host([file]) .name{ 73 pointer-events: none; 74 } 75 :host([file]) .icon{ 76 pointer-events: none; 77 } 78 79 :host([back]) { 80 background-color: var(--dark-background8,#6C9BFA); 81 } 82 83 </style> 84 `; 85 86@element('lit-main-menu-item') 87export class LitMainMenuItem extends BaseElement { 88 private titleEl: HTMLElement | null | undefined; 89 private rootEL: HTMLElement | null | undefined; 90 private iconEl: HTMLElement | null | undefined; 91 private fileEL: HTMLInputElement | undefined | null; 92 93 static get observedAttributes(): string[] { 94 return ['title', 'icon', 'file', 'multi', 'disabled']; 95 } 96 97 get title(): string { 98 return this.getAttribute('title') || ''; 99 } 100 101 set title(val: string) { 102 this.setAttribute('title', val); 103 } 104 105 get multi(): boolean { 106 return this.hasAttribute('multi'); 107 } 108 109 set multi(val: boolean) { 110 if (val) { 111 this.setAttribute('multi', ''); 112 } else { 113 this.removeAttribute('multi'); 114 } 115 } 116 117 get disabled(): boolean { 118 return this.hasAttribute('disabled'); 119 } 120 121 set disabled(val: boolean) { 122 if (val) { 123 this.setAttribute('disabled', val.toString()); 124 this.fileEL?.setAttribute('disabled', val.toString()); 125 } else { 126 this.removeAttribute('disabled'); 127 this.fileEL?.removeAttribute('disabled'); 128 } 129 } 130 131 get back(): boolean { 132 return this.hasAttribute('back'); 133 } 134 135 set back(isShowBack: boolean) { 136 if (isShowBack) { 137 this.setAttribute('back', ''); 138 } else { 139 this.removeAttribute('back'); 140 } 141 } 142 143 initElements(): void { 144 this.rootEL = this.shadowRoot?.querySelector('.root'); 145 this.titleEl = this.shadowRoot?.querySelector('.name'); 146 this.iconEl = this.shadowRoot?.querySelector('.icon'); 147 this.fileEL = this.shadowRoot?.querySelector('.file'); 148 } 149 150 isFile(): boolean { 151 if (this.hasAttribute('file')) { 152 if (this.fileEL) { 153 return true; 154 } 155 } 156 return false; 157 } 158 159 connectedCallback(): void { 160 if (this.hasAttribute('file')) { 161 if (this.fileEL) { 162 this.fileEL!.addEventListener('change', (event) => { 163 let files = this.fileEL!.files; 164 if (files && files.length > 0) { 165 if (this.titleEl!.textContent!.includes('long trace') || this.multi) { 166 this.dispatchEvent( 167 new CustomEvent('file-change', { 168 // @ts-ignore 169 target: this, 170 // @ts-ignore 171 detail: event.target!.files, 172 }) 173 ); 174 } else { 175 this.dispatchEvent( 176 new CustomEvent('file-change', { 177 // @ts-ignore 178 target: this, 179 detail: files[0], 180 }) 181 ); 182 } 183 if (this.fileEL) { 184 this.fileEL.value = ''; 185 } 186 if (this.fileEL) { 187 this.fileEL.value = ''; 188 } 189 } 190 }); 191 } 192 this.addEventListener('click', (e) => { 193 e.stopPropagation(); 194 }); 195 } 196 } 197 198 initHtml(): string { 199 return ` 200 ${initHtmlStyle} 201 <input id="file" class="file" type="file" style="display:none;pointer-events: none" /> 202 <label class="root" for="file"> 203 <lit-icon class="icon" name="user" size="20"></lit-icon> 204 <label class="name"></label> 205 </label> 206 `; 207 } 208 209 attributeChangedCallback(name: string, oldValue: string, newValue: string): void { 210 switch (name) { 211 case 'title': 212 if (this.titleEl) { 213 this.titleEl.textContent = newValue; 214 if (newValue.includes('long trace')) { 215 this.fileEL!.setAttribute('multiple', ''); 216 this.fileEL!.setAttribute('webkitdirectory', ''); 217 this.fileEL!.setAttribute('directory', ''); 218 } else { 219 if (this.fileEL!.hasAttribute('multiple')) { 220 this.fileEL!.removeAttribute('multiple'); 221 this.fileEL!.removeAttribute('webkitdirectory'); 222 this.fileEL!.removeAttribute('directory'); 223 } 224 } 225 } 226 break; 227 case 'multi': 228 if (this.hasAttribute('multi')) { 229 this.fileEL!.setAttribute('multiple', ''); 230 this.fileEL!.setAttribute('webkitdirectory', ''); 231 this.fileEL!.setAttribute('directory', ''); 232 } else { 233 this.fileEL!.removeAttribute('multiple'); 234 this.fileEL!.removeAttribute('webkitdirectory'); 235 this.fileEL!.removeAttribute('directory'); 236 } 237 break; 238 case 'icon': 239 if (this.iconEl) { 240 this.iconEl.setAttribute('name', newValue); 241 } 242 break; 243 } 244 } 245} 246