UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

149 lines (148 loc) • 6.31 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 } from "lit"; import { LitElement, createEvent, safeClassMap } from "@arcgis/lumina"; import { u as updateHostInteraction, I as InteractiveContainer } from "../../chunks/interactive.js"; import { c as createObserver } from "../../chunks/observers.js"; import { d as focusElementInGroup } from "../../chunks/dom.js"; import { css } from "@lit/reactive-element/css-tag.js"; const CSS = { container: "container" }; 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{box-sizing:border-box;display:inline-block}:host ::slotted(calcite-tile){margin-block-end:var(--calcite-spacing-px);margin-inline-end:var(--calcite-spacing-px)}.container{display:grid;grid-auto-rows:minmax(auto,1fr)}:host([scale=s]) .container{grid-template-columns:repeat(auto-fit,minmax(100px,1fr))}:host([scale=m]) .container{grid-template-columns:repeat(auto-fit,minmax(140px,1fr))}:host([scale=l]) .container{grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}:host([layout=vertical]) .container{display:flex;flex-direction:column}: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 TileGroup extends LitElement { constructor() { super(); this.items = []; this.mutationObserver = createObserver("mutation", () => this.updateTiles()); this.alignment = "start"; this.disabled = false; this.layout = "horizontal"; this.scale = "m"; this.selectedItems = []; this.selectionAppearance = "icon"; this.selectionMode = "none"; this.calciteTileGroupSelect = createEvent({ cancelable: false }); this.listen("calciteInternalTileKeyEvent", this.calciteInternalTileKeyEventListener); this.listen("calciteTileSelect", this.calciteTileSelectHandler); } static { this.properties = { alignment: [3, {}, { reflect: true }], disabled: [7, {}, { reflect: true, type: Boolean }], label: 1, layout: [3, {}, { reflect: true }], scale: [3, {}, { reflect: true }], selectedItems: [0, {}, { attribute: false }], selectionAppearance: [3, {}, { reflect: true }], selectionMode: [3, {}, { reflect: true }] }; } static { this.styles = styles; } connectedCallback() { super.connectedCallback(); this.mutationObserver?.observe(this.el, { childList: true }); this.updateTiles(); } willUpdate(changes) { if (changes.has("scale") && (this.hasUpdated || this.scale !== "m") || changes.has("selectionMode") && (this.hasUpdated || this.selectionMode !== "none") || changes.has("selectionAppearance") && (this.hasUpdated || this.selectionAppearance !== "icon")) { this.updateTiles(); } } updated() { updateHostInteraction(this); } loaded() { this.updateSelectedItems(); } disconnectedCallback() { super.disconnectedCallback(); this.mutationObserver?.disconnect(); } getSlottedTiles() { return this.slotEl?.assignedElements({ flatten: true }).filter((el) => el?.matches("calcite-tile")); } selectItem(item) { if (!item) { return; } this.items?.forEach((el) => { const matchingEl = item === el; switch (this.selectionMode) { case "multiple": if (matchingEl) { el.selected = !el.selected; } break; case "single": el.selected = matchingEl && !el.selected; break; case "single-persist": el.selected = !!matchingEl; break; } }); this.updateSelectedItems(); this.calciteTileGroupSelect.emit(); } setSlotEl(el) { this.slotEl = el; } updateSelectedItems() { const selectedItems = this.items?.filter((el) => el.selected); if ((this.selectionMode === "single" || this.selectionMode === "single-persist") && selectedItems?.length > 1) { this.selectedItems = [selectedItems.pop()]; this.items?.forEach((el) => { if (this.selectedItems.indexOf(el) === -1) { el.selected = false; } }); } else { this.selectedItems = selectedItems ?? []; } } updateTiles() { this.items = this.getSlottedTiles(); this.items?.forEach((el) => { el.alignment = this.alignment; el.interactive = true; el.layout = this.layout; el.scale = this.scale; el.selectionAppearance = this.selectionAppearance; el.selectionMode = this.selectionMode; }); this.updateSelectedItems(); } calciteInternalTileKeyEventListener(event) { if (event.composedPath().includes(this.el)) { event.preventDefault(); event.stopPropagation(); const interactiveItems = this.items?.filter((el) => !el.disabled); switch (event.detail.key) { case "ArrowDown": case "ArrowRight": focusElementInGroup(interactiveItems, event.detail.target, "next"); break; case "ArrowUp": 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; } } } calciteTileSelectHandler(event) { if (event.composedPath().includes(this.el)) { this.selectItem(event.target); } } render() { const role = this.selectionMode === "none" || this.selectionMode === "multiple" ? "group" : "radiogroup"; return InteractiveContainer({ disabled: this.disabled, children: html`<div .ariaLabel=${this.label} class=${safeClassMap(CSS.container)} .role=${role}><slot @slotchange=${this.updateTiles} ${ref(this.setSlotEl)}></slot></div>` }); } } customElement("calcite-tile-group", TileGroup); export { TileGroup };