import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; // @ts-ignore import PageStyle from "@patternfly/patternfly/components/Page/page.css"; // @ts-ignore import NavStyle from "@patternfly/patternfly/components/Nav/nav.css"; // @ts-ignore import GlobalsStyle from "@patternfly/patternfly/base/patternfly-globals.css"; // @ts-ignore import AKGlobal from "../../authentik.css"; import { until } from "lit-html/directives/until"; import "./SidebarBrand"; import "./SidebarUser"; export class SidebarItem { name: string; path?: string; _children: SidebarItem[]; condition: () => Promise; activeMatchers: RegExp[]; constructor(name: string, path?: string) { this.name = name; this.path = path; this._children = []; this.condition = async () => true; this.activeMatchers = []; if (this.path) { this.activeMatchers.push(new RegExp(`^${this.path}$`)); } } children(...children: SidebarItem[]): SidebarItem { this._children = children; return this; } activeWhen(...regexp: string[]): SidebarItem { regexp.forEach(r => { this.activeMatchers.push(new RegExp(r)); }); return this; } when(condition: () => Promise): SidebarItem { this.condition = condition; return this; } hasChildren(): boolean { return this._children.length > 0; } isActive(activePath: string): boolean { if (!this.path) { return false; } return this.activeMatchers.some(v => { const match = v.exec(activePath); if (match !== null) { return true; } }); } async render(activePath: string): Promise { if (this.condition) { const result = await this.condition(); if (!result) { return html``; } } return html`
  • ${this.path ? html` ${this.name} ` : html` ${this.name}
      ${this._children.map((i) => until(i.render(activePath), html``))}
    `}
  • `; } } @customElement("ak-sidebar") export class Sidebar extends LitElement { @property({attribute: false}) items: SidebarItem[] = []; @property() activePath: string; static get styles(): CSSResult[] { return [ GlobalsStyle, PageStyle, NavStyle, AKGlobal, css` .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__subnav { --pf-c-nav__subnav--PaddingBottom: 0px; } `, ]; } constructor() { super(); this.activePath = window.location.hash.slice(1, Infinity); window.addEventListener("hashchange", () => { this.activePath = window.location.hash.slice(1, Infinity); }); } render(): TemplateResult { return html``; } }