UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

124 lines (123 loc) • 8.4 kB
/*! All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://github.com/Esri/calcite-design-system/blob/dev/LICENSE.md for details. v3.2.1 */ import { c as customElement } from "../../chunks/runtime.js"; import { html } from "lit-html"; import { keyed } from "lit-html/directives/keyed.js"; import { LitElement, createEvent, safeClassMap, nothing } from "@arcgis/lumina"; import { h as focusFirstTabbable } from "../../chunks/dom.js"; import { i as isActivationKey } from "../../chunks/key.js"; import { c as componentFocusable } from "../../chunks/component.js"; import { u as useT9n } from "../../chunks/useT9n.js"; import { l as logger } from "../../chunks/logger.js"; import { css } from "@lit/reactive-element/css-tag.js"; const IDS = { content: "content", toggle: "toggle" }; const CSS = { chevronIcon: "chevron-icon", content: "content", iconStart: "icon--start", iconEnd: "icon--end", invalid: "invalid", sectionHeader: "section-header", sectionHeaderText: "section-header__text", statusIcon: "status-icon", switch: "switch", toggle: "toggle", toggleSwitch: "toggle--switch", toggleContainer: "toggle-container", toggleSwitchContent: "toggle--switch__content", toggleSwitchText: "toggle--switch__text", valid: "valid" }; const ICONS = { menuExpanded: "chevron-up", menuCollapsed: "chevron-down", valid: "check-circle", invalid: "exclamation-mark-triangle" }; const styles = css`:host{box-sizing:border-box;display:block;font-size:var(--calcite-font-size--1);color:var(--calcite-block-section-header-text-color, var(--calcite-color-text-2));background-color:var(--calcite-block-section-background-color, var(--calcite-color-foreground-1))}:host([expanded]){border-width:0px;border-block-end-width:1px;border-style:solid;border-block-end-color:var(--calcite-block-section-border-color, var(--calcite-color-border-3))}:host([expanded]) .toggle{color:var(--calcite-block-section-text-color-hover, var(--calcite-color-text-1))}:host([expanded]) .toggle:hover{color:var(--calcite-block-section-text-color-hover, var(--calcite-color-text-1))}:host([expanded]) .chevron-icon{color:var(--calcite-block-section-text-color, var(--calcite-color-text-3))}:host([expanded]) .chevron-icon:hover{color:var(--calcite-block-section-text-color-hover, var(--calcite-color-text-1))}:host(:last-child){border-block-end-width:0px}.toggle{inline-size:100%;border-width:0px;font-family:var(--calcite-font-family);gap:var(--calcite-spacing-md);color:var(--calcite-block-section-header-text-color, var(--calcite-color-text-2));background-color:var(--calcite-block-section-background-color, transparent);font-weight:var(--calcite-font-weight-normal)}.toggle:hover{color:var(--calcite-block-section-text-color-hover, var(--calcite-color-text-1))}.toggle--switch,.section-header{margin-inline:0px;margin-block:.25rem;display:flex;cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;padding-inline:0px;padding-block:.5rem;font-size:var(--calcite-font-size--1);outline-color:transparent}.toggle--switch:focus,.section-header:focus{outline:2px solid var(--calcite-color-focus, var(--calcite-ui-focus-color, var(--calcite-color-brand)));outline-offset:calc(2px*(1 - (2*clamp(0,var(--calcite-offset-invert-focus),1))))}.toggle--switch:hover,.section-header:hover{color:var(--calcite-block-section-text-color-hover, var(--calcite-color-text-1))}.section-header__text{margin-block:0px;flex:1 1 auto;text-align:initial;word-wrap:anywhere}.toggle-container{position:relative;display:flex;align-items:center;word-break:break-word;background-color:var(--calcite-block-section-background-color, transparent)}.toggle-container .toggle--switch__content{display:flex;flex:1 1 auto;align-items:center}.toggle-container .icon--end,.toggle-container .icon--start,.toggle-container .chevron-icon{display:flex;align-items:center;color:var(--calcite-block-section-text-color, var(--calcite-color-text-3))}.toggle-container .icon--end:hover,.toggle-container .icon--start:hover,.toggle-container .chevron-icon:hover{color:var(--calcite-block-section-text-color-hover, var(--calcite-color-text-1))}.status-icon{display:flex;align-items:center}.status-icon.valid{color:var(--calcite-color-status-success)}.status-icon.invalid{color:var(--calcite-color-status-danger)}:host([hidden]){display:none}[hidden]{display:none}`; class BlockSection extends LitElement { constructor() { super(...arguments); this.messages = useT9n(); this.expanded = false; this.toggleDisplay = "button"; this.calciteBlockSectionToggle = createEvent({ cancelable: false }); } static { this.properties = { expanded: [7, {}, { reflect: true, type: Boolean }], iconEnd: [3, {}, { reflect: true }], iconFlipRtl: [3, {}, { reflect: true }], iconStart: [3, {}, { reflect: true }], messageOverrides: [0, {}, { attribute: false }], open: [7, {}, { reflect: true, type: Boolean }], status: [3, {}, { reflect: true }], text: 1, toggleDisplay: [3, {}, { reflect: true }] }; } static { this.styles = styles; } get open() { return this.expanded; } set open(value) { logger.deprecated("property", { name: "open", removalVersion: 4, suggested: "expanded" }); this.expanded = value; } async setFocus() { await componentFocusable(this); focusFirstTabbable(this.el); } handleHeaderKeyDown(event) { if (isActivationKey(event.key)) { this.toggleSection(); event.preventDefault(); event.stopPropagation(); } } toggleSection() { this.expanded = !this.expanded; this.calciteBlockSectionToggle.emit(); } renderStatusIcon() { const { status } = this; const statusIcon = ICONS[status] ?? false; const statusIconClasses = { [CSS.statusIcon]: true, [CSS.valid]: status == "valid", [CSS.invalid]: status == "invalid" }; return statusIcon ? html`<calcite-icon class=${safeClassMap(statusIconClasses)} .icon=${statusIcon} scale=s></calcite-icon>` : null; } renderIcon(icon) { const { iconFlipRtl } = this; if (icon === void 0) { return null; } const flipRtlStart = iconFlipRtl === "both" || iconFlipRtl === "start"; const flipRtlEnd = iconFlipRtl === "both" || iconFlipRtl === "end"; const isIconStart = icon === this.iconStart; return keyed(isIconStart ? this.iconStart : this.iconEnd, html`<calcite-icon class=${safeClassMap(isIconStart ? CSS.iconStart : CSS.iconEnd)} .flipRtl=${isIconStart ? flipRtlStart : flipRtlEnd} .icon=${isIconStart ? this.iconStart : this.iconEnd} scale=s></calcite-icon>`); } render() { const { messages, expanded, text, toggleDisplay } = this; const arrowIcon = expanded ? ICONS.menuExpanded : ICONS.menuCollapsed; const toggleLabel = expanded ? messages.collapse : messages.expand; const headerNode = toggleDisplay === "switch" ? html`<div class=${safeClassMap({ [CSS.toggleContainer]: true })}><div aria-controls=${IDS.content} .ariaExpanded=${expanded} class=${safeClassMap({ [CSS.toggle]: true, [CSS.toggleSwitch]: true })} id=${IDS.toggle} @click=${this.toggleSection} @keydown=${this.handleHeaderKeyDown} role=button tabindex=0 title=${toggleLabel ?? nothing}>${this.renderIcon(this.iconStart)}<div class=${safeClassMap(CSS.toggleSwitchContent)}><span class=${safeClassMap(CSS.toggleSwitchText)}>${text}</span></div>${this.renderIcon(this.iconEnd)}${this.renderStatusIcon()}<calcite-switch .checked=${expanded} class=${safeClassMap(CSS.switch)} inert .label=${toggleLabel} scale=s></calcite-switch></div></div>` : html`<div class=${safeClassMap({ [CSS.toggleContainer]: true })}><button aria-controls=${IDS.content} .ariaExpanded=${expanded} class=${safeClassMap({ [CSS.sectionHeader]: true, [CSS.toggle]: true })} id=${IDS.toggle} @click=${this.toggleSection}>${this.renderIcon(this.iconStart)}<span class=${safeClassMap(CSS.sectionHeaderText)}>${text}</span>${this.renderIcon(this.iconEnd)}${this.renderStatusIcon()}<calcite-icon class=${safeClassMap(CSS.chevronIcon)} .icon=${arrowIcon} scale=s></calcite-icon></button></div>`; return html`${headerNode}<section aria-labelledby=${IDS.toggle} class=${safeClassMap(CSS.content)} .hidden=${!expanded} id=${IDS.content}><slot></slot></section>`; } } customElement("calcite-block-section", BlockSection); export { BlockSection };