UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

152 lines (151 loc) • 11 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 { keyed } from "lit-html/directives/keyed.js"; import { html, nothing } from "lit"; import { LitElement, createEvent, safeClassMap, safeStyleMap } from "@arcgis/lumina"; import { g as guid } from "../../chunks/guid.js"; import { u as updateHostInteraction, I as InteractiveContainer } from "../../chunks/interactive.js"; import { g as getAncestors, i as isSingleLike, a as getDepth } from "../../chunks/utils3.js"; import { w as warnIfMissingRequiredProp, g as getIconScale } from "../../chunks/component.js"; import { r as slotChangeHasContent } from "../../chunks/dom.js"; import { h as highlightText } from "../../chunks/text.js"; import { css } from "@lit/reactive-element/css-tag.js"; const CSS = { active: "label--active", centerContent: "center-content", container: "container", iconCustom: "icon--custom", description: "description", icon: "icon", label: "label", scale: (scale) => `scale--${scale}`, shortText: "short-text", single: "label--single", textContainer: "text-container", heading: "heading" }; const ICONS = { checked: "check-square-f", circle: "circle", indeterminate: "minus-square-f", selectedSingle: "circle-inset-large", unchecked: "square" }; const SLOTS = { contentEnd: "content-end", contentStart: "content-start" }; 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([hidden]){display:none}[hidden]{display:none}.scale--s{font-size:var(--calcite-font-size--2);line-height:1rem;--calcite-internal-combobox-item-spacing-unit-s: .25rem;--calcite-internal-combobox-item-spacing-unit-l: .5rem;--calcite-combobox-item-selector-icon-size: 1rem;--calcite-internal-combobox-item-description-font-size: var(--calcite-font-size-xs)}.scale--m{font-size:var(--calcite-font-size--1);line-height:1rem;--calcite-internal-combobox-item-spacing-unit-s: .375rem;--calcite-internal-combobox-item-spacing-unit-l: .75rem;--calcite-combobox-item-selector-icon-size: 1rem;--calcite-internal-combobox-item-description-font-size: var(--calcite-font-size-sm)}.scale--l{font-size:var(--calcite-font-size-0);line-height:1.25rem;--calcite-internal-combobox-item-spacing-unit-s: .625rem;--calcite-internal-combobox-item-spacing-unit-l: 1rem;--calcite-combobox-item-selector-icon-size: 1.5rem;--calcite-internal-combobox-item-description-font-size: var(--calcite-font-size)}.container{--calcite-combobox-item-indent-value: calc( var(--calcite-internal-combobox-item-spacing-unit-l) * var(--calcite-combobox-item-spacing-indent-multiplier) )}:host(:focus){--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}:host([disabled]) ::slotted([calcite-hydrated][disabled]),:host([disabled]) [calcite-hydrated][disabled]{opacity:1}.interaction-container{display:contents}:host,ul{margin:0;display:flex;flex-direction:column;padding:0}:host(:focus),ul:focus{outline:2px solid transparent;outline-offset:2px}.label{position:relative;box-sizing:border-box;display:flex;inline-size:100%;min-inline-size:100%;cursor:pointer;align-items:center;text-decoration-line:none;transition-timing-function:cubic-bezier(.4,0,.2,1);outline-color:transparent;word-wrap:break-word;word-break:break-word;justify-content:space-around;gap:var(--calcite-internal-combobox-item-spacing-unit-l);padding-block:var(--calcite-internal-combobox-item-spacing-unit-s);padding-inline-end:var(--calcite-internal-combobox-item-spacing-unit-l);padding-inline-start:var(--calcite-combobox-item-indent-value);color:var(--calcite-combobox-text-color, var(--calcite-color-text-3));transition-duration:var(--calcite-animation-timing)}:host([disabled]) .label{cursor:default}.label--active{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))))}.label:hover{background-color:var(--calcite-combobox-item-background-color-hover, var(--calcite-color-foreground-2));color:var(--calcite-combobox-text-color-hover, var(--calcite-color-text-1))}.label:active{background-color:var(--calcite-combobox-item-background-color-active, var(--calcite-color-foreground-3))}:host([selected]) .label,.label:active{color:var(--calcite-combobox-text-color-hover, var(--calcite-color-text-1))}:host([selected]) .label .description,:host([selected]) .label .short-text,.label:active .description,.label:active .short-text{color:var(--calcite-combobox-description-text-color-press, var(--calcite-color-text-2))}.icon{display:inline-flex;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1);color:var(--calcite-color-border-input)}:host([selected]) .icon,:host([indeterminate]) .icon{color:var(--calcite-combobox-selected-icon-color, var(--calcite-color-brand))}.icon--custom{margin-block-start:-1px}.center-content{display:flex;flex-direction:column;flex-grow:1;padding-block:0}.description{font-size:var(--calcite-internal-combobox-item-description-font-size)}.short-text{white-space:nowrap}.heading{color:var(--calcite-combobox-heading-text-color, var(--calcite-color-text-1))}.description,.short-text{color:var(--calcite-combobox-description-text-color, var(--calcite-color-text-3))}:host([selected]) .heading{font-weight:var(--calcite-font-weight-medium)}.heading,.description,.short-text{line-height:var(--calcite-font-line-height-relative-snug)}:host([item-hidden]){display:none}.text-match{background-color:transparent;color:inherit;font-weight:var(--calcite-font-weight-bold)}`; class ComboboxItem extends LitElement { constructor() { super(...arguments); this._selected = false; this.hasContent = false; this.active = false; this.disabled = false; this.guid = guid(); this.iconFlipRtl = false; this.scale = "m"; this.selectionMode = "multiple"; this.itemHidden = false; this.indeterminate = false; this.calciteComboboxItemChange = createEvent({ cancelable: false }); this.calciteInternalComboboxItemChange = createEvent({ cancelable: false }); } static { this.properties = { hasContent: [16, {}, { state: true }], active: [7, {}, { reflect: true, type: Boolean }], ancestors: [0, {}, { attribute: false }], description: 1, disabled: [7, {}, { reflect: true, type: Boolean }], filterDisabled: [7, {}, { reflect: true, type: Boolean }], filterTextMatchPattern: [2, {}, { reflect: true, attribute: false }], guid: [3, {}, { reflect: true }], heading: 1, icon: [3, {}, { reflect: true }], iconFlipRtl: [7, {}, { reflect: true, type: Boolean }], label: 1, metadata: [0, {}, { attribute: false }], scale: 1, selected: [7, {}, { reflect: true, type: Boolean }], selectionMode: [3, {}, { reflect: true }], shortHeading: 1, textLabel: [3, {}, { reflect: true }], value: 1, itemHidden: [7, {}, { reflect: true, type: Boolean }], indeterminate: [7, {}, { reflect: true, type: Boolean }] }; } static { this.styles = styles; } get selected() { return this._selected; } set selected(value) { const oldValue = this._selected; if (value !== oldValue) { this._selected = value; this.emitItemChange(); } } connectedCallback() { super.connectedCallback(); this.ancestors = getAncestors(this.el); } load() { warnIfMissingRequiredProp(this, "value", "textLabel"); } willUpdate(changes) { if (this.hasUpdated && (changes.has("disabled") || changes.has("heading") || changes.has("label") || changes.has("textLabel"))) { this.emitItemChange(); } } updated() { updateHostInteraction(this); } emitItemChange() { this.calciteInternalComboboxItemChange.emit(); } handleDefaultSlotChange(event) { this.hasContent = slotChangeHasContent(event); } toggleSelected() { const isSinglePersistSelect = this.selectionMode === "single-persist"; if (this.disabled || isSinglePersistSelect && this.selected) { return; } this.selected = !this.selected; this.calciteComboboxItemChange.emit(); } itemClickHandler() { this.toggleSelected(); } renderIcon(iconPath) { return this.icon ? keyed("icon", html`<calcite-icon class=${safeClassMap({ [CSS.iconCustom]: !!this.icon })} .flipRtl=${this.iconFlipRtl} .icon=${this.icon || iconPath} .scale=${getIconScale(this.scale)}></calcite-icon>`) : null; } renderSelectIndicator(icon) { return keyed("indicator", html`<calcite-icon class=${safeClassMap({ [CSS.icon]: true })} .flipRtl=${this.iconFlipRtl} .icon=${icon} .scale=${getIconScale(this.scale)}></calcite-icon>`); } renderChildren() { return keyed("default-slot-container", html`<ul .hidden=${!this.hasContent}><slot @slotchange=${this.handleDefaultSlotChange}></slot></ul>`); } render() { const { disabled, heading, label, textLabel, value, filterTextMatchPattern, description, shortHeading } = this; const isSingleSelect = isSingleLike(this.selectionMode); const icon = disabled || isSingleSelect ? void 0 : ICONS.checked; const selectionIcon = isSingleSelect ? this.selected ? ICONS.selectedSingle : ICONS.circle : this.indeterminate ? ICONS.indeterminate : this.selected ? ICONS.checked : ICONS.unchecked; const headingText = heading || textLabel; const itemLabel = label || value; const classes = { [CSS.label]: true, [CSS.active]: this.active, [CSS.single]: isSingleSelect }; const depth = getDepth(this.el); this.el.ariaHidden = "true"; this.el.ariaLabel = itemLabel; return InteractiveContainer({ disabled, children: html`<div class=${safeClassMap({ [CSS.container]: true, [CSS.scale(this.scale)]: true })} style=${safeStyleMap({ "--calcite-combobox-item-spacing-indent-multiplier": `${depth}` })}><li class=${safeClassMap(classes)} id=${this.guid ?? nothing} @click=${this.itemClickHandler}>${this.renderSelectIndicator(selectionIcon)}<slot name=${SLOTS.contentStart}></slot>${this.renderIcon(icon)}<div class=${safeClassMap(CSS.centerContent)}><div class=${safeClassMap(CSS.heading)}>${highlightText({ text: headingText, pattern: filterTextMatchPattern })}</div>${description ? html`<div class=${safeClassMap(CSS.description)}>${highlightText({ text: description, pattern: filterTextMatchPattern })}</div>` : null}</div>${shortHeading ? html`<div class=${safeClassMap(CSS.shortText)}>${highlightText({ text: shortHeading, pattern: filterTextMatchPattern })}</div>` : null}<slot name=${SLOTS.contentEnd}></slot></li>${this.renderChildren()}</div>` }); } } customElement("calcite-combobox-item", ComboboxItem); export { ComboboxItem };