UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

194 lines (193 loc) 7.98 kB
import { _ as _define_property } from "@swc/helpers/_/_define_property"; import { _ as _object_spread } from "@swc/helpers/_/_object_spread"; import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props"; import { _ as _object_without_properties } from "@swc/helpers/_/_object_without_properties"; import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array"; import React, { useState, useRef } from "react"; import classNames from "classnames"; import { ComponentDefaults } from "../../utils/typings"; import { useIsomorphicLayoutEffect } from "../../hooks/use-isomprphic-layout-effect"; import { useRtl } from "../configprovider"; var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), { content: '', direction: 'end', rows: 1, expandText: '', collapseText: '', symbol: '...', lineHeight: '20' }); var classPrefix = "nut-ellipsis"; export var Ellipsis = function(props) { var _ellipsis_current, _ellipsis_current1; var _ref = _object_spread({}, defaultProps, props), children = _ref.children, content = _ref.content, className = _ref.className, direction = _ref.direction, rows = _ref.rows, expandText = _ref.expandText, collapseText = _ref.collapseText, symbol = _ref.symbol, lineHeight = _ref.lineHeight, onClick = _ref.onClick, onChange = _ref.onChange, rest = _object_without_properties(_ref, [ "children", "content", "className", "direction", "rows", "expandText", "collapseText", "symbol", "lineHeight", "onClick", "onChange" ]); var rtl = useRtl(); var container = null; var maxHeight = 0; var _useState = _sliced_to_array(useState(false), 2), exceeded = _useState[0], setExceeded = _useState[1]; var _useState1 = _sliced_to_array(useState(false), 2), expanded = _useState1[0], setExpanded = _useState1[1]; var ellipsis = useRef(); var root = useRef(null); var rtlClasses = classNames(_define_property({}, "".concat(classPrefix, "-rtl"), rtl)); var classes = classNames(classPrefix, rtlClasses, className); useIsomorphicLayoutEffect(function() { if (content) { createContainer(); } }, [ content ]); // 创建虚拟 container,内容为 contant 的内容 var createContainer = function() { if (!root.current) return; var originStyle = window.getComputedStyle(root.current); container = document.createElement('div'); var styleNames = Array.prototype.slice.apply(originStyle); styleNames.forEach(function(name) { container.style.setProperty(name, originStyle.getPropertyValue(name)); }); container.style.position = 'fixed'; container.style.left = '999999px'; container.style.top = '999999px'; container.style.zIndex = '-1000'; container.style.height = 'auto'; container.style.minHeight = 'auto'; container.style.maxHeight = 'auto'; container.style.textOverflow = 'clip'; container.style.whiteSpace = 'normal'; container.style.webkitLineClamp = 'unset'; container.style.display = 'block'; var lineH = pxToNumber(originStyle.lineHeight === 'normal' ? lineHeight : originStyle.lineHeight); maxHeight = Math.floor(lineH * (Number(rows) + 0.5) + pxToNumber(originStyle.paddingTop) + pxToNumber(originStyle.paddingBottom)); container.innerText = content; document.body.appendChild(container); calcEllipse(); document.body.removeChild(container); }; // 计算省略号的位置 var calcEllipse = function() { if (container.offsetHeight <= maxHeight) { setExceeded(false); } else { setExceeded(true); var end = content.length; var middle = Math.floor((0 + end) / 2); var ellipsised = direction === 'middle' ? tailorMiddle([ 0, middle ], [ middle, end ]) : tailor(0, end); ellipsis.current = ellipsised; } }; // 计算 start/end 省略 var tailor = function(left, right) { var actionText = expanded ? collapseText : expandText; var end = content.length; if (right - left <= 1) { if (direction === 'end') { return { leading: content.slice(0, left) + symbol }; } return { tailing: symbol + content.slice(right, end) }; } var middle = Math.round((left + right) / 2); if (direction === 'end') { container.innerText = content.slice(0, middle) + symbol + actionText; } else { container.innerText = actionText + symbol + content.slice(middle, end); } if (container.offsetHeight <= maxHeight) { if (direction === 'end') { return tailor(middle, right); } return tailor(left, middle); } if (direction === 'end') { return tailor(left, middle); } return tailor(middle, right); }; // 计算 middle 省略 var tailorMiddle = function(leftPart, rightPart) { var actionText = expanded ? collapseText : expandText; var end = content.length; if (leftPart[1] - leftPart[0] <= 1 && rightPart[1] - rightPart[0] <= 1) { return { leading: content.slice(0, leftPart[0]) + symbol, tailing: symbol + content.slice(rightPart[1], end) }; } var leftPartMiddle = Math.floor((leftPart[0] + leftPart[1]) / 2); var rightPartMiddle = Math.ceil((rightPart[0] + rightPart[1]) / 2); container.innerText = content.slice(0, leftPartMiddle) + symbol + actionText + symbol + content.slice(rightPartMiddle, end); if (container.offsetHeight <= maxHeight) { return tailorMiddle([ leftPartMiddle, leftPart[1] ], [ rightPart[0], rightPartMiddle ]); } return tailorMiddle([ leftPart[0], leftPartMiddle ], [ rightPartMiddle, rightPart[1] ]); }; var pxToNumber = function(value) { if (!value) return 0; var match = value.match(/^\d*(\.\d*)?/); return match ? Number(match[0]) : 0; }; var clickHandle = function(type) { if (type === 1) { setExpanded(true); onChange && onChange('expand'); } else { setExpanded(false); onChange && onChange('collapse'); } }; var handleClick = function() { onClick && onClick(); }; return /*#__PURE__*/ React.createElement("div", _object_spread({ className: classes, onClick: handleClick, ref: root }, rest), !exceeded ? content : null, exceeded && !expanded ? /*#__PURE__*/ React.createElement("span", null, (_ellipsis_current = ellipsis.current) === null || _ellipsis_current === void 0 ? void 0 : _ellipsis_current.leading, expandText ? /*#__PURE__*/ React.createElement("span", { className: "nut-ellipsis-text", onClick: function(e) { e.stopPropagation(); clickHandle(1); } }, expandText) : null, (_ellipsis_current1 = ellipsis.current) === null || _ellipsis_current1 === void 0 ? void 0 : _ellipsis_current1.tailing) : null, exceeded && expanded ? /*#__PURE__*/ React.createElement("span", null, content, expandText ? /*#__PURE__*/ React.createElement("span", { className: "nut-ellipsis-text", onClick: function(e) { e.stopPropagation(); clickHandle(2); } }, collapseText) : null) : null); }; Ellipsis.displayName = 'NutEllipsis';