![dependabot[bot]](/assets/img/avatar_default.png) 73733b20b6
			
		
	
	73733b20b6
	
	
	
		
			
			* build(deps): bump @trivago/prettier-plugin-sort-imports in /web Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 2.0.4 to 3.0.0. - [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases) - [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/master/CHANGELOG.md) - [Commits](https://github.com/trivago/prettier-plugin-sort-imports/commits) --- updated-dependencies: - dependency-name: "@trivago/prettier-plugin-sort-imports" dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * web: update prettier config Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jens Langhammer <jens.langhammer@beryju.org>
		
			
				
	
	
		
			200 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { CSSResult, LitElement, css } from "lit";
 | |
| import { TemplateResult, html } from "lit";
 | |
| import { customElement, property } from "lit/decorators";
 | |
| import { until } from "lit/directives/until";
 | |
| 
 | |
| import AKGlobal from "../../authentik.css";
 | |
| import PFNav from "@patternfly/patternfly/components/Nav/nav.css";
 | |
| import PFPage from "@patternfly/patternfly/components/Page/page.css";
 | |
| import PFBase from "@patternfly/patternfly/patternfly-base.css";
 | |
| 
 | |
| import { ROUTE_SEPARATOR } from "../../constants";
 | |
| 
 | |
| @customElement("ak-sidebar-item")
 | |
| export class SidebarItem extends LitElement {
 | |
|     static get styles(): CSSResult[] {
 | |
|         return [
 | |
|             PFBase,
 | |
|             PFPage,
 | |
|             PFNav,
 | |
|             AKGlobal,
 | |
|             css`
 | |
|                 :host {
 | |
|                     z-index: 100;
 | |
|                     box-shadow: none !important;
 | |
|                 }
 | |
|                 :host([highlight]) .pf-c-nav__item {
 | |
|                     background-color: var(--ak-accent);
 | |
|                     margin: 16px;
 | |
|                 }
 | |
|                 :host([highlight]) .pf-c-nav__item .pf-c-nav__link {
 | |
|                     padding-left: 0.5rem;
 | |
|                 }
 | |
|                 .pf-c-nav__link.pf-m-current::after,
 | |
|                 .pf-c-nav__link.pf-m-current:hover::after,
 | |
|                 .pf-c-nav__item.pf-m-current:not(.pf-m-expanded) .pf-c-nav__link::after {
 | |
|                     --pf-c-nav__link--m-current--after--BorderColor: #fd4b2d;
 | |
|                 }
 | |
| 
 | |
|                 .pf-c-nav__section + .pf-c-nav__section {
 | |
|                     --pf-c-nav__section--section--MarginTop: var(--pf-global--spacer--sm);
 | |
|                 }
 | |
|                 .pf-c-nav__list .sidebar-brand {
 | |
|                     max-height: 82px;
 | |
|                     margin-bottom: -0.5rem;
 | |
|                 }
 | |
|                 nav {
 | |
|                     display: flex;
 | |
|                     flex-direction: column;
 | |
|                     max-height: 100vh;
 | |
|                     height: 100%;
 | |
|                     overflow-y: hidden;
 | |
|                 }
 | |
|                 .pf-c-nav__list {
 | |
|                     flex-grow: 1;
 | |
|                     overflow-y: auto;
 | |
|                 }
 | |
| 
 | |
|                 .pf-c-nav__link {
 | |
|                     --pf-c-nav__link--PaddingTop: 0.5rem;
 | |
|                     --pf-c-nav__link--PaddingRight: 0.5rem;
 | |
|                     --pf-c-nav__link--PaddingBottom: 0.5rem;
 | |
|                 }
 | |
|                 .pf-c-nav__section-title {
 | |
|                     font-size: 12px;
 | |
|                 }
 | |
|                 .pf-c-nav__item {
 | |
|                     --pf-c-nav__item--MarginTop: 0px;
 | |
|                 }
 | |
|             `,
 | |
|         ];
 | |
|     }
 | |
| 
 | |
|     @property()
 | |
|     path?: string;
 | |
| 
 | |
|     @property({ attribute: false })
 | |
|     condition: () => Promise<boolean> = async () => true;
 | |
| 
 | |
|     activeMatchers: RegExp[] = [];
 | |
| 
 | |
|     @property({ type: Boolean })
 | |
|     expanded = false;
 | |
| 
 | |
|     @property({ type: Boolean })
 | |
|     isActive = false;
 | |
| 
 | |
|     @property({ type: Boolean })
 | |
|     isAbsoluteLink?: boolean;
 | |
| 
 | |
|     @property({ type: Boolean })
 | |
|     highlight?: boolean;
 | |
| 
 | |
|     parent?: SidebarItem;
 | |
| 
 | |
|     get childItems(): SidebarItem[] {
 | |
|         const children = Array.from(this.querySelectorAll<SidebarItem>("ak-sidebar-item") || []);
 | |
|         children.forEach((child) => (child.parent = this));
 | |
|         return children;
 | |
|     }
 | |
| 
 | |
|     @property({ attribute: false })
 | |
|     set activeWhen(regexp: string[]) {
 | |
|         regexp.forEach((r) => {
 | |
|             this.activeMatchers.push(new RegExp(r));
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     firstUpdated(): void {
 | |
|         this.onHashChange();
 | |
|         window.addEventListener("hashchange", () => this.onHashChange());
 | |
|     }
 | |
| 
 | |
|     onHashChange(): void {
 | |
|         const activePath = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR)[0];
 | |
|         this.childItems.forEach((item) => {
 | |
|             this.expandParentRecursive(activePath, item);
 | |
|         });
 | |
|         this.isActive = this.matchesPath(activePath);
 | |
|     }
 | |
| 
 | |
|     private matchesPath(path: string): boolean {
 | |
|         if (!this.path) {
 | |
|             return false;
 | |
|         }
 | |
|         if (this.path) {
 | |
|             if (new RegExp(`^${this.path}$`).exec(path)) {
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
|         return this.activeMatchers.some((v) => {
 | |
|             const match = v.exec(path);
 | |
|             if (match !== null) {
 | |
|                 return true;
 | |
|             }
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     expandParentRecursive(activePath: string, item: SidebarItem): void {
 | |
|         if (item.matchesPath(activePath) && item.parent) {
 | |
|             item.parent.expanded = true;
 | |
|             this.requestUpdate();
 | |
|         }
 | |
|         item.childItems.forEach((i) => this.expandParentRecursive(activePath, i));
 | |
|     }
 | |
| 
 | |
|     render(): TemplateResult {
 | |
|         return html`${until(this.renderInner())}`;
 | |
|     }
 | |
| 
 | |
|     async renderInner(): Promise<TemplateResult> {
 | |
|         if (this.condition) {
 | |
|             const result = await this.condition();
 | |
|             if (!result) {
 | |
|                 return html``;
 | |
|             }
 | |
|         }
 | |
|         if (this.childItems.length > 0) {
 | |
|             return html`<li
 | |
|                 class="pf-c-nav__item ${this.expanded ? "pf-m-expandable pf-m-expanded" : ""}"
 | |
|             >
 | |
|                 <button
 | |
|                     class="pf-c-nav__link"
 | |
|                     aria-expanded="true"
 | |
|                     @click=${() => {
 | |
|                         this.expanded = !this.expanded;
 | |
|                     }}
 | |
|                 >
 | |
|                     <slot name="label"></slot>
 | |
|                     <span class="pf-c-nav__toggle">
 | |
|                         <span class="pf-c-nav__toggle-icon">
 | |
|                             <i class="fas fa-angle-right" aria-hidden="true"></i>
 | |
|                         </span>
 | |
|                     </span>
 | |
|                 </button>
 | |
|                 <section class="pf-c-nav__subnav" ?hidden=${!this.expanded}>
 | |
|                     <ul class="pf-c-nav__list">
 | |
|                         <slot></slot>
 | |
|                     </ul>
 | |
|                 </section>
 | |
|             </li>`;
 | |
|         }
 | |
|         return html`<li class="pf-c-nav__item">
 | |
|             ${this.path
 | |
|                 ? html`
 | |
|                       <a
 | |
|                           href="${this.isAbsoluteLink ? "" : "#"}${this.path}"
 | |
|                           class="pf-c-nav__link ${this.isActive ? "pf-m-current" : ""}"
 | |
|                       >
 | |
|                           <slot name="label"></slot>
 | |
|                       </a>
 | |
|                   `
 | |
|                 : html`
 | |
|                       <span class="pf-c-nav__link">
 | |
|                           <slot name="label"></slot>
 | |
|                       </span>
 | |
|                   `}
 | |
|         </li>`;
 | |
|     }
 | |
| }
 |