@carbon/react
Version:
React components for the Carbon Design System
127 lines (125 loc) • 5.77 kB
JavaScript
/**
* 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;