UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

153 lines (152 loc) • 14.2 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 CSS_UTILITY, c as customElement } from "../../chunks/runtime.js"; import { html } from "lit-html"; import { keyed } from "lit-html/directives/keyed.js"; import { ref } from "lit-html/directives/ref.js"; import { LitElement, createEvent, safeClassMap } from "@arcgis/lumina"; import { l as closestElementCrossShadowBoundary, a as slotChangeHasAssignedElement, g as getElementDir } from "../../chunks/dom.js"; import { c as componentFocusable, g as getIconScale } from "../../chunks/component.js"; import { css } from "@lit/reactive-element/css-tag.js"; const SLOTS = { actionsStart: "actions-start", actionsEnd: "actions-end" }; const CSS = { actionsEnd: "actions-end", actionsStart: "actions-start", content: "content", description: "description", expandIcon: "expand-icon", header: "header", headerContainer: "header-container", headerContent: "header-content", headerText: "header-text", heading: "heading", icon: "icon", iconEnd: "icon--end", iconStart: "icon--start" }; const IDS = { section: "section", sectionToggle: "section-toggle" }; const styles = css`.icon-position--end,.icon-position--start{--calcite-internal-accordion-item-icon-rotation: -90deg ;--calcite-internal-accordion-item-active-icon-rotation: 0deg;--calcite-internal-accordion-item-icon-rotation-rtl: 90deg;--calcite-internal-accordion-item-active-icon-rotation-rtl: 0deg}:host{position:relative;display:flex;flex-direction:column;text-decoration-line:none;color:var(--calcite-accordion-text-color, var(--calcite-accordion-item-text-color, var(--calcite-color-text-3)));background-color:var(--calcite-accordion-background-color, var(--calcite-accordion-item-background-color));border-width:0}:host .header{background-color:var(--calcite-accordion-item-header-background-color)}:host .header:hover{background-color:var(--calcite-internal-accordion-item-header-background-color-hover)}:host .header:active{background-color:var(--calcite-internal-accordion-item-header-background-color-press)}.header--solid{--calcite-internal-accordion-item-header-background-color-hover: var( --calcite-accordion-item-header-background-color-hover, var(--calcite-color-foreground-2) );--calcite-internal-accordion-item-header-background-color-press: var( --calcite-accordion-item-header-background-color-press, var(--calcite-color-foreground-3) )}.header--transparent{--calcite-internal-accordion-item-header-background-color-hover: var( --calcite-accordion-item-header-background-color-hover, var(--calcite-color-transparent-hover) );--calcite-internal-accordion-item-header-background-color-press: var( --calcite-accordion-item-header-background-color-press, var(--calcite-color-transparent-press) )}.icon-position--start{--calcite-internal-accordion-item-flex-direction: row-reverse;--calcite-internal-accordion-item-icon-spacing-start: 0;--calcite-internal-accordion-item-icon-spacing-end: var(--calcite-internal-accordion-icon-margin)}.icon-position--end{--calcite-internal-accordion-item-flex-direction: row;--calcite-internal-accordion-item-icon-spacing-start: var(--calcite-internal-accordion-icon-margin);--calcite-internal-accordion-item-icon-spacing-end: 0}.icon-position--end:not(.icon-type--plus-minus){--calcite-internal-accordion-item-icon-rotation: 0deg;--calcite-internal-accordion-item-active-icon-rotation: 180deg;--calcite-internal-accordion-item-icon-rotation-rtl: 0deg;--calcite-internal-accordion-item-active-icon-rotation-rtl: -180deg }.content,.header{border-block-end-width:var(--calcite-border-width-sm);border-block-end-style:solid;border-color:var(--calcite-accordion-border-color, var(--calcite-accordion-item-border-color, var(--calcite-color-border-2)))}.header-content{padding:var(--calcite-internal-accordion-item-padding, var(--calcite-internal-accordion-item-spacing-unit, .5rem .75rem))}.content{padding:var(--calcite-accordion-item-content-space, var(--calcite-internal-accordion-item-padding, var(--calcite-internal-accordion-item-spacing-unit, .5rem .75rem)))}.header{display:flex;align-items:stretch}.header-content,.header-container,.header .actions-start,.header .actions-end{display:flex;align-items:center;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);word-wrap:break-word;word-break:break-word}.header-content{flex-grow:1;cursor:pointer;outline-color:transparent;flex-direction:var(--calcite-internal-accordion-item-flex-direction);color:var(--calcite-accordion-item-heading-text-color, var(--calcite-accordion-text-color, inherit))}.header-content: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))))}.header-content:focus,.header-content:hover,.header-content:active{color:var(--calcite-accordion-item-heading-text-color, var(--calcite-accordion-text-color-hover))}.header-content:focus .heading,.header-content:hover .heading,.header-content:active .heading{color:var(--calcite-accordion-item-heading-text-color, var(--calcite-accordion-text-color-press))}.header-container{inline-size:100%}.header-text{margin-block:0px;flex-grow:1;flex-direction:column;padding-block:0px;text-align:initial;margin-inline-end:auto}.heading,.description{display:flex;inline-size:100%}.heading{font-weight:var(--calcite-font-weight-medium)}.actions-start ::slotted(calcite-action),.actions-end ::slotted(calcite-action){align-self:stretch}.icon{display:flex;align-items:center;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);margin-inline-end:var(--calcite-internal-accordion-item-icon-spacing-start);margin-inline-start:var(--calcite-internal-accordion-item-icon-spacing-end)}.icon--start{color:var(--calcite-accordion-item-icon-color-start, var(--calcite-accordion-item-start-icon-color, var(--calcite-accordion-item-icon-color, currentColor)));margin-inline-end:var(--calcite-internal-accordion-icon-margin)}.icon--end{color:var(--calcite-accordion-item-icon-color-end, var(--calcite-accordion-item-end-icon-color, var(--calcite-accordion-item-icon-color, currentColor)));margin-inline-end:var(--calcite-internal-accordion-icon-margin);margin-inline-start:var(--calcite-internal-accordion-icon-margin)}.expand-icon{color:var(--calcite-accordion-item-expand-icon-color, var(--calcite-accordion-text-color, var(--calcite-accordion-item-text-color, var(--calcite-color-text-3))));margin-inline-start:var(--calcite-internal-accordion-item-icon-spacing-start);margin-inline-end:var(--calcite-internal-accordion-item-icon-spacing-end);transform:rotate(var(--calcite-internal-accordion-item-icon-rotation))}.calcite--rtl .expand-icon{transform:rotate(var(--calcite-internal-accordion-item-icon-rotation-rtl))}.description{margin-block-start:.25rem}.content{display:none;text-align:initial}:host(:not([expanded])) .heading{color:var(--calcite-accordion-item-heading-text-color, var(--calcite-accordion-text-color-hover, var(--calcite-accordion-item-text-color-hover, var(--calcite-color-text-2))))}:host([expanded]){color:var(--calcite-accordion-text-color-press, var(--calcite-accordion-text-color, var(--calcite-accordion-item-text-color, var(--calcite-color-text-1))))}:host([expanded]) .header{border-block-end-color:transparent}:host([expanded]) .expand-icon{color:var(--calcite-accordion-item-expand-icon-color, var(--calcite-accordion-text-color-hover, var(--calcite-accordion-text-color, var(--calcite-accordion-item-text-color, var(--calcite-accordion-item-text-color-hover, var(--calcite-color-text-2))))));transform:rotate(var(--calcite-internal-accordion-item-active-icon-rotation))}:host([expanded]) .calcite--rtl .expand-icon{transform:rotate(var(--calcite-internal-accordion-item-active-icon-rotation-rtl))}:host([expanded]) .description{color:var(--calcite-accordion-text-color-hover, var(--calcite-accordion-text-color, var(--calcite-accordion-item-text-color, var(--calcite-accordion-item-text-color-hover, var(--calcite-color-text-2)))))}:host([expanded]) .content{display:block}@media (forced-colors: active){:host([expanded]) .header{border-block-end:none}:host([expanded]) .heading{font-weight:bolder}.header-content:hover .heading,.header-content:focus .heading{text-decoration:underline}}:host([hidden]){display:none}[hidden]{display:none}`; class AccordionItem extends LitElement { constructor() { super(); this.hasActionsEnd = false; this.hasActionsStart = false; this.expanded = false; this.calciteInternalAccordionItemClose = createEvent({ cancelable: false }); this.calciteInternalAccordionItemSelect = createEvent({ cancelable: false }); this.listen("keydown", this.keyDownHandler); this.listenOn(document.body, "calciteInternalAccordionChange", this.updateActiveItemOnChange); this.listenOn(document, "calciteInternalAccordionItemsSync", this.accordionItemSyncHandler); } static { this.properties = { hasActionsEnd: [16, {}, { state: true }], hasActionsStart: [16, {}, { state: true }], accordionParent: [0, {}, { attribute: false }], description: 1, expanded: [7, {}, { reflect: true, type: Boolean }], heading: 1, iconEnd: [3, {}, { reflect: true }], iconFlipRtl: [3, {}, { reflect: true }], appearance: 1, iconPosition: 1, iconStart: [3, {}, { reflect: true }], iconType: 1, scale: 1 }; } static { this.styles = styles; } async setFocus() { await componentFocusable(this); this.headerEl.focus(); } keyDownHandler(event) { if (event.target === this.el) { switch (event.key) { case " ": case "Enter": this.emitRequestedItem(); event.preventDefault(); break; } } } updateActiveItemOnChange(event) { const [accordion] = event.composedPath(); const parent = closestElementCrossShadowBoundary(this.el, "calcite-accordion"); if (accordion !== parent) { return; } this.determineActiveItem(parent.selectionMode, event.detail.requestedAccordionItem); event.stopPropagation(); } accordionItemSyncHandler(event) { const [accordion] = event.composedPath(); const accordionItem = this.el; const willBeSyncedByDirectParent = accordionItem.parentElement === accordion; if (willBeSyncedByDirectParent) { return; } const closestAccordionParent = closestElementCrossShadowBoundary(accordionItem, "calcite-accordion"); if (accordion !== closestAccordionParent) { return; } this.appearance = closestAccordionParent.appearance; this.iconPosition = closestAccordionParent.iconPosition; this.iconType = closestAccordionParent.iconType; this.scale = closestAccordionParent.scale; event.stopPropagation(); } handleActionsStartSlotChange(event) { this.hasActionsStart = slotChangeHasAssignedElement(event); } handleActionsEndSlotChange(event) { this.hasActionsEnd = slotChangeHasAssignedElement(event); } storeHeaderEl(el) { this.headerEl = el; } itemHeaderClickHandler() { this.emitRequestedItem(); } determineActiveItem(selectionMode, requestedItem) { switch (selectionMode) { case "multiple": if (this.el === requestedItem) { this.expanded = !this.expanded; } break; case "single": this.expanded = this.el === requestedItem ? !this.expanded : false; break; case "single-persist": this.expanded = this.el === requestedItem; break; } } emitRequestedItem() { this.calciteInternalAccordionItemSelect.emit({ requestedAccordionItem: this.el }); } renderActionsStart() { return html`<div class=${safeClassMap(CSS.actionsStart)} .hidden=${!this.hasActionsStart}><slot name=${SLOTS.actionsStart} @slotchange=${this.handleActionsStartSlotChange}></slot></div>`; } renderActionsEnd() { return html`<div class=${safeClassMap(CSS.actionsEnd)} .hidden=${!this.hasActionsEnd}><slot name=${SLOTS.actionsEnd} @slotchange=${this.handleActionsEndSlotChange}></slot></div>`; } render() { const { iconFlipRtl } = this; const dir = getElementDir(this.el); const iconStartEl = this.iconStart ? keyed("icon-start", html`<calcite-icon class=${safeClassMap({ [CSS.icon]: true, [CSS.iconStart]: true })} .flipRtl=${iconFlipRtl === "both" || iconFlipRtl === "start"} .icon=${this.iconStart} .scale=${getIconScale(this.scale)}></calcite-icon>`) : null; const iconEndEl = this.iconEnd ? keyed("icon-end", html`<calcite-icon class=${safeClassMap({ [CSS.iconEnd]: true, [CSS.icon]: true })} .flipRtl=${iconFlipRtl === "both" || iconFlipRtl === "end"} .icon=${this.iconEnd} .scale=${getIconScale(this.scale)}></calcite-icon>`) : null; const { description } = this; return html`<div class=${safeClassMap({ [`icon-position--${this.iconPosition}`]: true, [`icon-type--${this.iconType}`]: true })}><div class=${safeClassMap({ [CSS.header]: true, [CSS_UTILITY.rtl]: dir === "rtl", [`header--${this.appearance}`]: true })}>${this.renderActionsStart()}<div aria-controls=${IDS.section} .ariaExpanded=${this.expanded} class=${safeClassMap(CSS.headerContent)} id=${IDS.sectionToggle} @click=${this.itemHeaderClickHandler} role=button tabindex=0 ${ref(this.storeHeaderEl)}><div class=${safeClassMap(CSS.headerContainer)}>${iconStartEl}<div class=${safeClassMap(CSS.headerText)}><span class=${safeClassMap(CSS.heading)}>${this.heading}</span>${description ? html`<span class=${safeClassMap(CSS.description)}>${description}</span>` : null}</div>${iconEndEl}</div><calcite-icon class=${safeClassMap(CSS.expandIcon)} .icon=${this.iconType === "chevron" ? "chevronDown" : this.iconType === "caret" ? "caretDown" : this.expanded ? "minus" : "plus"} .scale=${getIconScale(this.scale)}></calcite-icon></div>${this.renderActionsEnd()}</div><section aria-labelledby=${IDS.sectionToggle} class=${safeClassMap(CSS.content)} id=${IDS.section}><slot></slot></section></div>`; } } customElement("calcite-accordion-item", AccordionItem); export { AccordionItem };