UNPKG

@neo4j-ndl/react

Version:

React implementation of Neo4j Design System

181 lines 8.46 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TreeItemWrapper = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); /** * * Copyright (c) "Neo4j" * Neo4j Sweden AB [http://neo4j.com] * * This file is part of Neo4j. * * Neo4j is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ const classnames_1 = __importDefault(require("classnames")); const react_1 = require("react"); const utils_1 = require("../_common/utils"); const icons_1 = require("../icons"); const tree_view_keyboard_helpers_1 = require("./tree-view-keyboard-helpers"); const TreeViewTrail_1 = require("./TreeViewTrail"); /** * Handles keydown events for when the item itself is focused (wrapperRef.current) * Moves the focus between the item and its children as well as toggles collapsing of the item * @param event * @param shouldDisableInteraction * @param wrapperRef * @param onCollapse * @param item * @returns */ const onWrapperKeyDown = (event, shouldDisableInteraction, wrapperRef, onCollapse, item) => { if (shouldDisableInteraction || wrapperRef.current === null) { return; } if (event.key === 'Enter' && onCollapse) { onCollapse(); } else if (event.key === 'ArrowRight') { event.preventDefault(); if (item.canHaveSubItems && item.isCollapsed && onCollapse) { onCollapse(); } else { const focusable = (0, utils_1.findFocusableChildren)(wrapperRef.current); const [firstElement] = focusable; if (firstElement instanceof HTMLElement) { firstElement.focus(); } } event.preventDefault(); } else if (event.key === 'ArrowLeft') { event.preventDefault(); if (item.canHaveSubItems && !item.isCollapsed && onCollapse) { onCollapse(); } else { (0, tree_view_keyboard_helpers_1.focusPreviousRow)(wrapperRef.current); } } else if (event.key === 'ArrowDown') { event.preventDefault(); (0, tree_view_keyboard_helpers_1.focusNextRow)(wrapperRef.current); } else if (event.key === 'ArrowUp') { event.preventDefault(); (0, tree_view_keyboard_helpers_1.focusPreviousRow)(wrapperRef.current); } }; /** * Handles keydown events for when one of the items children is focused * Moves the focus between the children of the item and up to the parent if needed. * Stops the event from propagating to the parent since it has it own keydown handler * The parent is the wrapperRef.current and uses onWrapperKeyDown * @param event * @param shouldDisableInteraction * @param wrapperRef */ const onInnerDivKeyDown = (event, shouldDisableInteraction, wrapperRef) => { var _a; if (shouldDisableInteraction) { return; } event.stopPropagation(); if (event.key === 'ArrowRight') { event.preventDefault(); const nextElement = (0, utils_1.findFocusableSibling)(wrapperRef, 'next'); if (nextElement) { nextElement.focus(); } } else if (event.key === 'ArrowLeft') { event.preventDefault(); const previousElement = (0, utils_1.findFocusableSibling)(wrapperRef, 'prev'); if (previousElement) { previousElement.focus(); } else { (_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.focus(); } } else if (event.key === 'ArrowDown' && wrapperRef.current !== null) { event.preventDefault(); (0, tree_view_keyboard_helpers_1.focusCellInNextRow)(wrapperRef.current); } else if (event.key === 'ArrowUp' && wrapperRef.current !== null) { event.preventDefault(); (0, tree_view_keyboard_helpers_1.focusCellInPreviousRow)(wrapperRef.current); } else if (event.shiftKey && event.key === 'Tab') { const previousElement = (0, utils_1.findFocusableSibling)(wrapperRef, 'prev'); if (previousElement) { event.preventDefault(); previousElement.focus(); } } else if (event.key === 'Tab') { if (event.shiftKey) { return; } const nextElement = (0, utils_1.findFocusableSibling)(wrapperRef, 'next'); if (nextElement) { nextElement.focus(); event.preventDefault(); } } }; /** * Used as a helper function to wrap the TreeItem component * This adds the drag handle and trail to the start of a tree item. * Useful if you want to add additional functionality to the tree item but still keep the drag handle and trail * Is also used internally to create the TreeViewTextItem component */ function TreeItemWrapperInner(_a) { var { depth, shouldDisableInteraction, shouldDisableSorting, isGhost, isIndicator, onCollapse, item, setNodeRef, setActivatorNodeRef, dragHandleProps, style, className, trails, children, indentationWidth, tabIndex, onFocus, ref } = _a, // Need to destruct to avoid passing it to the component // oxlint-disable-next-line no-unused-vars restProps = __rest(_a, ["depth", "shouldDisableInteraction", "shouldDisableSorting", "isGhost", "isIndicator", "onCollapse", "item", "setNodeRef", "setActivatorNodeRef", "dragHandleProps", "style", "className", "trails", "children", "indentationWidth", "tabIndex", "onFocus", "ref"]); const wrapperRef = (0, react_1.useRef)(null); return ((0, jsx_runtime_1.jsx)("li", { ref: (el) => { wrapperRef.current = el; if (el === null) { return; } setNodeRef(el); }, className: (0, classnames_1.default)({ className, 'ndl-tree-view-list-item': true, indicator: isIndicator, 'ndl-tree-view-list-item-placeholder': isGhost, 'ndl-tree-view-list-item-disable-interaction': shouldDisableInteraction, }), style: Object.assign(Object.assign({}, style), { paddingLeft: isIndicator ? `${depth * indentationWidth}px` : 0 }), role: "treeitem", onFocus: onFocus, "aria-selected": item.isSelected && !item.isSkeletonLoading, "aria-expanded": item.canHaveSubItems ? !item.isCollapsed : undefined, onKeyDown: (event) => onWrapperKeyDown(event, shouldDisableInteraction !== null && shouldDisableInteraction !== void 0 ? shouldDisableInteraction : false, wrapperRef, onCollapse, item), children: (0, jsx_runtime_1.jsxs)("div", { role: "presentation", className: "ndl-tree-view-list-item-content", ref: ref, onKeyDown: (event) => onInnerDivKeyDown(event, shouldDisableInteraction !== null && shouldDisableInteraction !== void 0 ? shouldDisableInteraction : false, wrapperRef), children: [!shouldDisableSorting && ((0, jsx_runtime_1.jsx)("button", Object.assign({ className: "ndl-tree-view-drag-handle", ref: setActivatorNodeRef, "aria-label": "Pick up" }, dragHandleProps, { tabIndex: tabIndex, children: (0, jsx_runtime_1.jsx)(icons_1.DragIcon, {}) }))), trails.map((trail, index) => { return (0, jsx_runtime_1.jsx)(TreeViewTrail_1.Trail, { variant: trail }, index); }), children] }) })); } exports.TreeItemWrapper = TreeItemWrapperInner; //# sourceMappingURL=TreeItemWrapper.js.map