UNPKG

@carbon/ibm-products

Version:
299 lines (297 loc) 12.2 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_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;