@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
210 lines (209 loc) • 14.6 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 { LitElement, createEvent, safeClassMap } from "@arcgis/lumina";
import { g as guid } from "../../chunks/guid.js";
import { u as updateHostInteraction, I as InteractiveContainer } from "../../chunks/interactive.js";
import { c as componentFocusable } from "../../chunks/component.js";
import { l as logger } from "../../chunks/logger.js";
import { css } from "@lit/reactive-element/css-tag.js";
const CSS = {
description: "description",
descriptionOnly: "description-only",
heading: "heading",
headingOnly: "heading-only",
icon: "icon",
iconOnly: "icon-only",
inputAlignmentEnd: "input-alignment-end",
inputAlignmentStart: "input-alignment-start",
inputEnabled: "input-enabled",
largeVisual: "large-visual",
tile: "tile",
tileContentContainer: "tile-content-container",
tileContent: "tile-content",
tileDescription: "tile-description",
tileHeading: "tile-heading",
tileLargeVisual: "tile--large-visual",
widthAuto: "width-auto",
widthFull: "width-full"
};
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:block}:host .container{background-color:var(--calcite-color-foreground-1);box-shadow:0 0 0 1px var(--calcite-color-border-2);box-sizing:border-box;cursor:pointer;display:inline-block;block-size:100%;max-inline-size:300px;padding:.75rem;position:relative;vertical-align:top;transition-property:background-color,block-size,border-color,box-shadow,color,inset-block-end,inset-block-start,inset-inline-end,inset-inline-start,inset-size,opacity,outline-color,transform;transition-duration:var(--calcite-animation-timing);transition-timing-function:ease-in-out}:host .container.checked{z-index:var(--calcite-z-index);box-shadow:0 0 0 1px var(--calcite-color-brand)}:host .container.heading-only{align-items:center}:host .container:not(.input-enabled) ::slotted(calcite-checkbox),:host .container:not(.input-enabled) ::slotted(calcite-radio-button){position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}:host .container.focused{outline-color:transparent}:host .container.focused:not(.disabled):not(.input-enabled){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))));outline-offset:-4px;box-shadow:0 0 0 1px var(--calcite-color-brand),inset 0 0 0 2px var(--calcite-color-foreground-1)}:host .container.input-enabled.input-alignment-start.width-auto.heading-only,:host .container.input-enabled.input-alignment-start.width-auto.icon-only,:host .container.input-enabled.input-alignment-start.width-auto.description-only,:host .container.input-enabled.input-alignment-start.width-auto.heading.description,:host .container.input-enabled.input-alignment-start.width-auto.icon.description,:host .container.input-enabled.input-alignment-start.width-auto.heading.icon.description{display:inline-grid;grid-template-columns:max-content 1fr}:host .container.input-enabled.input-alignment-start.heading-only,:host .container.input-enabled.input-alignment-start.icon-only,:host .container.input-enabled.input-alignment-start.description-only,:host .container.input-enabled.input-alignment-start.heading.description,:host .container.input-enabled.input-alignment-start.icon.description,:host .container.input-enabled.input-alignment-start.heading.icon.description{gap:.75rem}:host .container.input-enabled.input-alignment-start .tile{order:1}:host .container.input-enabled.input-alignment-start.large-visual ::slotted(calcite-checkbox),:host .container.input-enabled.input-alignment-start.large-visual ::slotted(calcite-radio-button){position:absolute;inset-block-start:.75rem;inset-inline-start:.75rem}:host .container.input-enabled.input-alignment-end.width-auto.heading-only,:host .container.input-enabled.input-alignment-end.width-auto.icon-only{display:inline-grid;grid-gap:.75rem;grid-template-columns:max-content 1fr}:host .container.input-enabled.input-alignment-end.heading-only,:host .container.input-enabled.input-alignment-end.icon-only{gap:.75rem}:host .container.input-enabled.input-alignment-end.description-only ::slotted(calcite-checkbox),:host .container.input-enabled.input-alignment-end.description-only ::slotted(calcite-radio-button),:host .container.input-enabled.input-alignment-end.heading.description ::slotted(calcite-checkbox),:host .container.input-enabled.input-alignment-end.heading.description ::slotted(calcite-radio-button),:host .container.input-enabled.input-alignment-end.icon.description ::slotted(calcite-checkbox),:host .container.input-enabled.input-alignment-end.icon.description ::slotted(calcite-radio-button),:host .container.input-enabled.input-alignment-end.heading.icon.description ::slotted(calcite-checkbox),:host .container.input-enabled.input-alignment-end.heading.icon.description ::slotted(calcite-radio-button){position:absolute;inset-block-start:.75rem;inset-inline-end:.75rem}:host .container.input-enabled.input-alignment-end.large-visual ::slotted(calcite-checkbox),:host .container.input-enabled.input-alignment-end.large-visual ::slotted(calcite-radio-button){position:absolute;inset-block-start:.75rem;inset-inline-end:.75rem}:host .container.width-full{display:flex;max-inline-size:none}:host .container.width-full .tile{flex:1 1 auto}.tile{pointer-events:none;box-sizing:border-box;display:flex;-webkit-user-select:none;user-select:none;flex-direction:column;gap:.5rem;background-color:var(--calcite-color-foreground-1);color:var(--calcite-color-text-3);transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.tile-content-container{display:flex;inline-size:100%;align-items:stretch;padding:0;color:var(--calcite-color-text-2);outline-color:transparent}.tile-content{display:flex;flex:1 1 auto;flex-direction:column;gap:.5rem;inline-size:10%}.tile-heading{pointer-events:none;overflow-wrap:break-word;font-size:var(--calcite-font-size--1);line-height:1.375;font-weight:var(--calcite-font-weight-medium);color:var(--calcite-color-text-2);transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.tile-description{pointer-events:none;overflow-wrap:break-word;font-size:var(--calcite-font-size--2);line-height:1.375;color:var(--calcite-color-text-3);transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.tile--large-visual{display:grid;justify-content:center;text-align:center;min-block-size:12rem}.tile--large-visual .icon{align-self:flex-end}.tile--large-visual calcite-icon{block-size:64px;inline-size:64px}.tile--large-visual .tile-content-container{align-self:center}:host(:hover) .container:not(.input-enabled){box-shadow:0 0 0 1px var(--calcite-color-brand)}:host(:hover) .tile-heading,.checked .tile-heading{color:var(--calcite-color-text-1)}:host(:hover) .tile-description,.checked .tile-description{color:var(--calcite-color-text-2)}: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 TileSelect extends LitElement {
constructor() {
super();
this.guid = `calcite-tile-select-${guid()}`;
this.focused = false;
this.checked = false;
this.disabled = false;
this.iconFlipRtl = false;
this.inputAlignment = "start";
this.inputEnabled = false;
this.type = "radio";
this.width = "auto";
this.calciteTileSelectChange = createEvent({ cancelable: false });
this.listen("calciteCheckboxChange", this.checkboxChangeHandler);
this.listen("calciteInternalCheckboxFocus", this.checkboxFocusBlurHandler);
this.listen("calciteInternalCheckboxBlur", this.checkboxFocusBlurHandler);
this.listen("calciteRadioButtonChange", this.radioButtonChangeHandler);
this.listen("calciteInternalRadioButtonCheckedChange", this.radioButtonCheckedChangeHandler);
this.listen("calciteInternalRadioButtonFocus", this.radioButtonFocusBlurHandler);
this.listen("calciteInternalRadioButtonBlur", this.radioButtonFocusBlurHandler);
this.listen("click", this.clickHandler);
this.listen("pointerenter", this.pointerEnterHandler);
this.listen("pointerleave", this.pointerLeaveHandler);
}
static {
this.properties = { focused: [16, {}, { state: true }], checked: [7, {}, { reflect: true, type: Boolean }], description: [3, {}, { reflect: true }], disabled: [7, {}, { reflect: true, type: Boolean }], heading: [3, {}, { reflect: true }], icon: [3, {}, { reflect: true }], iconFlipRtl: [7, {}, { reflect: true, type: Boolean }], inputAlignment: [3, {}, { reflect: true }], inputEnabled: [7, {}, { reflect: true, type: Boolean }], name: [3, {}, { reflect: true }], type: [3, {}, { reflect: true }], value: 1, width: [3, {}, { reflect: true }] };
}
static {
this.styles = styles;
}
async setFocus() {
await componentFocusable(this);
return this.input?.setFocus();
}
connectedCallback() {
super.connectedCallback();
this.renderInput();
}
load() {
logger.deprecated("component", {
name: "tile-select",
removalVersion: 4,
suggested: ["tile", "tile-group"]
});
}
willUpdate(changes) {
if (changes.has("checked") && (this.hasUpdated || this.checked !== false)) {
this.input.checked = this.checked;
}
if (changes.has("name")) {
this.input.name = this.name;
}
}
updated() {
updateHostInteraction(this);
}
disconnectedCallback() {
super.disconnectedCallback();
this.input?.remove();
}
checkboxChangeHandler(event) {
const checkbox = event.target;
if (checkbox === this.input) {
this.checked = checkbox.checked;
}
event.stopPropagation();
this.calciteTileSelectChange.emit();
}
checkboxFocusBlurHandler(event) {
const checkbox = event.target;
if (checkbox === this.input) {
this.focused = event.detail;
}
event.stopPropagation();
}
radioButtonChangeHandler(event) {
const radioButton = event.target;
if (radioButton === this.input) {
this.checked = radioButton.checked;
}
event.stopPropagation();
this.calciteTileSelectChange.emit();
}
radioButtonCheckedChangeHandler(event) {
const radioButton = event.target;
if (radioButton === this.input) {
this.checked = radioButton.checked;
}
event.stopPropagation();
}
radioButtonFocusBlurHandler(event) {
const radioButton = event.target;
if (radioButton === this.input) {
this.focused = radioButton.focused;
}
event.stopPropagation();
}
clickHandler(event) {
if (this.disabled) {
return;
}
const target = event.target;
const targets = ["calcite-tile", "calcite-tile-select"];
if (targets.includes(target.localName)) {
this.input.click();
}
}
pointerEnterHandler() {
if (this.disabled) {
return;
}
const { localName } = this.input;
if (localName === "calcite-radio-button" || localName === "calcite-checkbox") {
this.input.hovered = true;
}
}
pointerLeaveHandler() {
if (this.disabled) {
return;
}
const { localName } = this.input;
if (localName === "calcite-radio-button" || localName === "calcite-checkbox") {
this.input.hovered = false;
}
}
renderInput() {
this.input = this.type === "radio" ? (
/* we need to call createElement(x) separately to ensure supporting components are properly bundled */
document.createElement(
// TODO: [MIGRATION] If this is dynamically creating a web component, please read the docs: https://qawebgis.esri.com/arcgis-components/?path=/docs/lumina-jsx--docs#rendering-jsx-outside-the-component
"calcite-radio-button"
)
) : document.createElement(
// TODO: [MIGRATION] If this is dynamically creating a web component, please read the docs: https://qawebgis.esri.com/arcgis-components/?path=/docs/lumina-jsx--docs#rendering-jsx-outside-the-component
"calcite-checkbox"
);
this.input.checked = this.checked;
this.input.disabled = this.disabled;
this.input.hidden = this.el.hidden;
this.input.id = this.guid;
this.input.label = this.heading || this.name || "";
if (this.name) {
this.input.name = this.name;
}
if (this.value) {
this.input.value = this.value != null ? this.value.toString() : "";
}
this.el.insertAdjacentElement("beforeend", this.input);
}
render() {
const { checked, description, disabled, focused, heading, icon, inputAlignment, inputEnabled, width, iconFlipRtl } = this;
const isLargeVisual = heading && icon && !description;
const renderIcon = Boolean(icon);
return InteractiveContainer({ disabled, children: html`<div class=${safeClassMap({
checked,
container: true,
[CSS.description]: Boolean(description),
[CSS.descriptionOnly]: Boolean(!heading && !icon && description),
disabled,
focused,
[CSS.heading]: Boolean(heading),
[CSS.headingOnly]: heading && !icon && !description,
[CSS.icon]: renderIcon,
[CSS.iconOnly]: !heading && icon && !description,
[CSS.inputAlignmentEnd]: inputAlignment === "end",
[CSS.inputAlignmentStart]: inputAlignment === "start",
[CSS.inputEnabled]: inputEnabled,
[CSS.largeVisual]: isLargeVisual,
[CSS.widthAuto]: width === "auto",
[CSS.widthFull]: width === "full"
})}><div class=${safeClassMap({ [CSS.tile]: true, [CSS.tileLargeVisual]: isLargeVisual })}>${icon && html`<div class=${safeClassMap({ [CSS.icon]: renderIcon })}><calcite-icon .flipRtl=${iconFlipRtl} .icon=${icon} scale=l></calcite-icon></div>` || ""}<div class=${safeClassMap(CSS.tileContentContainer)}><div class=${safeClassMap(CSS.tileContent)}>${heading && html`<div class=${safeClassMap(CSS.tileHeading)}>${heading}</div>` || ""}${description && html`<div class=${safeClassMap(CSS.tileDescription)}>${description}</div>` || ""}</div></div></div><slot></slot></div>` });
}
}
customElement("calcite-tile-select", TileSelect);
export {
TileSelect
};