UNPKG

@shoelace-style/shoelace

Version:

A forward-thinking library of web components.

232 lines (227 loc) 6.52 kB
import { details_styles_default } from "./chunk.J7PLVEQM.js"; import { getAnimation, setDefaultAnimation } from "./chunk.UW6SLYOK.js"; import { waitForEvent } from "./chunk.B4BZKR24.js"; import { animateTo, shimKeyframesHeightAuto, stopAnimations } from "./chunk.3EPZX5HE.js"; import { LocalizeController } from "./chunk.WLV3FVBR.js"; import { SlIcon } from "./chunk.E6QAPUBK.js"; import { watch } from "./chunk.CCJUT23E.js"; import { component_styles_default } from "./chunk.TUVJKY7S.js"; import { ShoelaceElement } from "./chunk.UYAO2JRR.js"; import { __decorateClass } from "./chunk.B3BW2AY6.js"; // src/components/details/details.component.ts import { classMap } from "lit/directives/class-map.js"; import { html } from "lit"; import { property, query } from "lit/decorators.js"; var SlDetails = class extends ShoelaceElement { constructor() { super(...arguments); this.localize = new LocalizeController(this); this.open = false; this.disabled = false; } firstUpdated() { this.body.style.height = this.open ? "auto" : "0"; if (this.open) { this.details.open = true; } this.detailsObserver = new MutationObserver((changes) => { for (const change of changes) { if (change.type === "attributes" && change.attributeName === "open") { if (this.details.open) { this.show(); } else { this.hide(); } } } }); this.detailsObserver.observe(this.details, { attributes: true }); } disconnectedCallback() { var _a; super.disconnectedCallback(); (_a = this.detailsObserver) == null ? void 0 : _a.disconnect(); } handleSummaryClick(event) { event.preventDefault(); if (!this.disabled) { if (this.open) { this.hide(); } else { this.show(); } this.header.focus(); } } handleSummaryKeyDown(event) { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); if (this.open) { this.hide(); } else { this.show(); } } if (event.key === "ArrowUp" || event.key === "ArrowLeft") { event.preventDefault(); this.hide(); } if (event.key === "ArrowDown" || event.key === "ArrowRight") { event.preventDefault(); this.show(); } } async handleOpenChange() { if (this.open) { this.details.open = true; const slShow = this.emit("sl-show", { cancelable: true }); if (slShow.defaultPrevented) { this.open = false; this.details.open = false; return; } await stopAnimations(this.body); const { keyframes, options } = getAnimation(this, "details.show", { dir: this.localize.dir() }); await animateTo(this.body, shimKeyframesHeightAuto(keyframes, this.body.scrollHeight), options); this.body.style.height = "auto"; this.emit("sl-after-show"); } else { const slHide = this.emit("sl-hide", { cancelable: true }); if (slHide.defaultPrevented) { this.details.open = true; this.open = true; return; } await stopAnimations(this.body); const { keyframes, options } = getAnimation(this, "details.hide", { dir: this.localize.dir() }); await animateTo(this.body, shimKeyframesHeightAuto(keyframes, this.body.scrollHeight), options); this.body.style.height = "auto"; this.details.open = false; this.emit("sl-after-hide"); } } /** Shows the details. */ async show() { if (this.open || this.disabled) { return void 0; } this.open = true; return waitForEvent(this, "sl-after-show"); } /** Hides the details */ async hide() { if (!this.open || this.disabled) { return void 0; } this.open = false; return waitForEvent(this, "sl-after-hide"); } render() { const isRtl = this.localize.dir() === "rtl"; return html` <details part="base" class=${classMap({ details: true, "details--open": this.open, "details--disabled": this.disabled, "details--rtl": isRtl })} > <summary part="header" id="header" class="details__header" role="button" aria-expanded=${this.open ? "true" : "false"} aria-controls="content" aria-disabled=${this.disabled ? "true" : "false"} tabindex=${this.disabled ? "-1" : "0"} @click=${this.handleSummaryClick} @keydown=${this.handleSummaryKeyDown} > <slot name="summary" part="summary" class="details__summary">${this.summary}</slot> <span part="summary-icon" class="details__summary-icon"> <slot name="expand-icon"> <sl-icon library="system" name=${isRtl ? "chevron-left" : "chevron-right"}></sl-icon> </slot> <slot name="collapse-icon"> <sl-icon library="system" name=${isRtl ? "chevron-left" : "chevron-right"}></sl-icon> </slot> </span> </summary> <div class="details__body" role="region" aria-labelledby="header"> <slot part="content" id="content" class="details__content"></slot> </div> </details> `; } }; SlDetails.styles = [component_styles_default, details_styles_default]; SlDetails.dependencies = { "sl-icon": SlIcon }; __decorateClass([ query(".details") ], SlDetails.prototype, "details", 2); __decorateClass([ query(".details__header") ], SlDetails.prototype, "header", 2); __decorateClass([ query(".details__body") ], SlDetails.prototype, "body", 2); __decorateClass([ query(".details__expand-icon-slot") ], SlDetails.prototype, "expandIconSlot", 2); __decorateClass([ property({ type: Boolean, reflect: true }) ], SlDetails.prototype, "open", 2); __decorateClass([ property() ], SlDetails.prototype, "summary", 2); __decorateClass([ property({ type: Boolean, reflect: true }) ], SlDetails.prototype, "disabled", 2); __decorateClass([ watch("open", { waitUntilFirstUpdate: true }) ], SlDetails.prototype, "handleOpenChange", 1); setDefaultAnimation("details.show", { keyframes: [ { height: "0", opacity: "0" }, { height: "auto", opacity: "1" } ], options: { duration: 250, easing: "linear" } }); setDefaultAnimation("details.hide", { keyframes: [ { height: "auto", opacity: "1" }, { height: "0", opacity: "0" } ], options: { duration: 250, easing: "linear" } }); export { SlDetails };