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