@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
155 lines (154 loc) • 6.22 kB
JavaScript
/*! 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";
import { createRef, ref } from "lit-html/directives/ref.js";
import { LitElement, createEvent } from "@arcgis/lumina";
import { d as focusElementInGroup, s as slotChangeGetAssignedElements } from "../../chunks/dom.js";
import { u as updateHostInteraction, I as InteractiveContainer } from "../../chunks/interactive.js";
import { c as componentFocusable } from "../../chunks/component.js";
import { css } from "@lit/reactive-element/css-tag.js";
const styles = css`:host([disabled]){cursor:default;-webkit-user-select:none;user-select:none;opacity:var(--calcite-opacity-disabled)}:host([disabled]) *,:host([disabled]) ::slotted(*){pointer-events:none}:host{display:flex}.container{display:flex;inline-size:100%;flex-wrap:wrap;gap:.5rem}::slotted(calcite-chip){flex:none}:host([scale=s]) .container{gap:.25rem}:host([scale=l]) .container{gap:.75rem}:host([disabled]) ::slotted([calcite-hydrated][disabled]),:host([disabled]) [calcite-hydrated][disabled]{opacity:1}.interaction-container{display:contents}:host([hidden]){display:none}[hidden]{display:none}`;
class ChipGroup extends LitElement {
constructor() {
super();
this.items = [];
this.slotRefEl = createRef();
this.disabled = false;
this.scale = "m";
this.selectedItems = [];
this.selectionMode = "none";
this.calciteChipGroupSelect = createEvent({ cancelable: false });
this.listen("calciteInternalChipKeyEvent", this.calciteInternalChipKeyEventListener);
this.listen("calciteChipClose", this.calciteChipCloseListener);
this.listen("calciteChipSelect", this.calciteChipSelectListener);
this.listen("calciteInternalChipSelect", this.calciteInternalChipSelectListener);
this.listen("calciteInternalSyncSelectedChips", this.calciteInternalSyncSelectedChips);
}
static {
this.properties = { disabled: [7, {}, { reflect: true, type: Boolean }], label: 1, scale: [3, {}, { reflect: true }], selectedItems: [0, {}, { attribute: false }], selectionMode: [3, {}, { reflect: true }] };
}
static {
this.styles = styles;
}
async setFocus() {
await componentFocusable(this);
if (!this.disabled) {
return (this.selectedItems[0] || this.items[0])?.setFocus();
}
}
willUpdate(changes) {
if (changes.has("selectionMode") && (this.hasUpdated || this.selectionMode !== "none")) {
this.updateItems();
}
}
updated() {
updateHostInteraction(this);
}
calciteInternalChipKeyEventListener(event) {
if (event.composedPath().includes(this.el)) {
const interactiveItems = this.items?.filter((el) => !el.disabled);
switch (event.detail.key) {
case "ArrowRight":
focusElementInGroup(interactiveItems, event.detail.target, "next");
break;
case "ArrowLeft":
focusElementInGroup(interactiveItems, event.detail.target, "previous");
break;
case "Home":
focusElementInGroup(interactiveItems, event.detail.target, "first");
break;
case "End":
focusElementInGroup(interactiveItems, event.detail.target, "last");
break;
}
}
event.stopPropagation();
}
calciteChipCloseListener(event) {
const item = event.target;
if (this.items?.includes(item)) {
if (this.items?.indexOf(item) > 0) {
focusElementInGroup(this.items, item, "previous");
} else if (this.items?.indexOf(item) === 0) {
focusElementInGroup(this.items, item, "next");
} else {
focusElementInGroup(this.items, item, "first");
}
}
this.items = this.items?.filter((el) => el !== item);
event.stopPropagation();
}
calciteChipSelectListener(event) {
if (event.composedPath().includes(this.el)) {
this.setSelectedItems(true, event.target);
}
event.stopPropagation();
}
calciteInternalChipSelectListener(event) {
if (event.composedPath().includes(this.el)) {
this.setSelectedItems(false, event.target);
}
event.stopPropagation();
}
calciteInternalSyncSelectedChips(event) {
if (event.composedPath().includes(this.el)) {
this.updateSelectedItems();
if (this.selectionMode === "single" && this.selectedItems.length > 1) {
this.setSelectedItems(false, event.target);
}
}
event.stopPropagation();
}
updateItems(event) {
const itemsFromSlot = this.slotRefEl.value?.assignedElements({ flatten: true }).filter((el) => el?.matches("calcite-chip"));
this.items = !event ? itemsFromSlot : slotChangeGetAssignedElements(event);
if (this.items?.length < 1) {
return;
}
this.items?.forEach((el) => {
el.interactive = true;
el.scale = this.scale;
el.selectionMode = this.selectionMode;
el.parentChipGroup = this.el;
});
this.setSelectedItems(false);
}
updateSelectedItems() {
this.selectedItems = this.items?.filter((el) => el.selected);
}
setSelectedItems(emit, elToMatch) {
if (elToMatch) {
this.items?.forEach((el) => {
const matchingEl = elToMatch === el;
switch (this.selectionMode) {
case "multiple":
if (matchingEl) {
el.selected = !el.selected;
}
break;
case "single":
el.selected = matchingEl ? !el.selected : false;
break;
case "single-persist":
el.selected = !!matchingEl;
break;
}
});
}
this.updateSelectedItems();
if (emit) {
this.calciteChipGroupSelect.emit();
}
}
render() {
const role = this.selectionMode === "none" || this.selectionMode === "multiple" ? "group" : "radiogroup";
const { disabled } = this;
return InteractiveContainer({ disabled, children: html`<div .ariaLabel=${this.label} class="container" .role=${role}><slot =${this.updateItems} ${ref(this.slotRefEl)}></slot></div>` });
}
}
customElement("calcite-chip-group", ChipGroup);
export {
ChipGroup
};