UNPKG

@carbon/ibm-products-web-components

Version:
188 lines (186 loc) 5.63 kB
/** * Copyright IBM Corp. 2020, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ import "../../globals/settings.js"; import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.js"; import add_select_content_default$1 from "./add-select-content.scss.js"; import { classMap } from "lit/directives/class-map.js"; import { LitElement, html } from "lit"; import { carbonElement } from "@carbon/web-components/es/globals/decorators/carbon-element.js"; //#region src/components/add-select/add-select-content.ts /** * @license * * Copyright IBM Corp. 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ const blockClass = `c4p--add-select__next-list`; /** * Add Select Content component - contains the list of selectable items * @element c4p-add-select-content * @slot default - Contains c4p-add-select-row components */ let CDSAddSelectContent = class CDSAddSelectContent extends LitElement { constructor(..._args) { super(..._args); this._focusedIndex = 0; this._hasKeyboardInteraction = false; } /** * Whether this is a multi-select list (inherited from parent c4p-add-select) * @private */ get _multi() { return this.closest(`c4p-add-select`)?.multi ?? false; } /** * Get all item elements */ _getItems() { const slot = this.shadowRoot?.querySelector("slot"); if (!slot) return []; return slot.assignedElements({ flatten: true }).filter((el) => el.tagName.toLowerCase() === `c4p-add-select-row`); } /** * Update focus on items - only one item should have tabindex="0" */ _updateItemFocus(focusIndex, shouldFocus = true) { const items = this._getItems(); if (items.length === 0) return; this._focusedIndex = Math.max(0, Math.min(focusIndex, items.length - 1)); items.forEach((item, index) => { if (index === this._focusedIndex) { item.setAttribute("tabindex", "0"); if (shouldFocus) item.focus(); } else item.setAttribute("tabindex", "-1"); }); } /** * Handle keyboard navigation */ _handleKeyDown(event) { const items = this._getItems(); if (items.length === 0) return; this._hasKeyboardInteraction = true; const currentItem = items[this._focusedIndex]; let handled = false; switch (event.key) { case "ArrowDown": event.preventDefault(); this._updateItemFocus(this._focusedIndex + 1); handled = true; break; case "ArrowUp": event.preventDefault(); this._updateItemFocus(this._focusedIndex - 1); handled = true; break; case "ArrowRight": if (currentItem && currentItem.hasAttribute("has-children")) { event.preventDefault(); const navigateEvent = new CustomEvent("c4p-add-select-row-navigate", { bubbles: true, composed: true, detail: { itemId: currentItem.getAttribute("item-id"), title: currentItem.getAttribute("title"), parentId: currentItem.getAttribute("parent-id") || "" } }); currentItem.dispatchEvent(navigateEvent); handled = true; } break; case "Enter": case " ": event.preventDefault(); if (currentItem) { const newSelected = !currentItem.hasAttribute("selected"); if (newSelected) currentItem.setAttribute("selected", ""); else currentItem.removeAttribute("selected"); const selectEvent = new CustomEvent("c4p-add-select-row-select", { bubbles: true, composed: true, detail: { itemId: currentItem.getAttribute("item-id"), selected: newSelected, value: currentItem.getAttribute("value") } }); currentItem.dispatchEvent(selectEvent); } handled = true; break; case "Home": if (event.ctrlKey) { event.preventDefault(); this._updateItemFocus(0); handled = true; } break; case "End": if (event.ctrlKey) { event.preventDefault(); this._updateItemFocus(items.length - 1); handled = true; } break; } if (handled) event.stopPropagation(); } /** * Initialize focus management after first update */ firstUpdated() { this._updateItemFocus(0, false); } /** * Handle slot change to update focus management */ _handleSlotChange() { const items = this._getItems(); if (items.length > 0) { if (this._focusedIndex >= items.length) this._focusedIndex = 0; this._updateItemFocus(this._focusedIndex, this._hasKeyboardInteraction); } } /** * Update lifecycle - ensure focus is maintained when items change */ updated(changedProperties) { super.updated(changedProperties); const items = this._getItems(); if (items.length > 0) { if (!items.some((item) => item.getAttribute("tabindex") === "0")) this._updateItemFocus(0, this._hasKeyboardInteraction); } } render() { const { _handleKeyDown: handleKeyDown, _handleSlotChange: handleSlotChange } = this; return html` <div class=${classMap({ [`${blockClass}-list`]: true })} role="grid" aria-multiselectable=${this._multi} tabindex="0" @keydown=${handleKeyDown} > <div class="${blockClass}-list-body"> <slot @slotchange=${handleSlotChange}></slot> </div> </div> `; } static { this.styles = add_select_content_default$1; } }; CDSAddSelectContent = __decorate([carbonElement(`c4p-add-select-content`)], CDSAddSelectContent); var add_select_content_default = CDSAddSelectContent; //#endregion export { add_select_content_default as default }; //# sourceMappingURL=add-select-content.js.map