/**
* Copyright Aquera Inc 2023
*
* This source code is licensed under the BSD-3-Clause license found in the
* LICENSE file in the root directory of this source tree.
*/
import { html, CSSResultArray, TemplateResult } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { styles } from './nile-app-shell-nav-toggle.css';
import { renderGlyph } from '../internal/glyph';
import '../nile-button/nile-button';
import NileElement from '../internal/nile-element';
import type { NileAppShell } from '../nile-app-shell/nile-app-shell';
/**
* @summary The side-nav toggle as a standalone control, for a header you build yourself.
*
* @status stable
* @since 2.0
*
* @tag nile-app-shell-nav-toggle
*
* @dependency nile-app-shell
* @dependency nile-glyph
*
* @csspart button - The toggle button.
* @csspart rule - The trailing vertical rule.
*
* @cssproperty [--nile-app-shell-nav-toggle-offset=-6px] - Optical start offset, so the glyph lands on the bar's text origin.
* @cssproperty [--nile-app-shell-utility-size=32px] - Box the toggle sits in; the hit area and hover surface, not a visible chip.
*/
@customElement('nile-app-shell-nav-toggle')
export class NileAppShellNavToggle extends NileElement {
public static get styles(): CSSResultArray {
return [styles];
}
/** Draws the vertical rule the shell's own bar puts after the toggle. */
@property({ type: Boolean, reflect: true, attribute: 'with-rule' })
withRule: boolean = false;
/** The shell to drive. Defaults to the nearest `nile-app-shell` ancestor, or the element with this id. */
@property({ type: String })
shell?: string;
@state() private _rail: boolean = false;
@state() private _locked: boolean = false;
private _observed?: NileAppShell;
public connectedCallback(): void {
super.connectedCallback();
// The shell may upgrade after this element does, so read it on a microtask.
Promise.resolve().then(() => this._attach());
}
public disconnectedCallback(): void {
super.disconnectedCallback();
this._observed?.removeEventListener('nile-nav-toggle', this._onShellToggle);
this._observed = undefined;
}
/** The shell this toggle drives, if it found one. */
public get appShell(): NileAppShell | null {
if (this.shell) {
const root = this.getRootNode() as Document | ShadowRoot;
return (root.querySelector(`#${this.shell}`) as NileAppShell) ?? null;
}
return this.closest('nile-app-shell') ?? null;
}
private _attach(): void {
const shell = this.appShell;
if (!shell || shell === this._observed) return;
this._observed?.removeEventListener('nile-nav-toggle', this._onShellToggle);
this._observed = shell;
shell.addEventListener('nile-nav-toggle', this._onShellToggle);
this._sync();
}
private _onShellToggle = (): void => {
this._sync();
};
private _sync(): void {
const shell = this._observed;
if (!shell) return;
this._rail = shell.rail;
this._locked = shell.navLocked;
}
public render(): TemplateResult {
const expanded = !this._rail;
return html`
${renderGlyph(
expanded ? 'ng-panel-left' : 'ng-panel-right',
20,
'currentColor'
)}
`;
}
private _onClick = (): void => {
this._attach();
this._observed?.toggleNav();
this._sync();
};
}
export default NileAppShellNavToggle;
declare global {
interface HTMLElementTagNameMap {
'nile-app-shell-nav-toggle': NileAppShellNavToggle;
}
}