added all the needed code
ADD
src/header/empty-profile.ts
+export const emptyProfile = `
+<svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 26 26" fill="none">
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M13 25C19.6274 25 25 19.6274 25 13C25 6.37258 19.6274 1 13 1C6.37258 1 1 6.37258 1 13C1 19.6274 6.37258 25 13 25Z" fill="#D8D8D8" stroke="#8B8B8B"/>
+ <mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="26" height="26">
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M13 25C19.6274 25 25 19.6274 25 13C25 6.37258 19.6274 1 13 1C6.37258 1 1 6.37258 1 13C1 19.6274 6.37258 25 13 25Z" fill="white" stroke="white"/>
+ </mask>
+ <g mask="url(#mask0)">
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M17.0468 10.4586C17.0468 14.4979 15.4281 16.9214 12.9999 16.9214C10.5718 16.9214 8.95298 14.4979 8.95298 10.4586C8.95298 6.41931 12.9999 6.41931 12.9999 6.41931C12.9999 6.41931 17.0468 6.41931 17.0468 10.4586ZM4.09668 23.3842C6.52483 17.7293 12.9999 17.7293 12.9999 17.7293C12.9999 17.7293 19.475 17.7293 21.9031 23.3842C21.9031 23.3842 17.8481 25 12.9999 25C8.15169 25 4.09668 23.3842 4.09668 23.3842Z" fill="#8B8B8B"/>
+ </g>
+</svg>`
\ No newline at end of file

ADD
src/header/headerHelpers.ts
+/*
+ Copied from mashlib/src/global/metadata.ts
+ */
+import { NamedNode, sym } from 'rdflib'
+
+type ThrottleOptions = {
+ leading?: boolean;
+ throttling?: boolean;
+ trailing?: boolean;
+}
+
+export function getPod (): NamedNode {
+ // @@ TODO: This is given that mashlib runs on NSS - might need to change when we want it to run on other Pod servers
+ return sym(document.location.origin).site()
+}
+
+export function throttle (func: Function, wait: number, options: ThrottleOptions = {}): (...args: any[]) => any {
+ let context: any,
+ args: any,
+ result: any
+ let timeout: any = null
+ let previous = 0
+ const later = function () {
+ previous = !options.leading ? 0 : Date.now()
+ timeout = null
+ result = func.apply(context, args)
+ if (!timeout) context = args = null
+ }
+ return function () {
+ const now = Date.now()
+ if (!previous && !options.leading) previous = now
+ const remaining = wait - (now - previous)
+ // @ts-ignore
+ context = this
+ args = arguments
+ if (remaining <= 0 || remaining > wait) {
+ if (timeout) {
+ clearTimeout(timeout)
+ timeout = null
+ }
+ previous = now
+ result = func.apply(context, args)
+ if (!timeout) context = args = null
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining)
+ }
+ return result
+ }
+}

MODIFY
src/header/index.ts
src/header/index.ts
+/*
+ This file was copied from mashlib/src/global/header.ts file. It is modified to
+ work in solid-ui by adjusting where imported functions are found.
+ */
+import { IndexedFormula, NamedNode, sym } from 'rdflib'
+import { loginStatusBox, solidAuthClient } from '../authn/authn'
+import { widgets } from '../widgets'
+import { icon } from './icon'
+import { emptyProfile } from './empty-profile'
+import { throttle, getPod } from './headerHelpers'
+import { getOutliner } from 'solid-panes'
+
+// SolidAuthorization, SolidClam, and SolidSession was copied from mashlib/typings/solid-auth-client
+// access_token, client_id, id_token, at_hash had to be converted to camelcase for typescript compatibility
+interface SolidAuthorization {
+ accessToken: string;
+ clientId: string;
+ idToken: string;
+}
+
+interface SolidClaim {
+ atHash: string;
+ aud: string;
+ azp: string;
+ cnf: {
+ jwk: string;
+ };
+ exp: number;
+ iat: number;
+ iss: string;
+ jti: string;
+ nonce: string;
+ sub: string;
+}
+export interface SolidSession {
+ authorization: SolidAuthorization;
+ credentialType: string;
+ idClaims: SolidClaim;
+ idp: string;
+ issuer: string;
+ sessionKey: string;
+ webId: string;
+}
+
+export async function initHeader (store: IndexedFormula) {
+ const header = document.getElementById('PageHeader')
+ if (!header) {
+ return
+ }
+
+ const pod = getPod()
+ solidAuthClient.trackSession(rebuildHeader(header, store, pod))
+}
+
+function rebuildHeader (header: HTMLElement, store: IndexedFormula, pod: NamedNode) {
+ return async (session: SolidSession | null) => {
+ const user = session ? sym(session.webId) : null
+ header.innerHTML = ''
+ header.appendChild(await createBanner(store, pod, user))
+ }
+}
+
+async function createBanner (store: IndexedFormula, pod: NamedNode, user: NamedNode | null): Promise<HTMLElement> {
+ const podLink = document.createElement('a')
+ podLink.href = pod.uri
+ podLink.classList.add('header-banner__link')
+ podLink.innerHTML = icon
+
+ const menu = user
+ ? await createUserMenu(store, user)
+ : createLoginSignUpButtons()
+
+ const banner = document.createElement('div')
+ banner.classList.add('header-banner')
+ banner.appendChild(podLink)
+ banner.appendChild(menu)
+
+ return banner
+}
+
+function createLoginSignUpButtons () {
+ const profileLoginButtonPre = document.createElement('div')
+ profileLoginButtonPre.classList.add('header-banner__login')
+ profileLoginButtonPre.appendChild(loginStatusBox(document, null, {}))
+ return profileLoginButtonPre
+}
+
+async function openDashboardPane (outliner: any, pane: string): Promise<void> {
+ outliner.showDashboard({
+ pane
+ })
+}
+
+function createUserMenuButton (label: string, onClick: EventListenerOrEventListenerObject): HTMLElement {
+ const button = document.createElement('button')
+ button.classList.add('header-user-menu__button')
+ button.addEventListener('click', onClick)
+ button.innerText = label
+ return button
+}
+
+function createUserMenuLink (label: string, href: string): HTMLElement {
+ const link = document.createElement('a')
+ link.classList.add('header-user-menu__link')
+ link.href = href
+ link.innerText = label
+ return link
+}
+
+async function createUserMenu (store: IndexedFormula, user: NamedNode): Promise<HTMLElement> {
+ const fetcher = (<any>store).fetcher
+ if (fetcher) {
+ // Making sure that Profile is loaded before building menu
+ await fetcher.load(user)
+ }
+ const outliner = getOutliner(document)
+
+ const loggedInMenuList = document.createElement('ul')
+ loggedInMenuList.classList.add('header-user-menu__list')
+ loggedInMenuList.appendChild(createUserMenuItem(createUserMenuLink('Show your profile', user.uri)))
+ const menuItems = await getMenuItems(outliner)
+ menuItems.forEach(item => {
+ loggedInMenuList.appendChild(createUserMenuItem(createUserMenuButton(item.label, () => openDashboardPane(outliner, item.tabName || item.paneName))))
+ })
+ loggedInMenuList.appendChild(createUserMenuItem(createUserMenuButton('Log out', () => solidAuthClient.logout())))
+
+ const loggedInMenu = document.createElement('nav')
+ loggedInMenu.classList.add('header-user-menu__navigation-menu')
+ loggedInMenu.setAttribute('aria-hidden', 'true')
+ loggedInMenu.appendChild(loggedInMenuList)
+
+ const loggedInMenuTrigger = document.createElement('button')
+ loggedInMenuTrigger.classList.add('header-user-menu__trigger')
+ loggedInMenuTrigger.type = 'button'
+ const profileImg = getProfileImg(store, user)
+ if (typeof profileImg === 'string') {
+ loggedInMenuTrigger.innerHTML = profileImg
+ } else {
+ loggedInMenuTrigger.appendChild(profileImg)
+ }
+
+ const loggedInMenuContainer = document.createElement('div')
+ loggedInMenuContainer.classList.add('header-banner__user-menu', 'header-user-menu')
+ loggedInMenuContainer.appendChild(loggedInMenuTrigger)
+ loggedInMenuContainer.appendChild(loggedInMenu)
+
+ const throttledMenuToggle = throttle((event: Event) => toggleMenu(event, loggedInMenuTrigger, loggedInMenu), 50)
+ loggedInMenuTrigger.addEventListener('click', throttledMenuToggle)
+ let timer = setTimeout(() => null, 0)
+ loggedInMenuContainer.addEventListener('mouseover', event => {
+ clearTimeout(timer)
+ throttledMenuToggle(event)
+ })
+ loggedInMenuContainer.addEventListener('mouseout', event => {
+ timer = setTimeout(() => throttledMenuToggle(event), 200)
+ })
+
+ return loggedInMenuContainer
+}
+
+function createUserMenuItem (child: HTMLElement): HTMLElement {
+ const menuProfileItem = document.createElement('li')
+ menuProfileItem.classList.add('header-user-menu__list-item')
+ menuProfileItem.appendChild(child)
+ return menuProfileItem
+}
+
+async function getMenuItems (outliner: any): Promise<Array<{
+ paneName: string;
+ tabName?: string;
+ label: string;
+ icon: string;
+}>> {
+ return outliner.getDashboardItems()
+}
+
+function getProfileImg (store: IndexedFormula, user: NamedNode): string | HTMLElement {
+ const profileUrl = widgets.findImage(user)
+ if (!profileUrl) {
+ return emptyProfile
+ }
+ const profileImage = document.createElement('div')
+ profileImage.classList.add('header-user-menu__photo')
+ profileImage.style.backgroundImage = `url("${profileUrl}")`
+ return profileImage
+}
+
+function toggleMenu (event: Event, trigger: HTMLButtonElement, menu: HTMLElement): void {
+ const isExpanded = trigger.getAttribute('aria-expanded') === 'true'
+ const expand = event.type === 'mouseover'
+ const close = event.type === 'mouseout'
+ if ((isExpanded && expand) || (!isExpanded && close)) {
+ return
+ }
+ trigger.setAttribute('aria-expanded', (!isExpanded).toString())
+ menu.setAttribute('aria-hidden', isExpanded.toString())
+}

added all the needed code