@carbon/ibm-products
Version:
Carbon for IBM Products
299 lines (297 loc) • 12.2 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.
*/
const require_runtime = require("../../_virtual/_rolldown/runtime.js");
const require_index = require("../../node_modules/classnames/index.js");
const require_settings = require("../../settings.js");
const require_usePreviousValue = require("../../global/js/hooks/usePreviousValue.js");
const require_props_helper = require("../../global/js/utils/props-helper.js");
const require_selectAllCells = require("./utils/selectAllCells.js");
const require_useSpreadsheetMouseMove = require("./hooks/useSpreadsheetMouseMove.js");
const require_checkActiveHeaderCell = require("./utils/checkActiveHeaderCell.js");
const require_checkSelectedHeaderCell = require("./utils/checkSelectedHeaderCell.js");
const require_getSpreadsheetWidth = require("./utils/getSpreadsheetWidth.js");
const require_checkForHoldingKey = require("./utils/checkForHoldingKey.js");
const require_handleHeaderCellSelection = require("./utils/handleHeaderCellSelection.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_layout = require("@carbon/layout");
//#region src/components/DataSpreadsheet/DataSpreadsheetHeader.tsx
/**
* Copyright IBM Corp. 2022, 2022
*
* 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 blockClass = `${require_settings.pkg.prefix}--data-spreadsheet`;
const DataSpreadsheetHeader = (0, react.forwardRef)(({ activeCellCoordinates, cellSize, columns, currentMatcher, defaultColumn, headerGroups, scrollBarSize, selectionAreas, selectedHeaderReorderActive, setSelectedHeaderReorderActive, setActiveCellCoordinates, setCurrentMatcher, setSelectionAreas, readOnlyTable, disableColumnSwapping, setSelectionAreaData, rows, totalVisibleColumns, updateActiveCellCoordinates, setHeaderCellHoldActive, headerCellHoldActive, selectAllAriaLabel, visibleColumns }, ref) => {
const [scrollBarSizeValue, setScrollBarSizeValue] = (0, react.useState)(0);
const previousState = require_usePreviousValue.usePreviousValue({ cellSize }) || {};
(0, react.useEffect)(() => {
if (previousState?.cellSize !== cellSize) {
const scrollContainer = ref?.current?.querySelector(`.${blockClass}__list--container`);
const scrollBarValue = scrollContainer?.scrollHeight && scrollContainer?.clientHeight && scrollContainer?.scrollHeight > scrollContainer?.clientHeight ? 0 : scrollBarSize;
if (!scrollContainer?.getAttribute("tabIndex")) scrollContainer?.setAttribute("tabIndex", "0");
setScrollBarSizeValue(scrollBarValue);
}
}, [
cellSize,
ref,
scrollBarSize,
previousState?.cellSize
]);
const handleColumnHeaderClick = (index) => {
return (event) => {
require_handleHeaderCellSelection.handleHeaderCellSelection({
type: "column",
activeCellCoordinates,
rows,
columns,
currentMatcher,
setActiveCellCoordinates,
setCurrentMatcher,
setSelectionAreas,
spreadsheetRef: ref,
index,
isKeyboard: void 0,
setSelectionAreaData,
isHoldingCommandKey: require_checkForHoldingKey.checkForHoldingKey(event, "cmd"),
isHoldingShiftKey: require_checkForHoldingKey.checkForHoldingKey(event, "shiftKey")
});
};
};
const handleSelectAllClick = () => {
require_selectAllCells.selectAllCells({
ref,
setCurrentMatcher,
setSelectionAreas,
rows,
columns,
activeCellCoordinates,
updateActiveCellCoordinates
});
};
const handleHeaderMouseDown = (index) => {
return (event) => {
if (event.shiftKey) return;
const selectionAreaToClone = selectionAreas?.filter((item) => item?.matcher === currentMatcher);
const selectionAreaElement = ref.current.querySelector(`[data-matcher-id="${selectionAreaToClone?.[0]?.matcher}"]`);
if (selectionAreaElement) selectionAreaElement.classList.add(`${blockClass}__selection-area--element`);
if (typeof setSelectedHeaderReorderActive === "function") setSelectedHeaderReorderActive(true);
const clickXPosition = event.clientX;
const headerButtonCoords = event.target.getBoundingClientRect();
const headerIndex = event.target.getAttribute("data-column-index");
const offsetXValue = clickXPosition - headerButtonCoords.left;
const lowestColumnIndexFromSelectionArea = Math.min(selectionAreaToClone?.[0]?.point1?.column || 0, selectionAreaToClone?.[0]?.point2?.column || 0);
const selectionAreaCoords = selectionAreaElement?.getBoundingClientRect() || new DOMRect();
const updatedOffsetDifference = lowestColumnIndexFromSelectionArea < parseInt(headerIndex) ? offsetXValue + (headerButtonCoords.left - selectionAreaCoords?.left) : offsetXValue;
const bodyContainer = (ref?.current ?? document).querySelector(`.${blockClass}__list--container`)?.firstElementChild;
const selectionAreaClonedElement = selectionAreaElement?.cloneNode();
const reorderIndicatorLine = selectionAreaElement?.cloneNode();
if (reorderIndicatorLine) {
reorderIndicatorLine.className = `${blockClass}__reorder-indicator-line`;
reorderIndicatorLine.style.width = (0, _carbon_layout.px)(2);
}
selectionAreaClonedElement.classList.add(`${blockClass}__selection-area--element-cloned`);
selectionAreaClonedElement.setAttribute("data-clone-offset-x", `${updatedOffsetDifference}`);
selectionAreaClonedElement.setAttribute("data-column-index-original", index);
bodyContainer?.appendChild(selectionAreaClonedElement);
bodyContainer?.appendChild(reorderIndicatorLine);
setHeaderCellHoldActive?.(true);
};
};
require_useSpreadsheetMouseMove.useSpreadsheetMouseMove({
ref,
headerCellHoldActive,
defaultColumn
});
return /* @__PURE__ */ react.default.createElement("div", {
className: (0, import_classnames.default)(`${blockClass}__header--container`),
role: "rowgroup"
}, headerGroups?.map((headerGroup, index) => {
const headerProps = require_props_helper.prepareProps(headerGroup.getHeaderGroupProps(), "key");
return /* @__PURE__ */ react.default.createElement("div", {
key: `header_${index}`,
...headerProps,
style: {
...headerGroup.getHeaderGroupProps().style,
width: require_getSpreadsheetWidth.getSpreadsheetWidth({
type: "header",
headerGroup,
scrollBarSizeValue,
totalVisibleColumns,
defaultColumn,
totalColumnsWidth: void 0,
visibleColumns
}),
overflow: "hidden"
},
className: `${blockClass}__tr`
}, /* @__PURE__ */ react.default.createElement("div", {
role: "columnheader",
className: `${blockClass}__select-all-cell-container`,
style: {
width: defaultColumn?.rowHeaderWidth,
height: defaultColumn?.rowHeight
}
}, /* @__PURE__ */ react.default.createElement("button", {
id: `${blockClass}__cell--header--header`,
"data-row-index": "header",
"data-column-index": "header",
type: "button",
style: { width: defaultColumn?.rowHeaderWidth },
tabIndex: -1,
"aria-label": selectAllAriaLabel,
onClick: handleSelectAllClick,
className: (0, import_classnames.default)(`${blockClass}__th`, `${blockClass}--interactive-cell-element`, `${blockClass}__th--select-all`, { [`${blockClass}__th--active-header`]: activeCellCoordinates?.column === "header" && activeCellCoordinates?.row === "header" })
}, "\xA0")), headerGroup.headers.map((column, index) => {
const colProps = require_props_helper.prepareProps(column.getHeaderProps(), "key");
const selectedHeader = require_checkSelectedHeaderCell.checkSelectedHeaderCell(index, selectionAreas, "column", rows);
return /* @__PURE__ */ react.default.createElement("div", {
key: `column_${index}`,
role: "columnheader",
className: `${blockClass}__columnheader`,
...colProps
}, /* @__PURE__ */ react.default.createElement("button", {
id: `${blockClass}__cell--header--${index}`,
"data-row-index": "header",
"data-column-index": index,
tabIndex: -1,
onMouseDown: selectedHeader && !readOnlyTable && !disableColumnSwapping ? handleHeaderMouseDown(index) : void 0,
onMouseUp: selectedHeader && !readOnlyTable && !disableColumnSwapping && typeof setSelectedHeaderReorderActive === "function" ? () => setSelectedHeaderReorderActive(false) : void 0,
onClick: !selectedHeader ? handleColumnHeaderClick(index) : void 0,
style: {
height: defaultColumn?.rowHeight,
width: column?.width || defaultColumn?.width
},
className: (0, import_classnames.default)(`${blockClass}__th`, `${blockClass}--interactive-cell-element`, {
[`${blockClass}__th--active-header`]: activeCellCoordinates?.column === index || require_checkActiveHeaderCell.checkActiveHeaderCell(index, selectionAreas, "column"),
[`${blockClass}__th--active-header-disabledSwapping`]: disableColumnSwapping || readOnlyTable,
[`${blockClass}__th--selected-header`]: selectedHeader,
[`${blockClass}__th--selected-header-reorder-active`]: selectedHeaderReorderActive
}),
type: "button"
}, column.render("Header")));
}));
}));
});
DataSpreadsheetHeader.propTypes = {
/**
* Object containing the active cell coordinates
*/
/**@ts-ignore */
activeCellCoordinates: prop_types.default.shape({
row: prop_types.default.oneOfType([prop_types.default.number, prop_types.default.string]),
column: prop_types.default.oneOfType([prop_types.default.number, prop_types.default.string])
}),
/**
* Specifies the cell height
*/
cellSize: prop_types.default.oneOf([
"xs",
"sm",
"md",
"lg"
]),
/**
* All of the spreadsheet columns
*/
columns: prop_types.default.array,
/**
* uuid that corresponds to the current selection area
*/
currentMatcher: prop_types.default.string,
/**
* Default spreadsheet sizing values
*/
/**@ts-ignore */
defaultColumn: prop_types.default.shape({
rowHeight: prop_types.default.number,
rowHeaderWidth: prop_types.default.number,
width: prop_types.default.number
}),
/**
* Disable column swapping, default false
*/
disableColumnSwapping: prop_types.default.bool,
/**
* Whether or not a click/hold is active on a header cell
*/
headerCellHoldActive: prop_types.default.bool,
/**
* Headers provided from useTable hook
*/
headerGroups: prop_types.default.arrayOf(prop_types.default.object),
/**
* Read-only table
*/
readOnlyTable: prop_types.default.bool,
/**
* All of the spreadsheet row data
*/
/**@ts-ignore */
rows: prop_types.default.arrayOf(prop_types.default.object),
/**
* The scrollbar width
*/
scrollBarSize: prop_types.default.number,
/**
* The aria label applied to the Select all button
*/
selectAllAriaLabel: prop_types.default.string.isRequired,
/**
* Header reordering is active
*/
selectedHeaderReorderActive: prop_types.default.bool,
/**
* All of the cell selection area items
*/
/**@ts-ignore */
selectionAreas: prop_types.default.arrayOf(prop_types.default.object),
/**
* Setter fn for activeCellCoordinates value
*/
setActiveCellCoordinates: prop_types.default.func,
/**
* Setter fn for currentMatcher value
*/
setCurrentMatcher: prop_types.default.func,
/**
* Setter fn for header cell hold active value
*/
setHeaderCellHoldActive: prop_types.default.func,
/**
* Set header reordering active or not
*/
setSelectedHeaderReorderActive: prop_types.default.func,
/**
* Setter fn for selectionAreaData state value
*/
setSelectionAreaData: prop_types.default.func,
/**
* Setter fn for selectionAreas value
*/
setSelectionAreas: prop_types.default.func,
/**
* The total number of columns to be initially visible, additional columns will be rendered and
* visible via horizontal scrollbar
*/
totalVisibleColumns: prop_types.default.number,
/**
* Function used to update the active cell coordinates
*/
updateActiveCellCoordinates: prop_types.default.func,
/**
* Array of visible columns provided by react-table useTable hook
*/
/**@ts-ignore */
visibleColumns: prop_types.default.array
};
//#endregion
exports.DataSpreadsheetHeader = DataSpreadsheetHeader;