UNPKG

@synergy-design-system/components

Version:

This package provides the base of the Synergy Design System as native web components. It uses [lit](https://www.lit.dev) and parts of [shoelace](https://shoelace.style/). Synergy officially supports the latest two versions of all major browsers (as define

357 lines (347 loc) 10.8 kB
import { nav_item_styles_default } from "./chunk.FCYQT7CQ.js"; import { SynDivider } from "./chunk.YOAPSA7L.js"; import { HasSlotController } from "./chunk.WVVQK5TE.js"; import { SynIcon } from "./chunk.RCBSMXQH.js"; import { watch } from "./chunk.BVZQ6QSY.js"; import { component_styles_default } from "./chunk.NLYVOJGK.js"; import { SynergyElement } from "./chunk.3THJTCRO.js"; import { __decorateClass } from "./chunk.Z4XV3SMG.js"; // src/components/nav-item/nav-item.component.ts import { classMap } from "lit/directives/class-map.js"; import { html, literal } from "lit/static-html.js"; import { property, query, state } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; var SynNavItem = class extends SynergyElement { constructor() { super(...arguments); this.hasSlotController = new HasSlotController(this, "[default]", "children", "prefix", "suffix"); this.hasFocus = false; this.showPrefixOnly = false; this.currentMarkedChild = false; this.isMultiLine = false; this.rel = "noreferrer noopener"; this.current = false; this.disabled = false; this.horizontal = false; this.chevron = false; this.open = false; this.divider = false; } isButton() { return !this.href && !this.hasSlotController.test("children"); } isLink() { return !!this.href && !this.hasSlotController.test("children"); } isAccordion() { return this.hasSlotController.test("children"); } // eslint-disable-next-line class-methods-use-this getNavItemChildren(childrenSlot) { return Array.from( (childrenSlot == null ? void 0 : childrenSlot.assignedElements({ flatten: true })) || [] ).map((slottedElement) => slottedElement.tagName.toLowerCase() === "syn-nav-item" ? slottedElement : Array.from(slottedElement.querySelectorAll(":scope > syn-nav-item"))).flat(); } getAllNestedNavItems(childrenSlot) { const allNavItems = this.getNavItemChildren(childrenSlot); const nestedNavItems = allNavItems.map((item) => item.getAllNestedNavItems(item.childrenSlot)).flat(); return allNavItems.concat(nestedNavItems); } handleCurrentMarkedChild() { const sideNav = this.closest("syn-side-nav"); if (!this.open || !!((sideNav == null ? void 0 : sideNav.variant) === "rail")) { this.currentMarkedChild = this.getAllNestedNavItems(this.childrenSlot).some((item) => item.current); } } handleClickButton(e) { if (this.disabled) { e.preventDefault(); e.stopPropagation(); } } handleClickSummary(e) { e.preventDefault(); e.stopPropagation(); if (this.disabled) return; if (this.open) { this.hideDetails(); } else { this.showDetails(); } } hideDetails() { this.open = false; this.emit("syn-hide", { cancelable: true }); } showDetails() { this.open = true; this.emit("syn-show", { cancelable: true }); } /** * Automatically add the correct level of indentation for sub items if none is provided */ handleSlotChange() { const computedStyle = getComputedStyle(this); const lengthStyle = computedStyle.length; if (lengthStyle === 0) { setTimeout(() => { this.handleSlotChange(); }); return; } this.handleCurrentMarkedChild(); const level = computedStyle.getPropertyValue("--indentation"); const nextLevel = Math.min(parseInt(level, 10) + 1, 2); this.getNavItemChildren(this.childrenSlot).forEach((item) => { item.style.setProperty("--indentation", nextLevel.toFixed(0)); }); } handleBlur() { this.hasFocus = false; this.emit("syn-blur"); } handleFocus() { this.hasFocus = true; this.emit("syn-focus"); } handleWidth(entries) { entries.forEach((entry) => { requestAnimationFrame(() => { if (entry.contentRect.width < 100) { const hasPrefix = this.hasSlotController.test("prefix"); this.showPrefixOnly = hasPrefix; } else { this.showPrefixOnly = false; } if (entry.contentRect.height > 48) { this.isMultiLine = true; } else { this.isMultiLine = false; } }); }); } handleHorizontalChange() { if (this.horizontal) { this.resizeObserver.disconnect(); } else { this.resizeObserver.observe(this); } } connectedCallback() { super.connectedCallback(); this.resizeObserver = new ResizeObserver((entries) => this.handleWidth(entries)); if (!this.horizontal) { this.resizeObserver.observe(this); } } firstUpdated(_changedProperties) { super.firstUpdated(_changedProperties); this.mutationObserver = new MutationObserver(() => { if (this.childrenSlot) { this.handleCurrentMarkedChild(); } }); this.mutationObserver.observe(this, { attributeFilter: ["current", "open"], childList: true, subtree: true }); } disconnectedCallback() { var _a, _b; super.disconnectedCallback(); (_a = this.resizeObserver) == null ? void 0 : _a.disconnect(); (_b = this.mutationObserver) == null ? void 0 : _b.disconnect(); } /** * Removes focus from the button. */ blur() { this.control.blur(); } /** * Simulates a click on the nav-items button, link or summary. */ click() { this.control.click(); } /** * Sets focus on the nav-item */ focus(options) { this.control.focus(options); } // eslint-disable-next-line complexity render() { const isButton = this.isButton(); const isLink = this.isLink(); const isAccordion = this.isAccordion(); const sideNav = this.closest("syn-side-nav"); const showCurrentIndicatorForNested = this.currentMarkedChild && !this.open || this.currentMarkedChild && this.open && !!((sideNav == null ? void 0 : sideNav.variant) === "rail") && !(sideNav == null ? void 0 : sideNav.open); let tag = literal`button`; if (isAccordion) tag = literal`summary`; else if (isLink) tag = literal`a`; const hasChevron = (this.chevron || isAccordion) && !this.horizontal; let clickAction; if (isAccordion) { clickAction = this.handleClickSummary; } else if (isButton) { clickAction = this.handleClickButton; } const root = html` <${tag} aria-controls=${ifDefined(isAccordion ? "navigation-item-details" : void 0)} aria-current=${ifDefined(this.current ? "page" : void 0)} aria-disabled=${this.disabled} @blur=${this.handleBlur} class=${classMap({ "nav-item": true, "nav-item--current": this.current || showCurrentIndicatorForNested, "nav-item--disabled": this.disabled, "nav-item--focused": this.hasFocus, "nav-item--has-content": this.hasSlotController.test("[default]"), "nav-item--has-prefix": this.hasSlotController.test("prefix"), "nav-item--has-suffix": this.hasSlotController.test("suffix"), "nav-item--horizontal": this.horizontal, "nav-item--is-link": isLink, "nav-item--multi-line": this.isMultiLine, "nav-item--show-prefix-only": this.showPrefixOnly, "nav-item--vertical": !this.horizontal, "nav-item-is-accordion": isAccordion })} @click=${clickAction} ?disabled=${ifDefined(isLink ? void 0 : this.disabled)} @focus=${this.handleFocus} href=${ifDefined(isLink ? this.href : void 0)} part="base" role=${isLink ? "link" : "button"} rel=${ifDefined(isLink ? this.rel : void 0)} tabindex=${this.disabled ? "-1" : "0"} target=${ifDefined(isLink ? this.target : void 0)} > ${this.divider && !this.horizontal ? html`<syn-divider class="divider" part="divider"></syn-divider>` : ""} <div class="nav-item__content" part="content-wrapper"> <slot name="prefix" part="prefix" class="nav-item__prefix"></slot> <div part="content-container" class="nav-item__content-container"> <slot part="content"></slot> </div> <slot name="suffix" part="suffix" class="nav-item__suffix"></slot> ${hasChevron ? html` <syn-icon class=${classMap({ "nav-item__chevron": true, "nav-item__chevron-open": this.open })} library="system" name="chevron-down" part="chevron" /></syn-icon>` : ""} <div class=${classMap({ "current-indicator": true, "current-indicator--disabled": this.disabled, "current-indicator--visible": this.current || showCurrentIndicatorForNested })} part="current-indicator" > </div> </div> </${tag}> `; return isAccordion ? html` <details id="navigation-item-details" ?open=${this.open} part="details" > ${root} <slot class="children" name="children" part="children" @slotchange=${this.handleSlotChange} ></slot> </details> ` : root; } }; SynNavItem.styles = [component_styles_default, nav_item_styles_default]; SynNavItem.dependencies = { "syn-divider": SynDivider, "syn-icon": SynIcon }; __decorateClass([ state() ], SynNavItem.prototype, "hasFocus", 2); __decorateClass([ state() ], SynNavItem.prototype, "showPrefixOnly", 2); __decorateClass([ state() ], SynNavItem.prototype, "currentMarkedChild", 2); __decorateClass([ state() ], SynNavItem.prototype, "isMultiLine", 2); __decorateClass([ query('slot[name="children"]') ], SynNavItem.prototype, "childrenSlot", 2); __decorateClass([ query(".nav-item") ], SynNavItem.prototype, "control", 2); __decorateClass([ property({ reflect: true, type: String }) ], SynNavItem.prototype, "href", 2); __decorateClass([ property() ], SynNavItem.prototype, "target", 2); __decorateClass([ property() ], SynNavItem.prototype, "rel", 2); __decorateClass([ property({ reflect: true, type: Boolean }) ], SynNavItem.prototype, "current", 2); __decorateClass([ property({ reflect: true, type: Boolean }) ], SynNavItem.prototype, "disabled", 2); __decorateClass([ property({ reflect: true, type: Boolean }) ], SynNavItem.prototype, "horizontal", 2); __decorateClass([ property({ reflect: true, type: Boolean }) ], SynNavItem.prototype, "chevron", 2); __decorateClass([ property({ reflect: true, type: Boolean }) ], SynNavItem.prototype, "open", 2); __decorateClass([ property({ reflect: true, type: Boolean }) ], SynNavItem.prototype, "divider", 2); __decorateClass([ watch("horizontal", { waitUntilFirstUpdate: true }) ], SynNavItem.prototype, "handleHorizontalChange", 1); export { SynNavItem }; //# sourceMappingURL=chunk.VI5FLXBL.js.map