UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

235 lines (234 loc) • 12.1 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 } 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`@charset "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} @click=${this.clickHandler} @keydown=${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 @click=${this.clickHandler} @keydown=${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 })} @keydown=${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 };