UNPKG

@blueprintjs/table

Version:

Scalable interactive table component

207 lines (190 loc) 7.24 kB
/* * Copyright 2021 Palantir Technologies, Inc. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Children, type ReactElement } from "react"; import type { HotkeyConfig } from "@blueprintjs/core"; import type { ColumnProps } from "./column"; import { FocusMode } from "./common/cellTypes"; import { getFocusModeFromProps } from "./common/internal/focusedCellUtils"; import { Utils } from "./common/utils"; import { RegionCardinality } from "./regions"; import type { TableHotkeys } from "./tableHotkeys"; import type { TablePropsWithDefaults } from "./tableProps"; export function clampNumFrozenColumns(props: TablePropsWithDefaults) { const { numFrozenColumns } = props; const numColumns = Children.count(props.children); return maybeClampValue(numFrozenColumns, numColumns); } export function clampNumFrozenRows(props: TablePropsWithDefaults) { const { numFrozenRows, numRows } = props; return maybeClampValue(numFrozenRows, numRows); } function maybeClampValue(value: number | undefined, max: number) { return value === undefined ? 0 : Utils.clamp(value, 0, max); } export function hasLoadingOption(loadingOptions: string[] | undefined, loadingOption: string) { if (loadingOptions === undefined) { return false; } return loadingOptions.indexOf(loadingOption) >= 0; } export function isSelectionModeEnabled( props: TablePropsWithDefaults, selectionMode: RegionCardinality, selectionModes = props.selectionModes, ): boolean { const { children, numRows } = props; const numColumns = Children.count(children); return selectionModes.indexOf(selectionMode) >= 0 && numRows > 0 && numColumns > 0; } export function getHotkeysFromProps(props: TablePropsWithDefaults, hotkeysImpl: TableHotkeys): HotkeyConfig[] { const { getCellClipboardData, enableMultipleSelection, selectionModes } = props; const focusMode = getFocusModeFromProps(props); const hotkeys: HotkeyConfig[] = []; if (getCellClipboardData != null) { hotkeys.push({ combo: "mod+c", group: "Table", label: "Copy selected table cells", onKeyDown: hotkeysImpl.handleCopy, }); } const isSomeSelectionModeEnabled = selectionModes.length > 0; if (enableMultipleSelection && isSomeSelectionModeEnabled) { hotkeys.push( { combo: "shift+up", group: "Table", label: "Resize selection upward", onKeyDown: hotkeysImpl.handleSelectionResizeUp, }, { combo: "shift+down", group: "Table", label: "Resize selection downward", onKeyDown: hotkeysImpl.handleSelectionResizeDown, }, { combo: "shift+left", group: "Table", label: "Resize selection leftward", onKeyDown: hotkeysImpl.handleSelectionResizeLeft, }, { combo: "shift+right", group: "Table", label: "Resize selection rightward", onKeyDown: hotkeysImpl.handleSelectionResizeRight, }, ); } hotkeys.push(...getFocusHotkeys(focusMode, hotkeysImpl)); if (isSelectionModeEnabled(props, RegionCardinality.FULL_TABLE)) { hotkeys.push({ combo: "mod+a", group: "Table", label: "Select all", onKeyDown: hotkeysImpl.handleSelectAllHotkey, }); } return hotkeys; } function getFocusHotkeys(focusMode: FocusMode | undefined, hotkeysImpl: TableHotkeys): HotkeyConfig[] { switch (focusMode) { case undefined: return []; case FocusMode.ROW: return [ { combo: "up", group: "Table", label: "Move focus row up", onKeyDown: hotkeysImpl.handleFocusMoveUp, }, { combo: "down", group: "Table", label: "Move focus row down", onKeyDown: hotkeysImpl.handleFocusMoveDown, }, ]; case FocusMode.CELL: return [ { combo: "left", group: "Table", label: "Move focus cell left", onKeyDown: hotkeysImpl.handleFocusMoveLeft, }, { combo: "right", group: "Table", label: "Move focus cell right", onKeyDown: hotkeysImpl.handleFocusMoveRight, }, { combo: "up", group: "Table", label: "Move focus cell up", onKeyDown: hotkeysImpl.handleFocusMoveUp, }, { combo: "down", group: "Table", label: "Move focus cell down", onKeyDown: hotkeysImpl.handleFocusMoveDown, }, { allowInInput: true, combo: "tab", group: "Table", label: "Move focus cell tab", onKeyDown: hotkeysImpl.handleFocusMoveRightInternal, }, { allowInInput: true, combo: "shift+tab", group: "Table", label: "Move focus cell shift tab", onKeyDown: hotkeysImpl.handleFocusMoveLeftInternal, }, { allowInInput: true, combo: "enter", group: "Table", label: "Move focus cell enter", onKeyDown: hotkeysImpl.handleFocusMoveDownInternal, }, { allowInInput: true, combo: "shift+enter", group: "Table", label: "Move focus cell shift enter", onKeyDown: hotkeysImpl.handleFocusMoveUpInternal, }, ]; } } /** * @returns true if new and old children arrays are the same */ export function compareChildren( newChildren: Array<ReactElement<ColumnProps>>, oldChildren: Array<ReactElement<ColumnProps>>, ): boolean { return ( newChildren.length === oldChildren.length && newChildren.every((child, index) => child.key === oldChildren[index].key) ); }