@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
152 lines (151 loc) • 11 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 { 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
};