@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
130 lines (129 loc) • 6.45 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0/LICENSE.txt */
import { c as customElement } from "../../chunks/runtime.js";
import { css, nothing, html } from "lit";
import { createRef, ref } from "lit/directives/ref.js";
import { LitElement, createEvent, safeClassMap } from "@arcgis/lumina";
import { u as useT9n } from "../../chunks/useT9n.js";
import { l as logger } from "../../chunks/logger.js";
import { u as useSetFocus } from "../../chunks/useSetFocus.js";
import { u as useInteractive } from "../../chunks/useInteractive.js";
const CSS = {
handle: "handle",
handleSelected: "handle--selected"
};
const ICONS = {
drag: "drag"
};
const SUBSTITUTIONS = {
itemLabel: "{itemLabel}",
position: "{position}",
total: "{total}"
};
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}.handle{display:flex;align-items:center;justify-content:center;align-self:stretch;border-style:none;outline-color:transparent;color:var(--calcite-handle-icon-color, var(--calcite-color-border-input));background-color:var(--calcite-handle-background-color, transparent);padding-block:.75rem;padding-inline:.25rem;line-height:0}.handle calcite-icon{color:inherit}:host(:not([disabled])) .handle{cursor:move}:host(:not([disabled])) .handle:hover{color:var(--calcite-handle-icon-color-hover, var(--calcite-color-text-1));background-color:var(--calcite-handle-background-color-hover, var(--calcite-color-foreground-2))}:host(:not([disabled])) .handle:focus{outline:var(--calcite-border-width-md) solid var(--calcite-color-focus, var(--calcite-ui-focus-color, var(--calcite-color-brand)));outline-offset:calc(calc(-1 * var(--calcite-spacing-base)) * calc(1 - (2*clamp(0,var(--calcite-offset-invert-focus),1))));color:var(--calcite-handle-icon-color-hover, var(--calcite-color-text-1))}:host(:not([disabled])) .handle--selected{color:var(--calcite-handle-icon-color-selected, var(--calcite-color-text-1));background-color:var(--calcite-handle-background-color-selected, var(--calcite-color-foreground-3))}: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 Handle extends LitElement {
constructor() {
super(...arguments);
this.handleButtonRef = createRef();
this.messages = useT9n({ blocking: true });
this.focusSetter = useSetFocus()(this);
this.interactiveContainer = useInteractive(this);
this.blurUnselectDisabled = false;
this.disabled = false;
this.selected = false;
this.calciteHandleChange = createEvent({ cancelable: false });
this.calciteHandleNudge = createEvent({ cancelable: false });
this.calciteInternalAssistiveTextChange = createEvent({ cancelable: false });
}
static {
this.properties = { blurUnselectDisabled: [5, {}, { type: Boolean }], disabled: [7, {}, { reflect: true, type: Boolean }], dragHandle: [3, {}, { reflect: true }], label: 1, messageOverrides: [0, {}, { attribute: false }], selected: [7, {}, { reflect: true, type: Boolean }], setPosition: [9, {}, { type: Number }], setSize: [9, {}, { type: Number }] };
}
static {
this.styles = styles;
}
async setFocus(options) {
return this.focusSetter(() => this.handleButtonRef.value, options);
}
willUpdate(changes) {
if (changes.has("messages") || changes.has("label") || changes.has("selected") && (this.hasUpdated || this.selected !== false) || changes.has("setPosition") || changes.has("setSize")) {
this.handleAriaTextChange();
}
}
loaded() {
logger.deprecated("component", {
component: this,
name: "handle",
removalVersion: 5,
suggested: "sort-handle"
});
}
handleAriaTextChange() {
const message = this.getAriaText("live");
if (message) {
this.calciteInternalAssistiveTextChange.emit({
message
});
}
}
getTooltip() {
const { label, messages } = this;
if (!messages) {
return "";
}
if (!label) {
return messages.dragHandleUntitled;
}
return messages.dragHandle.replace(SUBSTITUTIONS.itemLabel, label);
}
getAriaText(type) {
const { setPosition, setSize, label, messages, selected } = this;
if (!messages || !label || typeof setSize !== "number" || typeof setPosition !== "number") {
return null;
}
const text = type === "label" ? selected ? messages.dragHandleChange : messages.dragHandleIdle : selected ? messages.dragHandleActive : messages.dragHandleCommit;
const replacePosition = text.replace(SUBSTITUTIONS.position, setPosition.toString());
const replaceLabel = replacePosition.replace(SUBSTITUTIONS.itemLabel, label);
return replaceLabel.replace(SUBSTITUTIONS.total, setSize.toString());
}
handleKeyDown(event) {
if (this.disabled) {
return;
}
switch (event.key) {
case " ":
this.selected = !this.selected;
this.calciteHandleChange.emit();
event.preventDefault();
break;
case "ArrowUp":
if (!this.selected) {
return;
}
event.preventDefault();
this.calciteHandleNudge.emit({ direction: "up" });
break;
case "ArrowDown":
if (!this.selected) {
return;
}
event.preventDefault();
this.calciteHandleNudge.emit({ direction: "down" });
break;
}
}
handleBlur() {
if (this.blurUnselectDisabled || this.disabled) {
return;
}
if (this.selected) {
this.selected = false;
this.calciteHandleChange.emit();
}
}
render() {
return this.interactiveContainer({ disabled: this.disabled, children: html`<span .ariaChecked=${this.disabled ? null : this.selected} .ariaDisabled=${this.disabled ? this.disabled : null} .ariaLabel=${this.disabled ? null : this.getAriaText("label")} class=${safeClassMap({ [CSS.handle]: true, [CSS.handleSelected]: !this.disabled && this.selected })} @blur=${this.handleBlur} @keydown=${this.handleKeyDown} role=radio tabindex=${(this.disabled ? null : 0) ?? nothing} title=${this.getTooltip() ?? nothing} ${ref(this.handleButtonRef)}><calcite-icon .icon=${ICONS.drag} scale=s></calcite-icon></span>` });
}
}
customElement("calcite-handle", Handle);
export {
Handle
};