UNPKG

@neo4j-ndl/react

Version:

React implementation of Neo4j Design System

167 lines 6.77 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.truncateReactNodeByCharacters = exports.getTextContent = void 0; /** * * 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 react_1 = __importDefault(require("react")); const constants_1 = require("./constants"); /** * Recursively extracts plain text from React nodes */ const getTextContent = (node) => { if (typeof node === 'string') { return node; } if (typeof node === 'number') { return node.toString(); } if (react_1.default.isValidElement(node)) { // Type assertion to access props safely const element = node; return (0, exports.getTextContent)(element.props.children); } if (Array.isArray(node)) { return node.map(exports.getTextContent).join(''); } return ''; }; exports.getTextContent = getTextContent; /** * Truncates React node content by character count while preserving element structure. */ const truncateReactNodeByCharacters = (node, maxCharacters, shouldAddEllipsis = true) => { // Handle the case where node is an array (React children) const normalizedNode = Array.isArray(node) ? react_1.default.createElement(react_1.default.Fragment, null, ...node) : node; // Get the total character count first to determine if truncation is needed const totalLength = (0, exports.getTextContent)(normalizedNode).length; if (totalLength <= maxCharacters) { return { needsTruncation: false, truncatedContent: null }; } let charCount = 0; let hasReachedLimit = false; const truncateNode = (currentNode) => { // Stop processing if character limit is reached if (hasReachedLimit || charCount >= maxCharacters) { hasReachedLimit = true; return null; } // Handle arrays of children (mixed content case) if (Array.isArray(currentNode)) { const truncatedChildren = []; for (const child of currentNode) { if (hasReachedLimit || charCount >= maxCharacters) { break; } const truncatedChild = truncateNode(child); if (truncatedChild !== null) { truncatedChildren.push(truncatedChild); } } return truncatedChildren.length > 0 ? truncatedChildren : null; } if (typeof currentNode === 'string') { const availableChars = maxCharacters - charCount; if (currentNode.length <= availableChars) { charCount += currentNode.length; return currentNode; } // Truncate at character limit, preferring word boundaries let truncated = currentNode.substring(0, availableChars); const lastSpaceIndex = truncated.lastIndexOf(' '); if (lastSpaceIndex > availableChars * constants_1.ESTIMATION_FACTORS.WORD_BOUNDARY) { truncated = truncated.substring(0, lastSpaceIndex); } truncated = truncated.trim(); charCount += truncated.length; hasReachedLimit = true; return truncated; } if (typeof currentNode === 'number') { const str = currentNode.toString(); const availableChars = maxCharacters - charCount; if (str.length <= availableChars) { charCount += str.length; return currentNode; } const truncated = str.substring(0, availableChars); charCount += truncated.length; hasReachedLimit = true; return truncated; } if (!react_1.default.isValidElement(currentNode)) { return currentNode; } const { children } = currentNode.props; if (children === null || children === undefined) { return currentNode; } if (typeof children === 'string') { const truncatedChild = truncateNode(children); if (truncatedChild === null) { return null; } return react_1.default.cloneElement(currentNode, {}, truncatedChild); } if (Array.isArray(children)) { const truncatedChildren = []; for (const child of children) { if (hasReachedLimit || charCount >= maxCharacters) { break; } const truncatedChild = truncateNode(child); if (truncatedChild !== null) { truncatedChildren.push(truncatedChild); } } if (truncatedChildren.length === 0) { return null; } return react_1.default.cloneElement(currentNode, {}, ...truncatedChildren); } // Single React element child const truncatedChild = truncateNode(children); if (truncatedChild === null) { return null; } return react_1.default.cloneElement(currentNode, {}, truncatedChild); }; const truncatedResult = truncateNode(normalizedNode); // Convert array results to proper React elements const finalResult = Array.isArray(truncatedResult) ? react_1.default.createElement(react_1.default.Fragment, null, ...truncatedResult) : truncatedResult; // Add ellipsis if needed if (shouldAddEllipsis && finalResult !== null) { const withEllipsis = react_1.default.createElement(react_1.default.Fragment, null, finalResult, constants_1.ELLIPSIS_CHAR); return { needsTruncation: true, truncatedContent: withEllipsis }; } return { needsTruncation: true, truncatedContent: finalResult, }; }; exports.truncateReactNodeByCharacters = truncateReactNodeByCharacters; //# sourceMappingURL=text-overflow-utils.js.map