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'; 17import './LitMainMenuItem'; 18import './LitMainMenuGroup'; 19import { LitMainMenuGroup } from './LitMainMenuGroup'; 20import { LitMainMenuItem } from './LitMainMenuItem'; 21 22const initHtmlStyle: string = ` 23 <style> 24 :host{ 25 width: 248px; 26 height: 100vh; 27 display: flex; 28 flex-direction: column; 29 background-color: #fff; 30 } 31 .menu-body ::-webkit-scrollbar-thumb 32 { 33 background-color: var(--dark-background,#FFFFFF); 34 border-radius:10px; 35 36 } 37 .menu-body ::-webkit-scrollbar-track 38 { 39 border-radius:10px; 40 background-color:#F5F5F5; 41 42 } 43 .header{ 44 display: grid; 45 width: 100%; 46 height: 56px; 47 font-size: 1.4rem; 48 padding-left: 20px; 49 gap: 0 20px; 50 box-sizing: border-box; 51 grid-template-columns: min-content 1fr min-content; 52 grid-template-rows: auto; 53 color: #47A7E0; 54 background-color: var(--dark-background1); 55 border-bottom: 1px solid var(--dark-background1,#EFEFEF); 56 } 57 .bottom{ 58 width: 100%; 59 display: flex; 60 justify-content: space-between; 61 } 62 .header *{ 63 user-select: none; 64 align-self: center; 65 } 66 .version{ 67 width: 15rem; 68 padding: 20px 0; 69 text-align: center; 70 color: #94979d; 71 font-size: 0.6rem; 72 } 73 .color, .customColor{ 74 cursor: pointer; 75 font-size: 0.6rem; 76 padding: 20px 0px 20px 20px; 77 } 78 *{ 79 box-sizing: border-box; 80 } 81 .menu-button{ 82 display: flex; 83 align-content: center; 84 justify-content: right; 85 cursor: pointer; 86 height: 47px; 87 width: 48px; 88 } 89 </style> 90 `; 91 92@element('lit-main-menu') 93export class LitMainMenu extends BaseElement { 94 private slotElements: Element[] | undefined; 95 private _menus: Array<MenuGroup> | undefined; 96 97 static get observedAttributes(): string[] { 98 return []; 99 } 100 101 get menus(): Array<MenuGroup> | undefined { 102 return this._menus; 103 } 104 105 set menus(value: Array<MenuGroup> | undefined) { 106 this._menus = value; 107 this.shadowRoot?.querySelectorAll('lit-main-menu-group').forEach((a) => a.remove()); 108 let menuBody = this.shadowRoot?.querySelector('.menu-body'); 109 if (this.getAttribute('main_menu') === '1' && window.localStorage.getItem('Theme') === 'dark') { 110 this.style.backgroundColor = '#262f3c'; 111 } else { 112 this.style.backgroundColor = '#fff'; 113 } 114 value?.forEach((it) => { 115 let group: LitMainMenuGroup = new LitMainMenuGroup(); 116 group.setAttribute('title', it.title || ''); 117 if (it.describe !== '') { 118 group.setAttribute('describe', it.describe || ''); 119 } else { 120 group.removeAttribute('describe'); 121 } 122 group.setAttribute('icon', it.icon || ''); 123 if (it.collapsed) { 124 group.setAttribute('collapsed', ''); 125 } else { 126 group.removeAttribute('collapsed'); 127 } 128 let groupName: LitMainMenuGroup = group!.shadowRoot!.querySelector('.group-name') as LitMainMenuGroup; 129 let groupDescribe: LitMainMenuGroup = group!.shadowRoot!.querySelector('.group-describe') as LitMainMenuGroup; 130 menuBody?.appendChild(group); // @ts-ignore 131 it.children?.forEach((item: unknown) => { 132 // @ts-ignore 133 if (item.fileModel !== undefined && item.fileModel === 'db') { 134 return; 135 } // @ts-ignore 136 if (item.children && item.children.length > 0) { 137 let secondGroup: LitMainMenuGroup = new LitMainMenuGroup(); // @ts-ignore 138 secondGroup.setAttribute('title', item.title || ''); // @ts-ignore 139 if (item.describe !== '') { 140 // @ts-ignore 141 secondGroup.setAttribute('describe', item.describe || ''); 142 } else { 143 secondGroup.removeAttribute('describe'); 144 } 145 this.setChildren(item, group, groupName, groupDescribe, secondGroup); 146 } else { 147 this.notChildren(item, group, groupName, groupDescribe); 148 } 149 }); 150 }); 151 } 152 153 setChildren( 154 item: unknown, 155 group: LitMainMenuGroup, 156 groupName: LitMainMenuGroup, 157 groupDescribe: LitMainMenuGroup, 158 secondGroup: LitMainMenuGroup 159 ): void { 160 // @ts-ignore 161 secondGroup.setAttribute('icon', item.icon || ''); // @ts-ignore 162 if (item.second) { 163 secondGroup.setAttribute('second', ''); 164 } else { 165 secondGroup.removeAttribute('second'); 166 } // @ts-ignore 167 if (item.collapsed) { 168 secondGroup.setAttribute('collapsed', ''); 169 } else { 170 secondGroup.removeAttribute('collapsed'); 171 } 172 group?.appendChild(secondGroup); // @ts-ignore 173 item.children?.forEach((v: unknown) => { 174 let th = new LitMainMenuItem(); // @ts-ignore 175 th.setAttribute('icon', v.icon || ''); // @ts-ignore 176 th.setAttribute('title', v.title || ''); 177 if (this.getAttribute('main_menu') === '1' && window.localStorage.getItem('Theme') === 'dark') { 178 groupName.style.color = 'white'; 179 groupDescribe.style.color = 'white'; 180 th!.style.color = 'white'; 181 } else { 182 groupName.style.color = 'black'; 183 groupDescribe.style.color = 'black'; 184 th!.style.color = 'black'; 185 } // @ts-ignore 186 if (v.fileChoose) { 187 th.setAttribute('file', ''); 188 th.addEventListener('file-change', (e): void => { 189 // @ts-ignore 190 if (v.fileHandler && !th.disabled) { // @ts-ignore 191 v.fileHandler(e); 192 } 193 }); 194 } else { 195 th.removeAttribute('file'); 196 th.addEventListener('click', (e): void => { 197 // @ts-ignore 198 if (v.clickHandler && !th.disabled) { // @ts-ignore 199 v.clickHandler(v); 200 } 201 }); 202 } // @ts-ignore 203 if (v.disabled !== undefined) { // @ts-ignore 204 th.disabled = v.disabled; 205 } 206 secondGroup.appendChild(th); 207 }); 208 } 209 210 notChildren( 211 item: unknown, 212 group: LitMainMenuGroup, 213 groupName: LitMainMenuGroup, 214 groupDescribe: LitMainMenuGroup 215 ): void { 216 let th = new LitMainMenuItem(); // @ts-ignore 217 th.setAttribute('icon', item.icon || ''); // @ts-ignore 218 th.setAttribute('title', item.title || ''); 219 if (this.getAttribute('main_menu') === '1' && window.localStorage.getItem('Theme') === 'dark') { 220 groupName.style.color = 'white'; 221 groupDescribe.style.color = 'white'; 222 th!.style.color = 'white'; 223 } else { 224 groupName.style.color = 'black'; 225 groupDescribe.style.color = 'black'; 226 th!.style.color = 'black'; 227 } // @ts-ignore 228 if (item.fileChoose) { 229 th.setAttribute('file', ''); 230 th.addEventListener('file-change', (e) => { 231 // @ts-ignore 232 if (item.fileHandler && !th.disabled) { 233 // @ts-ignore 234 item.fileHandler(e); 235 } 236 }); 237 } else { 238 th.removeAttribute('file'); 239 th.addEventListener('click', (e) => { 240 // @ts-ignore 241 if (item.clickHandler && !th.disabled) { 242 // @ts-ignore 243 item.clickHandler(item); 244 } 245 }); 246 } 247 // @ts-ignore 248 if (item.multi) { 249 th.multi = true; 250 } 251 // @ts-ignore 252 if (item.disabled !== undefined) { 253 // @ts-ignore 254 th.disabled = item.disabled; 255 } 256 group?.appendChild(th); 257 } 258 259 initElements(): void { 260 let st: HTMLSlotElement | null | undefined = this.shadowRoot?.querySelector('#st'); 261 st?.addEventListener('slotchange', (e) => { 262 this.slotElements = st?.assignedElements(); 263 this.slotElements?.forEach((it) => { 264 it.querySelectorAll('lit-main-menu-item').forEach((cell) => {}); 265 }); 266 }); 267 let versionDiv: HTMLElement | null | undefined = this.shadowRoot?.querySelector<HTMLElement>('.version'); 268 //@ts-ignore 269 versionDiv!.innerText = window.version || ''; 270 } 271 272 initHtml(): string { 273 return ` 274 ${initHtmlStyle} 275 <div class="header" name="header"> 276 <img src="img/logo.png"/> 277 <div class="menu-button"> 278 <lit-icon name="menu" size="20" color="var(blue,#4D4D4D)"></lit-icon> 279 </div> 280 </div> 281 <div class="menu-body" style="overflow: auto;overflow-x:hidden;height: 100%"> 282 <slot id="st" ></slot> 283 </div> 284 <div class="bottom"> 285 <div class="customColor"> 286 <lit-icon name="bg-colors" size="20" color="grey"></lit-icon> 287 </div> 288 <div class="version" style=""> 289 </div> 290 </div>`; 291 } 292} 293 294export interface MenuGroup { 295 title: string; 296 describe: string; 297 second: boolean; 298 collapsed: boolean; 299 children: MenuItem[]; 300 icon: string; 301} 302 303export interface MenuItem { 304 icon: string; 305 title: string; 306 fileModel?: string; 307 multi?: boolean; 308 disabled?: boolean; 309 fileChoose?: boolean; 310 clickHandler?: Function; 311 fileHandler?: Function; 312} 313