UNPKG

@carbon/react

Version:

React components for the Carbon Design System

127 lines (125 loc) 5.77 kB
/** * Copyright IBM Corp. 2016, 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_usePrefix = require("../../internal/usePrefix.js"); const require_useIsomorphicEffect = require("../../internal/useIsomorphicEffect.js"); const require_useEvent = require("../../internal/useEvent.js"); const require_TableContext = require("./TableContext.js"); let classnames = require("classnames"); classnames = require_runtime.__toESM(classnames); let react = require("react"); react = require_runtime.__toESM(react); let prop_types = require("prop-types"); prop_types = require_runtime.__toESM(prop_types); let react_jsx_runtime = require("react/jsx-runtime"); let es_toolkit_compat = require("es-toolkit/compat"); //#region src/components/DataTable/Table.tsx /** * Copyright IBM Corp. 2016, 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 isElementWrappingContent = (element, context) => { if (element.children.length > 0) return false; const computedStyles = window.getComputedStyle(element); context.font = computedStyles.font ? computedStyles.font : `${computedStyles.fontSize}" "${computedStyles.fontFamily}`; let textWidth = (context?.measureText(element.textContent ?? "")).width ?? 0; const letterSpacing = computedStyles.letterSpacing?.split("px"); if (letterSpacing && letterSpacing.length && !isNaN(Number(letterSpacing[0]))) textWidth += Number(letterSpacing[0]) * (element.textContent?.length ?? 0); const paddingLeft = computedStyles.paddingLeft?.split("px"); if (paddingLeft && paddingLeft.length && !isNaN(Number(paddingLeft[0]))) textWidth += Number(paddingLeft[0]); const paddingRight = computedStyles.paddingLeft?.split("px"); if (paddingRight && paddingRight.length && !isNaN(Number(paddingRight[0]))) textWidth += Number(paddingRight[0]); if (textWidth > element.getBoundingClientRect().width) return true; return false; }; const Table = ({ className, children, useZebraStyles, size = "lg", isSortable = false, useStaticWidth, stickyHeader, overflowMenuOnHover = true, experimentalAutoAlign = false, ...other }) => { const { titleId, descriptionId } = (0, react.useContext)(require_TableContext.TableContext); const prefix = require_usePrefix.usePrefix(); const tableRef = (0, react.useRef)(null); const componentClass = (0, classnames.default)(`${prefix}--data-table`, className, { [`${prefix}--data-table--${size}`]: size, [`${prefix}--data-table--sort`]: isSortable, [`${prefix}--data-table--zebra`]: useZebraStyles, [`${prefix}--data-table--static`]: useStaticWidth, [`${prefix}--data-table--sticky-header`]: stickyHeader, [`${prefix}--data-table--visible-overflow-menu`]: !overflowMenuOnHover }); const toggleTableBodyAlignmentClass = (0, react.useCallback)((alignTop = false) => { if (alignTop) tableRef.current?.classList.add(`${prefix}--data-table--top-aligned-body`); else tableRef.current?.classList.remove(`${prefix}--data-table--top-aligned-body`); }, [prefix]); const toggleTableHeaderAlignmentClass = (0, react.useCallback)((alignTop = false) => { if (alignTop) tableRef.current?.classList.add(`${prefix}--data-table--top-aligned-header`); else tableRef.current?.classList.remove(`${prefix}--data-table--top-aligned-header`); }, [prefix]); const setTableAlignment = (0, react.useCallback)(() => { if (experimentalAutoAlign) { const context = document.createElement("canvas").getContext("2d"); if (tableRef.current && context) { const isBodyMultiline = Array.from(tableRef.current.querySelectorAll("td")).some((td) => isElementWrappingContent(td, context)); const isHeaderMultiline = Array.from(tableRef.current.querySelectorAll("th")).some((th) => { const label = th.querySelector(`.${prefix}--table-header-label`); return label instanceof HTMLElement && isElementWrappingContent(label, context); }); toggleTableBodyAlignmentClass(isBodyMultiline); toggleTableHeaderAlignmentClass(isHeaderMultiline); } } else { toggleTableBodyAlignmentClass(false); toggleTableHeaderAlignmentClass(false); } }, [ experimentalAutoAlign, toggleTableBodyAlignmentClass, toggleTableHeaderAlignmentClass, prefix ]); require_useEvent.useWindowEvent("resize", (0, es_toolkit_compat.debounce)(setTableAlignment, 100)); if (typeof document !== "undefined" && document?.fonts?.status && document.fonts.status !== "loaded") document.fonts.ready.then(() => { setTableAlignment(); }); require_useIsomorphicEffect.default(() => { setTableAlignment(); }, [setTableAlignment, size]); const table = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: `${prefix}--data-table-content`, children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("table", { "aria-labelledby": titleId, "aria-describedby": descriptionId, ...other, className: componentClass, ref: tableRef, children }) }); return stickyHeader ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", { className: `${prefix}--data-table_inner-container`, children: table }) : table; }; Table.propTypes = { children: prop_types.default.node, className: prop_types.default.string, experimentalAutoAlign: prop_types.default.bool, isSortable: prop_types.default.bool, overflowMenuOnHover: prop_types.default.bool, size: prop_types.default.oneOf([ "xs", "sm", "md", "lg", "xl" ]), stickyHeader: prop_types.default.bool, useStaticWidth: prop_types.default.bool, useZebraStyles: prop_types.default.bool, tabIndex: prop_types.default.number }; //#endregion exports.default = Table;