@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
235 lines (234 loc) • 12.1 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 } from "lit";
import { LitElement, createEvent, safeClassMap } from "@arcgis/lumina";
import { createRef, ref } from "lit-html/directives/ref.js";
import { render } from "lit-html";
import { d as focusElementInGroup } from "../../chunks/dom.js";
import { i as isActivationKey } from "../../chunks/key.js";
import { u as updateHostInteraction, I as InteractiveContainer } from "../../chunks/interactive.js";
import { g as getIconScale } from "../../chunks/component.js";
import { css } from "@lit/reactive-element/css-tag.js";
const CSS = {
lastVisibleRow: "last-visible-row"
};
const styles = css` "UTF-8";: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{--calcite-internal-table-row-background: var(--calcite-table-row-background, var(--calcite-color-foreground-1));--calcite-internal-table-row-border-color: var(--calcite-table-row-border-color, transparent);display:contents}:host([hidden]){display:none}[hidden]{display:none}:host([disabled]) tr{pointer-events:none;opacity:var(--calcite-opacity-disabled)}:host([disabled]) ::slotted([calcite-hydrated][disabled]),:host([disabled]) [calcite-hydrated][disabled]{opacity:1}.interaction-container{display:contents}tr{border-block-end:1px solid var(--calcite-internal-table-row-border-color);background-color:var(--calcite-internal-table-row-background)}tr.last-visible-row{border-block-end:0}@-moz-document url-prefix(){tr{box-shadow:inset 0 -1px 0 0 var(--calcite-internal-table-row-border-color)}tr.last-visible-row{box-shadow:inset 0 -1px 0 0 transparent}}:host([item-hidden]){display:none}`;
class TableRow extends LitElement {
constructor() {
super();
this.rowCells = [];
this.tableRowSlotEl = createRef();
this.userTriggered = false;
this._selected = false;
this.clickHandler = () => {
this.handleRowSelection();
};
this.handleKeyboardSelection = (event) => {
if (isActivationKey(event.key)) {
if (event.key === " ") {
event.preventDefault();
}
this.handleRowSelection();
}
};
this.itemHidden = false;
this.disabled = false;
this.interactionMode = "interactive";
this.numbered = false;
this.selectionMode = "none";
this.calciteInternalTableRowFocusRequest = createEvent({ cancelable: false });
this.calciteInternalTableRowSelect = createEvent({ cancelable: false });
this.calciteTableRowSelect = createEvent({ cancelable: false });
this.listenOn(document, "calciteInternalTableRowFocusChange", this.calciteInternalTableRowFocusChangeHandler);
}
static {
this.properties = { alignment: [3, {}, { reflect: true }], itemHidden: [7, {}, { reflect: true, type: Boolean }], bodyRowCount: [9, {}, { type: Number }], cellCount: [9, {}, { type: Number }], disabled: [7, {}, { reflect: true, type: Boolean }], interactionMode: 1, lastVisibleRow: [5, {}, { type: Boolean }], numbered: [5, {}, { type: Boolean }], positionAll: [9, {}, { type: Number }], positionSection: [9, {}, { type: Number }], positionSectionLocalized: 1, readCellContentsToAT: [5, {}, { type: Boolean }], rowType: 1, scale: 1, selected: [7, {}, { reflect: true, type: Boolean }], selectedRowCount: [9, {}, { type: Number }], selectedRowCountLocalized: 1, selectionMode: 1 };
}
static {
this.styles = styles;
}
get selected() {
return this._selected;
}
set selected(value) {
const oldValue = this._selected;
if (value !== oldValue) {
this._selected = value;
this.handleCellChanges();
}
}
load() {
this.listenOn(this.el.shadowRoot, "slotchange", this.handleSlotChange);
}
willUpdate(changes) {
if (changes.has("bodyRowCount") || changes.has("scale") || changes.has("selectedRowCount") || changes.has("interactionMode") && (this.hasUpdated || this.interactionMode !== "interactive")) {
this.handleCellChanges();
}
if (changes.has("numbered") && (this.hasUpdated || this.numbered !== false) || changes.has("selectionMode") && (this.hasUpdated || this.selectionMode !== "none")) {
this.handleDelayedCellChanges();
}
if (changes.has("selected") && (this.hasUpdated || this.selected !== false) && !this.userTriggered) {
this.calciteInternalTableRowSelect.emit();
}
}
updated() {
updateHostInteraction(this);
}
loaded() {
if (this.tableRowEl && this.rowCells.length > 0) {
this.updateCells();
}
}
handleSlotChange() {
this.updateCells();
}
handleCellChanges() {
if (this.tableRowEl && this.rowCells.length > 0) {
this.updateCells();
}
}
handleDelayedCellChanges() {
if (this.tableRowEl && this.rowCells.length > 0) {
requestAnimationFrame(() => this.updateCells());
}
}
calciteInternalTableRowFocusChangeHandler(event) {
if (event.target.contains(this.el)) {
const position = event.detail.cellPosition;
const rowPosition = event.detail.rowPosition;
const destination = event.detail.destination;
const lastCell = event.detail.lastCell;
if (rowPosition === this.positionAll) {
if (this.disabled) {
const deflectDirection = destination === "last" ? "previous" : destination === "first" ? "next" : destination;
this.emitTableRowFocusRequest(position, this.positionAll, deflectDirection);
return;
}
const cellPosition = lastCell ? this.rowCells[this.rowCells.length - 1] : this.rowCells?.find((_, index) => index + 1 === position);
if (cellPosition) {
cellPosition.setFocus();
}
}
}
}
keyDownHandler(event) {
if (this.interactionMode !== "interactive") {
return;
}
const el = event.target;
const key = event.key;
const isControl = event.ctrlKey;
const cells = this.rowCells;
if (el.matches("calcite-table-cell") || el.matches("calcite-table-header")) {
switch (key) {
case "ArrowUp":
this.emitTableRowFocusRequest(el.positionInRow, this.positionAll, "previous");
event.preventDefault();
break;
case "ArrowDown":
this.emitTableRowFocusRequest(el.positionInRow, this.positionAll, "next");
event.preventDefault();
break;
case "PageUp":
this.emitTableRowFocusRequest(el.positionInRow, this.positionAll, "first");
event.preventDefault();
break;
case "PageDown":
this.emitTableRowFocusRequest(el.positionInRow, this.positionAll, "last");
event.preventDefault();
break;
case "ArrowLeft":
focusElementInGroup(cells, el, "previous", false);
event.preventDefault();
break;
case "ArrowRight":
focusElementInGroup(cells, el, "next", false);
event.preventDefault();
break;
case "Home":
if (isControl) {
this.emitTableRowFocusRequest(1, this.positionAll, "first");
event.preventDefault();
} else {
focusElementInGroup(cells, el, "first", false);
event.preventDefault();
}
break;
case "End":
if (isControl) {
this.emitTableRowFocusRequest(this.rowCells?.length, this.positionAll, "last", true);
event.preventDefault();
} else {
focusElementInGroup(cells, el, "last", false);
event.preventDefault();
}
break;
}
}
}
emitTableRowFocusRequest(cellPosition, rowPosition, destination, lastCell) {
this.calciteInternalTableRowFocusRequest.emit({
cellPosition,
rowPosition,
destination,
lastCell
});
}
updateCells() {
const alignment = this.alignment ? this.alignment : this.rowType !== "head" ? "center" : "start";
const slottedCells = this.tableRowSlotEl.value?.assignedElements({ flatten: true })?.filter((el) => el.matches("calcite-table-cell") || el.matches("calcite-table-header"));
const renderedCells = Array.from(this.tableRowEl?.querySelectorAll("calcite-table-header, calcite-table-cell"))?.filter((el) => el.numberCell || el.selectionCell);
const cells = renderedCells ? renderedCells.concat(slottedCells) : slottedCells;
if (cells.length > 0) {
cells?.forEach((cell, index) => {
cell.interactionMode = this.interactionMode;
cell.lastCell = index === cells.length - 1;
cell.parentRowAlignment = alignment;
cell.parentRowIsSelected = this.selected;
cell.parentRowType = this.rowType;
cell.positionInRow = index + 1;
cell.scale = this.scale;
if (cell.nodeName === "CALCITE-TABLE-CELL") {
cell.readCellContentsToAT = this.readCellContentsToAT;
cell.disabled = this.disabled;
}
});
}
this.rowCells = cells || [];
this.cellCount = cells?.length;
}
async handleRowSelection() {
if (this.rowType === "body" || this.rowType === "head" && this.selectionMode === "multiple") {
this.userTriggered = true;
this.selected = !this.selected;
await this.updateComplete;
this.calciteTableRowSelect.emit();
}
}
renderSelectionIcon() {
const icon = this.selectionMode === "multiple" && this.selected ? "check-square-f" : this.selectionMode === "multiple" ? "square" : this.selected ? "circle-f" : "circle";
return html`<calcite-icon .icon=${icon} .scale=${getIconScale(this.scale)}></calcite-icon>`;
}
renderSelectableCell() {
return this.rowType === "head" ? keyed("selection-head", html`<calcite-table-header alignment=center .bodyRowCount=${this.bodyRowCount} =${this.clickHandler} =${this.handleKeyboardSelection} .parentRowAlignment=${this.alignment} .selectedRowCount=${this.selectedRowCount} .selectedRowCountLocalized=${this.selectedRowCountLocalized} .selectionCell=${true} .selectionMode=${this.selectionMode}></calcite-table-header>`) : this.rowType === "body" ? keyed("selection-body", html`<calcite-table-cell alignment=center =${this.clickHandler} =${this.handleKeyboardSelection} .parentRowAlignment=${this.alignment} .parentRowIsSelected=${this.selected} .parentRowPositionLocalized=${this.positionSectionLocalized} .selectionCell=${true}>${this.renderSelectionIcon()}</calcite-table-cell>`) : keyed("selection-foot", html`<calcite-table-cell alignment=center .parentRowAlignment=${this.alignment} .selectionCell=${true}></calcite-table-cell>`);
}
renderNumberedCell() {
return this.rowType === "head" ? keyed("numbered-head", html`<calcite-table-header alignment=center .numberCell=${true} .parentRowAlignment=${this.alignment}></calcite-table-header>`) : this.rowType === "body" ? keyed("numbered-body", html`<calcite-table-cell alignment=center .numberCell=${true} .parentRowAlignment=${this.alignment}>${this.positionSectionLocalized}</calcite-table-cell>`) : keyed("numbered-foot", html`<calcite-table-cell alignment=center .numberCell=${true} .parentRowAlignment=${this.alignment}></calcite-table-cell>`);
}
render() {
return InteractiveContainer({ disabled: this.disabled, children: html`<tr .ariaRowIndex=${this.positionAll + 1} .ariaSelected=${this.selected} class=${safeClassMap({ [CSS.lastVisibleRow]: this.lastVisibleRow })} =${this.keyDownHandler} ${ref((el) => {
if (!el) {
return;
}
this.tableRowEl = el;
render(html`${this.numbered && this.renderNumberedCell() || ""}${this.selectionMode !== "none" && this.renderSelectableCell() || ""}<slot ${ref(this.tableRowSlotEl)}></slot>`, el);
})}></tr>` });
}
}
customElement("calcite-table-row", TableRow);
export {
TableRow
};