@synergy-design-system/components
Version:
239 lines (231 loc) • 7.79 kB
JavaScript
import {
header_styles_default
} from "./chunk.HUJAKIZN.js";
import {
HasSlotController
} from "./chunk.CHFWLQN5.js";
import {
SynIcon
} from "./chunk.KODS2CCZ.js";
import {
LocalizeController
} from "./chunk.ZXMSJF2M.js";
import {
watch
} from "./chunk.UR2E7Y2Q.js";
import {
component_styles_default
} from "./chunk.2NT3B5WJ.js";
import {
SynergyElement
} from "./chunk.L2IYPRPF.js";
import {
__decorateClass
} from "./chunk.VK2FVWOF.js";
// src/components/header/header.component.ts
import { classMap } from "lit/directives/class-map.js";
import { html } from "lit/static-html.js";
import { property, query, state } from "lit/decorators.js";
var SynHeader = class extends SynergyElement {
constructor() {
super(...arguments);
this.hasSlotController = new HasSlotController(this, "[default]", "logo", "label", "meta-navigation", "navigation");
this.localize = new LocalizeController(this);
/*
* #587: If the side nav is animating, we should not allow to trigger the burger menu
*/
this.isSideNavAnimating = false;
this.label = "";
this.burgerMenu = "hidden";
this.sticky = false;
}
toggleBurgerMenu() {
switch (this.burgerMenu) {
case "closed":
this.burgerMenu = "open";
break;
case "open":
this.burgerMenu = "closed";
break;
default:
break;
}
}
handleBurgerMenuToggle() {
if (this.sideNav && this.sideNav.variant === "default" && !this.isSideNavAnimating) {
this.sideNav.open = !this.sideNav.open;
}
if (!this.isSideNavAnimating) {
this.toggleBurgerMenu();
}
}
/**
* Automatically update the burger menu icon based
* on the state of the side-nav, if one is connected.
*/
updateBurgerMenuBasedOnSideNav() {
if (this.sideNav) {
if (this.sideNav.variant !== "default") {
this.burgerMenu = "hidden";
} else {
this.burgerMenu = this.sideNav.open ? "open" : "closed";
}
}
}
/**
* #1130: Automatically set the correct styles for vertical syn-dividers in the meta navigation.
* Dividers may be slotted directly in the meta navigation or be nested in another element, e.g. a wrapper for the meta navigation.
* Horizontal dividers are not supported in the meta navigation and we don't want to override any styles for them that might be set by the user.
*/
updateMetaNavigation() {
const foundDividers = [];
this.metaNavigationSlot.assignedElements({ flatten: true }).forEach((el) => {
if (el.tagName.toLowerCase() === "syn-divider") {
foundDividers.push(el);
} else {
const directChildDividers = el.querySelectorAll(":scope > syn-divider");
if (directChildDividers.length) {
foundDividers.push(...directChildDividers);
}
}
});
const cssText = "--spacing: var(--syn-spacing-x-small); align-self: center; display: flex; height: var(--metanavigation-item-size);";
foundDividers.filter((divider) => divider.hasAttribute("vertical")).forEach((divider) => {
divider.style.cssText += cssText;
});
}
handleBurgerMenu() {
const myEvt = `syn-burger-menu-${this.burgerMenu}`;
this.emit(myEvt);
}
connectedCallback() {
super.connectedCallback();
this.mutationObserver = new MutationObserver(() => this.updateBurgerMenuBasedOnSideNav());
}
firstUpdated() {
this.updateComplete.then(() => {
const sideNav = document.querySelector("syn-side-nav");
this.connectSideNavigation(sideNav);
});
}
disconnectedCallback() {
super.disconnectedCallback();
this.mutationObserver.disconnect();
}
/**
* Connect a `syn-side-nav` to add automatic interaction of the header with the side navigation
* like showing the burger menu icon and open / close handling.
*
* If no side navigation is connected, the header will use the first `syn-side-nav` element it
* finds.
*
* @param sideNav The side navigation to connect to the header
*/
connectSideNavigation(sideNav) {
this.mutationObserver.disconnect();
this.sideNav = sideNav || document.querySelector("syn-side-nav");
if (this.sideNav) {
this.updateBurgerMenuBasedOnSideNav();
this.mutationObserver.observe(this.sideNav, { attributeFilter: ["open", "variant"], attributes: true });
const isAnimating = (e) => {
if (e.target !== this.sideNav) {
return;
}
this.isSideNavAnimating = true;
};
const isNotAnimating = (e) => {
if (e.target !== this.sideNav) {
return;
}
this.isSideNavAnimating = false;
};
this.sideNav.addEventListener("syn-show", isAnimating);
this.sideNav.addEventListener("syn-hide", isAnimating);
this.sideNav.addEventListener("syn-after-show", isNotAnimating);
this.sideNav.addEventListener("syn-after-hide", isNotAnimating);
}
}
render() {
const hasNavigation = this.hasSlotController.test("navigation");
const showBurgerMenu = this.burgerMenu !== "hidden";
return html`
<header
class=${classMap({
header: true,
"header--has-burger-menu": showBurgerMenu,
"header--has-navigation": hasNavigation
})}
part="base"
>
<!-- .header__content -->
<div part="content" class="header__content">
${showBurgerMenu ? html`
<button
aria-label=${this.localize.term(this.burgerMenu === "closed" ? "openMenu" : "closeMenu")}
class="header__burger-menu-toggle"
@click=${this.handleBurgerMenuToggle}
part="burger-menu-toggle-button"
type="button"
>
${this.burgerMenu === "open" ? html`
<slot name="open-burger-menu-icon">
<syn-icon name="x-lg" library="system"></syn-icon>
</slot>
` : html`
<slot name="closed-burger-menu-icon">
<syn-icon name="menu" library="system"></syn-icon>
</slot>
`}
</button>
` : ""}
<div part="logo" class="header__logo">
<slot name="logo">
<syn-icon name="logo-color" library="system" label="SICK Sensor Intelligence"></syn-icon>
</slot>
</div>
<div part="label" class="header__label">
<slot name="label">
${this.label}
</slot>
</div>
<div part="meta-navigation" class="header__meta-navigation">
<slot @slotchange=${this.updateMetaNavigation} name="meta-navigation"></slot>
</div>
</div>
<!-- /.header__content -->
<div part="navigation" class="header__navigation">
<slot name="navigation"></slot>
</div>
</header>
`;
}
};
SynHeader.styles = [
component_styles_default,
header_styles_default
];
SynHeader.dependencies = {
"syn-icon": SynIcon
};
__decorateClass([
query('slot[name="meta-navigation"]')
], SynHeader.prototype, "metaNavigationSlot", 2);
__decorateClass([
property()
], SynHeader.prototype, "label", 2);
__decorateClass([
property({ attribute: "burger-menu", reflect: true })
], SynHeader.prototype, "burgerMenu", 2);
__decorateClass([
property({ reflect: true, type: Boolean })
], SynHeader.prototype, "sticky", 2);
__decorateClass([
state()
], SynHeader.prototype, "sideNav", 2);
__decorateClass([
watch("burgerMenu", { waitUntilFirstUpdate: true })
], SynHeader.prototype, "handleBurgerMenu", 1);
export {
SynHeader
};
//# sourceMappingURL=chunk.JDDXIPHU.js.map