UNPKG

@carbon/ibm-products

Version:
178 lines (176 loc) 7.89 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. */ const require_runtime = require("../../../_virtual/_rolldown/runtime.js"); const require_index = require("../../../node_modules/classnames/index.js"); const require_context = require("./context.js"); let react = require("react"); react = require_runtime.__toESM(react); let prop_types = require("prop-types"); prop_types = require_runtime.__toESM(prop_types); let _carbon_react = require("@carbon/react"); //#region src/components/AddSelect/next/AddSelectBody.tsx /** * 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. */ var import_classnames = /* @__PURE__ */ require_runtime.__toESM(require_index.default); const AddSelectBody = (0, react.forwardRef)(({ children, className, layout = "vertical", itemsLabel = "", globalSearchLabel = "Search", globalSearchPlaceholder = "Search", searchResultsTitle = "Search results", itemCount, path = [], onSearch, onBreadcrumbClick, headerContent, actionsSlot, subHeaderActions, hideSearch = false, searchProps, tagProps, breadcrumbProps, breadcrumbItemProps, linkProps, ...rest }, ref) => { const { multi } = (0, react.useContext)(require_context.AddSelectContext); const [searchTerm, setSearchTerm] = (0, react.useState)(""); const listRef = (0, react.useRef)(null); const focusedIndexRef = (0, react.useRef)(0); const getItems = () => { if (!listRef.current) return []; return Array.from(listRef.current.querySelectorAll("[role=\"row\"]")); }; const updateItemFocus = (focusIndex, shouldFocus = true) => { const items = getItems(); if (items.length === 0) return; focusedIndexRef.current = Math.max(0, Math.min(focusIndex, items.length - 1)); items.forEach((item, index) => { if (index === focusedIndexRef.current) { item.setAttribute("tabindex", "0"); if (shouldFocus) item.focus(); } else item.setAttribute("tabindex", "-1"); }); }; const handleKeyDown = (event) => { const items = getItems(); if (items.length === 0) return; const currentItem = items[focusedIndexRef.current]; let handled = false; switch (event.key) { case "ArrowDown": event.preventDefault(); updateItemFocus(focusedIndexRef.current + 1); handled = true; break; case "ArrowUp": event.preventDefault(); updateItemFocus(focusedIndexRef.current - 1); handled = true; break; case "ArrowRight": if (currentItem && currentItem.hasAttribute("data-has-children")) { event.preventDefault(); currentItem.querySelector(`.${require_context.blockClass}-row__nav-indicator`)?.click(); handled = true; } break; case "Enter": case " ": event.preventDefault(); if (currentItem) currentItem.querySelector("input[type=\"checkbox\"], input[type=\"radio\"]")?.click(); handled = true; break; case "Home": if (event.ctrlKey) { event.preventDefault(); updateItemFocus(0); handled = true; } break; case "End": if (event.ctrlKey) { event.preventDefault(); updateItemFocus(items.length - 1); handled = true; } break; } if (handled) event.stopPropagation(); }; (0, react.useEffect)(() => { updateItemFocus(0, false); }, [children]); const handleSearch = (event) => { const value = event.target.value; setSearchTerm(value); onSearch?.(value); }; const bodyClasses = (0, import_classnames.default)(`${require_context.blockClass}__body`, className); return /* @__PURE__ */ react.default.createElement("div", { className: bodyClasses, ref, ...rest }, /* @__PURE__ */ react.default.createElement("div", { className: `${require_context.blockClass}__header` }, headerContent || /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, (!hideSearch || actionsSlot) && /* @__PURE__ */ react.default.createElement("div", { className: (0, import_classnames.default)(`${require_context.blockClass}__search`, { [`${require_context.blockClass}__search--with-actions`]: actionsSlot }) }, !hideSearch && /* @__PURE__ */ react.default.createElement("div", { className: actionsSlot ? `${require_context.blockClass}__search-input` : "" }, /* @__PURE__ */ react.default.createElement(_carbon_react.Search, { labelText: globalSearchLabel, placeholder: globalSearchPlaceholder, size: "lg", onChange: handleSearch, value: searchTerm, ...searchProps })), actionsSlot && /* @__PURE__ */ react.default.createElement("div", { className: `${require_context.blockClass}__global-actions` }, actionsSlot)), /* @__PURE__ */ react.default.createElement("div", { className: `${require_context.blockClass}__sub-header` }, /* @__PURE__ */ react.default.createElement("div", { className: `${require_context.blockClass}__tags` }, searchTerm ? /* @__PURE__ */ react.default.createElement("p", { className: `${require_context.blockClass}__tags-label` }, searchResultsTitle) : path && path.length > 0 ? /* @__PURE__ */ react.default.createElement(_carbon_react.Breadcrumb, { noTrailingSlash: true, className: `${require_context.blockClass}__breadcrumbs`, ...breadcrumbProps }, path.map((entry, idx) => { const isCurrentPage = idx === path.length - 1; return /* @__PURE__ */ react.default.createElement(_carbon_react.BreadcrumbItem, { key: entry.id, isCurrentPage, ...breadcrumbItemProps }, isCurrentPage ? entry.title : /* @__PURE__ */ react.default.createElement(_carbon_react.Link, { href: "#", onClick: (e) => { e.preventDefault(); onBreadcrumbClick?.(idx); }, ...linkProps }, entry.title)); })) : /* @__PURE__ */ react.default.createElement("p", { className: `${require_context.blockClass}__tags-label` }, itemsLabel), itemCount !== void 0 && /* @__PURE__ */ react.default.createElement(_carbon_react.Tag, { type: "gray", size: "sm", ...tagProps }, itemCount)), subHeaderActions && /* @__PURE__ */ react.default.createElement("div", { className: `${require_context.blockClass}__sub-header-actions` }, subHeaderActions)))), /* @__PURE__ */ react.default.createElement("div", { className: `${require_context.blockClass}__content`, ref: listRef, role: "grid", "aria-multiselectable": multi, tabIndex: 0, onKeyDown: handleKeyDown }, /* @__PURE__ */ react.default.createElement("div", { className: (0, import_classnames.default)(`${require_context.blockClass}-list-body`, { [`${require_context.blockClass}-list-body--horizontal`]: layout === "horizontal" }) }, children))); }); AddSelectBody.propTypes = { actionsSlot: prop_types.default.node, /**@ts-ignore */ breadcrumbItemProps: prop_types.default.object, /**@ts-ignore */ breadcrumbProps: prop_types.default.object, children: prop_types.default.node, className: prop_types.default.string, globalSearchLabel: prop_types.default.string, globalSearchPlaceholder: prop_types.default.string, headerContent: prop_types.default.node, hideSearch: prop_types.default.bool, itemCount: prop_types.default.number, itemsLabel: prop_types.default.string, /**@ts-ignore */ layout: prop_types.default.oneOf(["vertical", "horizontal"]), /**@ts-ignore */ linkProps: prop_types.default.object, /**@ts-ignore */ onBreadcrumbClick: prop_types.default.func, /**@ts-ignore */ onSearch: prop_types.default.func, /**@ts-ignore */ path: prop_types.default.arrayOf(prop_types.default.shape({ id: prop_types.default.string.isRequired, title: prop_types.default.string.isRequired })), /**@ts-ignore */ searchProps: prop_types.default.object, searchResultsTitle: prop_types.default.string, subHeaderActions: prop_types.default.node, /**@ts-ignore */ tagProps: prop_types.default.object }; AddSelectBody.displayName = "AddSelectBody"; //#endregion exports.default = AddSelectBody;