UNPKG

@i-novus/ui-core

Version:

Базовые UI компоненты

119 lines (118 loc) 6.15 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { cloneElement, forwardRef, useLayoutEffect, useMemo, useRef, useState } from 'react'; import EllipsisComponent from 'react-ellipsis-component'; const isEllipsisExtended = (ellipsis) => { return typeof ellipsis === 'object' && ellipsis?.rows !== undefined; }; // eslint-disable-next-line sonarjs/cognitive-complexity export const Ellipsis = forwardRef((props, ref) => { const { tag: Tag = 'article', className, ellipsis, children, ...restProps } = props; const rowsMap = useMemo(() => { if (isEllipsisExtended(ellipsis) && ellipsis?.rows) { return { ["Expanded" /* ExpandState.Expanded */]: Number.MAX_SAFE_INTEGER, ["Shrinked" /* ExpandState.Shrinked */]: ellipsis.rows, ["NotVisible" /* ExpandState.NotVisible */]: ellipsis.rows, }; } return { ["Expanded" /* ExpandState.Expanded */]: Number.MAX_SAFE_INTEGER, ["Shrinked" /* ExpandState.Shrinked */]: 1, ["NotVisible" /* ExpandState.NotVisible */]: 1, }; }, [ellipsis]); const [expandState, setExpandState] = useState("NotVisible" /* ExpandState.NotVisible */); const htmlEllipsisRef = useRef(); const htmlNodeRowHeight = useMemo(() => { const DEFAULT_LINE_HEIGHT = 24; if (!htmlEllipsisRef.current) { return DEFAULT_LINE_HEIGHT; } const computedLineHeight = getComputedStyle(htmlEllipsisRef.current).getPropertyValue('line-height'); return computedLineHeight ? parseInt(computedLineHeight, 10) : DEFAULT_LINE_HEIGHT; }, []); useLayoutEffect(() => { if (typeof children !== 'string' && isEllipsisExtended(ellipsis) && htmlEllipsisRef.current) { const nodeHeight = htmlEllipsisRef.current.clientHeight; const computedNodeRowHeight = ellipsis?.rowHeight || htmlNodeRowHeight; const ellipsisContentHeight = ellipsis.rows * computedNodeRowHeight; if (nodeHeight > ellipsisContentHeight) { setExpandState("Shrinked" /* ExpandState.Shrinked */); } else { setExpandState("NotVisible" /* ExpandState.NotVisible */); } } // eslint-disable-next-line }, [htmlNodeRowHeight]); if (!ellipsis) { return ( // @ts-ignore _jsx(Tag, { ref: ref, className: className, ...restProps, children: children })); } // eslint-disable-next-line react/no-unstable-nested-components const ExpandLabel = ({ expandable, expandText = 'Развернуть', shrinkText = 'Свернуть' }) => { if (!expandable) { return null; } const onExpandLabelClick = () => setExpandState("Expanded" /* ExpandState.Expanded */); const onShrinkLabelClick = () => setExpandState("Shrinked" /* ExpandState.Shrinked */); if (expandState === "Shrinked" /* ExpandState.Shrinked */) { return (_jsx("i", { className: "expand-container", children: _jsx("span", { className: "expand-label", onClick: onExpandLabelClick, children: expandText }) })); } if (expandState === "Expanded" /* ExpandState.Expanded */) { return (_jsx("i", { className: "expand-container", children: _jsx("span", { className: "expand-label", onClick: onShrinkLabelClick, children: shrinkText }) })); } return null; }; if (typeof children !== 'string') { if (isEllipsisExtended(ellipsis)) { const computedNodeRowHeight = ellipsis?.rowHeight || htmlNodeRowHeight; const ellipsisContentHeight = ellipsis.rows * computedNodeRowHeight; return ( // @ts-ignore _jsxs(Tag, { ref: ref, className: className, ...restProps, children: [cloneElement(children, { ref: htmlEllipsisRef, style: { letterSpacing: 'normal', textRendering: 'auto', width: '100%', boxSizing: 'content-box', wordBreak: 'normal', whiteSpace: 'pre-wrap', minHeight: '0', maxHeight: 'none', display: 'block', visibility: 'hidden', overflow: 'hidden', position: 'absolute', zIndex: '-1000', top: '-1000px', right: '-1000px', pointerEvents: 'none', }, }), cloneElement(children, { style: { height: expandState === "Shrinked" /* ExpandState.Shrinked */ ? ellipsisContentHeight : 'auto', overflow: 'hidden', whiteSpace: 'pre-wrap', } }), _jsx(ExpandLabel, { ...ellipsis })] })); } return ( // @ts-ignore _jsx(Tag, { ref: ref, className: className, ...restProps, children: children })); } if (isEllipsisExtended(ellipsis)) { const onEllipsisCompute = (textTruncated) => { if (textTruncated) { setExpandState("Shrinked" /* ExpandState.Shrinked */); } }; return ( // @ts-ignore _jsxs(Tag, { ref: ref, className: className, ...restProps, children: [_jsx(EllipsisComponent, { text: children, maxLine: rowsMap[expandState], ellipsis: true, dangerouslyUseInnerHTML: true, reflowOnResize: true, onReflow: onEllipsisCompute }, expandState), _jsx(ExpandLabel, { ...ellipsis })] })); } return ( // @ts-ignore _jsx(Tag, { ref: ref, className: className, ...restProps, children: _jsx(EllipsisComponent, { text: children, maxLine: rowsMap[expandState], ellipsis: ellipsis, dangerouslyUseInnerHTML: true, reflowOnResize: true }, expandState) })); }); Ellipsis.displayName = 'Ellipsis';