UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

274 lines (273 loc) • 13.7 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 { ref } from "lit-html/directives/ref.js"; import { html as html$1, nothing } from "lit"; import { safeClassMap, LitElement, createEvent } from "@arcgis/lumina"; import { d as focusElementInGroup, s as slotChangeGetAssignedElements } from "../../chunks/dom.js"; import { c as createObserver } from "../../chunks/observers.js"; import { g as guid } from "../../chunks/guid.js"; import { u as useT9n } from "../../chunks/useT9n.js"; import { i as isHidden } from "../../chunks/component.js"; import { svg, html } from "lit-html"; import { css } from "@lit/reactive-element/css-tag.js"; const CSS$1 = { actionIcon: "action-icon", actionContainer: "action-container", stepBarContainer: "step-bar-container", singleView: "single-view" }; const CSS = { stepBar: "step-bar", stepBarActive: "step-bar--active", stepBarComplete: "step-bar--complete", stepBarDisabled: "step-bar--disabled", stepBarError: "step-bar--error", stepBarInActive: "step-bar--inactive" }; const StepBar = ({ disabled, active, complete, error }) => html`<svg class=${safeClassMap({ [CSS.stepBar]: true })}>${svg`<rect class=${safeClassMap({ [CSS.stepBarActive]: active, [CSS.stepBarComplete]: complete, [CSS.stepBarDisabled]: disabled, [CSS.stepBarError]: error, [CSS.stepBarInActive]: true })} width=100% x=0 y=0 />`}</svg>`; const styles = css`:host([scale=s]){--calcite-internal-stepper-item-spacing-unit-s: .25rem;--calcite-internal-stepper-action-block-size: 2.75rem;--calcite-internal-stepper-action-inline-size: 2rem;--calcite-internal-step-bar-gap: .25rem}:host([scale=m]){--calcite-internal-stepper-item-spacing-unit-s: .5rem;--calcite-internal-stepper-action-block-size: 3.25rem;--calcite-internal-stepper-action-inline-size: 2.5rem}:host([scale=l]){--calcite-internal-stepper-item-spacing-unit-s: .75rem;--calcite-internal-stepper-action-block-size: 4rem;--calcite-internal-stepper-action-inline-size: 3rem;--calcite-internal-step-bar-gap: .75rem}:host{display:flex}.container{position:relative;display:flex;inline-size:100%;min-inline-size:fit-content;flex-direction:row;flex-wrap:wrap;align-items:stretch;justify-content:space-between}:host([layout=vertical]) .container{flex:1 1 auto;flex-direction:column}:host([layout=horizontal]) .container,:host([layout=horizontal-single]) .container{display:grid;grid-template-areas:"items" "content";gap:.5rem var(--calcite-stepper-bar-gap, var(--calcite-internal-stepper-item-spacing-unit-s))}:host([layout=horizontal][scale=s]) .container,:host([layout=horizontal-single][scale=s]) .container{gap:.25rem var(--calcite-stepper-bar-gap, var(--calcite-internal-stepper-item-spacing-unit-s))}:host([layout=horizontal][scale=l]) .container,:host([layout=horizontal-single][scale=l]) .container{gap:.75rem var(--calcite-stepper-bar-gap, var(--calcite-internal-stepper-item-spacing-unit-s))}:host([layout=horizontal]) .container.single-view{display:flex;grid-template-columns:none}.action-icon{position:relative;display:flex;flex-grow:0;block-size:var(--calcite-internal-stepper-action-block-size);inline-size:var(--calcite-internal-stepper-action-inline-size)}.action-container{position:absolute;display:flex;justify-content:space-between;padding-block:.25rem;inline-size:100%}.step-bar{display:flex;block-size:100%;inline-size:100%}.step-bar-container{position:absolute;display:flex;align-items:flex-start;justify-content:space-between;block-size:.125rem;inline-size:100%;gap:var(--calcite-stepper-bar-gap, var(--calcite-internal-step-bar-gap, .5rem))}.step-bar--inactive{fill:var(--calcite-stepper-bar-inactive-fill-color, var(--calcite-color-border-3, #dfdfdf));fill-opacity:1;block-size:100%}.step-bar--active{fill:var(--calcite-stepper-bar-active-fill-color, var(--calcite-color-brand))}.step-bar--complete{fill:var(--calcite-stepper-bar-complete-fill-color, var(--calcite-color-brand));fill-opacity:.5}.step-bar--error{fill:var(--calcite-stepper-bar-error-fill-color, var(--calcite-color-status-danger))}.step-bar--disabled{opacity:.5}:host([hidden]){display:none}[hidden]{display:none}`; class Stepper extends LitElement { constructor() { super(); this.enabledItems = []; this.guid = `calcite-stepper-action-${guid()}`; this.itemMap = /* @__PURE__ */ new Map(); this.items = []; this.multipleViewMode = false; this.mutationObserver = createObserver("mutation", () => this.updateItems()); this.messages = useT9n(); this.icon = false; this.layout = "horizontal"; this.numbered = false; this.scale = "m"; this.selectedItem = null; this.calciteInternalStepperItemChange = createEvent({ cancelable: false }); this.calciteStepperChange = createEvent({ cancelable: false }); this.calciteStepperItemChange = createEvent({ cancelable: false }); this.listen("calciteInternalStepperItemKeyEvent", this.calciteInternalStepperItemKeyEvent); this.listen("calciteInternalStepperItemRegister", this.registerItem); this.listen("calciteInternalStepperItemSelect", this.updateItem); this.listen("calciteStepperItemSelect", this.handleItemSelect); } static { this.properties = { currentActivePosition: [16, {}, { state: true }], icon: [7, {}, { reflect: true, type: Boolean }], layout: [3, {}, { reflect: true }], messageOverrides: [0, {}, { attribute: false }], numbered: [7, {}, { reflect: true, type: Boolean }], numberingSystem: [3, {}, { reflect: true }], scale: [3, {}, { reflect: true }], selectedItem: [0, {}, { attribute: false }] }; } static { this.styles = styles; } async endStep() { const enabledStepIndex = this.getEnabledStepIndex(this.items.length - 1, "previous"); if (typeof enabledStepIndex !== "number") { return; } this.updateStep(enabledStepIndex); } async goToStep(step) { const position = step - 1; if (this.currentActivePosition !== position) { this.updateStep(position); } } async nextStep() { const enabledStepIndex = this.getEnabledStepIndex(this.currentActivePosition + 1, "next"); if (typeof enabledStepIndex !== "number") { return; } this.updateStep(enabledStepIndex); } async prevStep() { const enabledStepIndex = this.getEnabledStepIndex(this.currentActivePosition - 1, "previous"); if (typeof enabledStepIndex !== "number") { return; } this.updateStep(enabledStepIndex); } async startStep() { const enabledStepIndex = this.getEnabledStepIndex(0, "next"); if (typeof enabledStepIndex !== "number") { return; } this.updateStep(enabledStepIndex); } connectedCallback() { super.connectedCallback(); this.mutationObserver?.observe(this.el, { childList: true }); this.updateItems(); } willUpdate(changes) { if (changes.has("icon") && (this.hasUpdated || this.icon !== false) || changes.has("layout") && (this.hasUpdated || this.layout !== "horizontal") || changes.has("numbered") && (this.hasUpdated || this.numbered !== false) || changes.has("scale") && (this.hasUpdated || this.scale !== "m")) { this.updateItems(); this.determineActiveStepper(); } if (changes.has("numberingSystem")) { this.setStepperItemNumberingSystem(); } if (changes.has("currentActivePosition")) { requestAnimationFrame(() => { this.determineActiveStepper(); }); } } loaded() { if (typeof this.currentActivePosition !== "number") { const enabledStepIndex = this.getFirstEnabledStepperPosition(); if (enabledStepIndex === 0) { this.currentActivePosition = enabledStepIndex; } this.calciteInternalStepperItemChange.emit({ position: enabledStepIndex }); } } disconnectedCallback() { super.disconnectedCallback(); this.mutationObserver?.disconnect(); } calciteInternalStepperItemKeyEvent(event) { const item = event.detail.item; const itemToFocus = event.target; switch (item.key) { case "ArrowDown": case "ArrowRight": focusElementInGroup(this.enabledItems, itemToFocus, "next"); break; case "ArrowUp": case "ArrowLeft": focusElementInGroup(this.enabledItems, itemToFocus, "previous"); break; case "Home": focusElementInGroup(this.enabledItems, itemToFocus, "first"); break; case "End": focusElementInGroup(this.enabledItems, itemToFocus, "last"); break; } event.stopPropagation(); } registerItem(event) { const item = event.target; const { content, position } = event.detail; this.itemMap.set(item, { position, content }); this.enabledItems = this.filterItems(); event.stopPropagation(); } updateItem(event) { const { position } = event.detail; if (typeof position === "number") { this.currentActivePosition = position; this.selectedItem = event.target; } this.calciteInternalStepperItemChange.emit({ position }); } handleItemSelect() { this.emitItemSelect(); } emitItemSelect() { this.calciteStepperItemChange.emit(); this.calciteStepperChange.emit(); } updateItems() { this.el.querySelectorAll("calcite-stepper-item").forEach((item) => { item.icon = this.icon; item.numbered = this.numbered; item.layout = this.layout; item.scale = this.scale; }); } determineActiveStepper() { const { items } = this; if (items.length < 2) { return; } const { currentActivePosition, layout } = this; this.multipleViewMode = layout !== "horizontal-single"; items.forEach((item, index) => { item.itemHidden = layout === "horizontal-single" && index !== (currentActivePosition || 0); }); } getEnabledStepIndex(startIndex, direction = "next") { const { items, currentActivePosition } = this; let newIndex = startIndex; while (items[newIndex]?.disabled && this.layout !== "horizontal-single") { newIndex = newIndex + (direction === "previous" ? -1 : 1); } return newIndex !== currentActivePosition && newIndex < items.length && newIndex >= 0 ? newIndex : null; } updateStep(position) { this.currentActivePosition = position; this.calciteInternalStepperItemChange.emit({ position }); } filterItems() { return this.items.filter((item) => !item.disabled && !isHidden(item)); } setStepperItemNumberingSystem() { this.items.forEach((item) => { item.numberingSystem = this.numberingSystem; }); } handleActionClick(event) { const currentActivePosition = this.currentActivePosition; const target = event.target; if (target.getAttribute("data-position") === "start") { this.prevStep(); } else { this.nextStep(); } if (typeof this.currentActivePosition === "number" && currentActivePosition !== this.currentActivePosition && !this.items[this.currentActivePosition].disabled) { this.emitItemSelect(); } } getFirstEnabledStepperPosition() { const enabledStepIndex = this.items.findIndex((item) => !item.disabled); if (enabledStepIndex > -1) { return enabledStepIndex; } return 0; } setContainerEl(el) { this.containerEl = el; } handleDefaultSlotChange(event) { const items = slotChangeGetAssignedElements(event).filter((el) => el?.tagName === "CALCITE-STEPPER-ITEM" && !isHidden(el)); this.items = items; const spacing = Array(items.length).fill("1fr").join(" "); this.containerEl.style.gridTemplateAreas = spacing; this.containerEl.style.gridTemplateColumns = spacing; this.setStepperItemNumberingSystem(); } render() { this.el.ariaLabel = this.messages.label; this.el.role = "region"; return html$1`<div class=${safeClassMap({ container: true, [CSS$1.singleView]: this.layout === "horizontal-single" })} ${ref(this.setContainerEl)}>${this.layout === "horizontal-single" && html$1`<div class=${safeClassMap({ [CSS$1.stepBarContainer]: true })}>${this.items.map((item, index) => StepBar({ active: index === this.currentActivePosition, complete: item.complete && index !== this.currentActivePosition && !item.error, disabled: item.disabled && index !== this.currentActivePosition, error: item.error && index !== this.currentActivePosition }))}</div>` || ""}${this.layout === "horizontal-single" && html$1`<div class=${safeClassMap({ [CSS$1.actionContainer]: true })}>${this.renderAction("start")}${this.renderAction("end")}</div>` || ""}<slot @slotchange=${this.handleDefaultSlotChange}></slot></div>`; } renderAction(position) { const isPositionStart = position === "start"; const path = isPositionStart ? "chevron-left" : "chevron-right"; const { currentActivePosition, multipleViewMode, layout } = this; const totalItems = this.items.length; const id = `${this.guid}-${isPositionStart ? "start" : "end"}`; return layout === "horizontal-single" && !multipleViewMode ? html$1`<calcite-action alignment=center appearance=transparent class=${safeClassMap({ [CSS$1.actionIcon]: true })} compact data-position=${position ?? nothing} .disabled=${currentActivePosition === 0 && isPositionStart || currentActivePosition === totalItems - 1 && !isPositionStart} .icon=${path} icon-flip-rtl id=${id ?? nothing} @click=${this.handleActionClick} .scale=${this.scale} .text=${isPositionStart ? this.messages.previousStep : this.messages.nextStep}></calcite-action>` : null; } } customElement("calcite-stepper", Stepper); export { Stepper };