@carbon/ibm-products-web-components
Version:
Carbon for IBM Products Web Components
188 lines (186 loc) • 5.63 kB
JavaScript
/**
* 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"
=${handleKeyDown}
>
<div class="${blockClass}-list-body">
<slot =${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