@ohkit/text-ellipsis 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.es.js +1 -1
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +1 -1
- package/dist/index.modern.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
- package/src/index.tsx +6 -4
package/dist/index.es.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import t,{forwardRef as e,useState as n,useRef as o,useMemo as i,useCallback as r,useEffect as l}from"react";import{prefixClassname as a,classNames as s}from"@ohkit/prefix-classname";import{useSyncPropsState as d,useRuntime as f,useCompatibleEffect as c,assignRef as u}from"@ohkit/react-helper";import{isSafari as h}from"@ohkit/platform";import{rgbaToObj as g,findEffectiveBgColor as p}from"@ohkit/dom-helper";import{Measure as v}from"@ohkit/measure";function m(){return m=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var o in n)({}).hasOwnProperty.call(n,o)&&(t[o]=n[o])}return t},m.apply(null,arguments)}var C=a("ohkit-text-ellipsis__"),x=e(function(e,a){var x=e.className,b=e.style,w=e.lineHeight,F=void 0===w?"":w,H=e.lines,E=e.maskBgColor,y=e.resetFoldWhenChildrenOrEllipsisChange,k=void 0!==y&&y,S=e.showTitleWhenFold,M=e.titleWhenFold,O=e.showFoldControl,W=void 0===O||O,B=e.foldText,N=void 0===B?"收起":B,L=e.unfoldText,P=void 0===L?"展开":L,T=e.uiType,R=void 0===T?"right":T,z=e.truncateMode,j=void 0===z?"line":z,q=e.maxHeight,A=e.controlPlacement,_=void 0===A?"center":A,I=e.whiteSpace,V=e.width,D=e.renderFoldButton,G=e.onEllipsisChange,J=e.onFoldChange,K=e.onStatusChange,Q=e.onMouseEnter,U=e.onMouseLeave,X=e.onPointerEnter,Y=e.onPointerLeave,Z=e.onClick,$=e.onFocus,tt=e.content||e.children,et=n(!1),nt=et[0],ot=et[1],it=n(!1),rt=it[0],lt=it[1],at=d(e,"fold",{defaultValue:!0,onChange:J}),st=at[0],dt=at[1],ft=n(1),ct=ft[0],ut=ft[1],ht=n("string"==typeof F&&F.endsWith("px")?parseFloat(F):0),gt=ht[0],pt=ht[1],vt=n(H),mt=vt[0],Ct=void 0===mt?0:mt,xt=vt[1],bt=n(""),wt=bt[0],Ft=bt[1],Ht=f({inited:!1,contentOffsetHeight:0,containerContentHeight:0,ellipsis:nt,defaultFold:st,fold:st,foldBtnWidth:ct,textContent:wt,onEllipsisChange:G,onFoldChange:J,onStatusChange:K},["fold","onEllipsisChange","onFoldChange","onStatusChange"])[0],Et=o(null),yt=o(null),kt=o(null),St=o(null),Mt=i(function(){return m({lineHeight:rt?"1.4":F||void 0},b)},[b,F,rt]),Ot=i(function(){return{whiteSpace:I,width:V}},[I,V]),Wt=i(function(){var t="height"===j;if(!nt||!(t||Ct&>))return Ot;var e=W&&"bottom"===R&&!st?gt+"px":void 0;return m({},Ot,{minHeight:!t&&st?(Ct-.2)*gt+"px":void 0,WebkitLineClamp:t?void 0:st?Ct:void 0,maxHeight:t&&st?q||Ct*gt||Ht.containerContentHeight||0:void 0,paddingBottom:e,boxSizing:e?"border-box":void 0})},[Ct,gt,nt,st,W,R,j,q,Ot]),Bt=i(function(){if(!W||!nt)return null;var t=g(E||"")||p(kt.current),e=t.r,n=t.g,o=t.b;return{startColor:"rgba("+e+", "+n+", "+o+", 0.2)",endColor:"rgba("+e+", "+n+", "+o+", 1)"}},[E,nt,W]),Nt=i(function(){if(st){var t=gt,e="right"===R?Math.min(t/ct*100,80):60,n=Bt||{},o=n.startColor,i=n.endColor,r=void 0===i?"rgba(255,255,255,1)":i;return{boxSizing:"content-box",height:gt+"px",lineHeight:gt+"px",paddingTop:"bottom"===R?t+"px":void 0,paddingLeft:"right"===R?t+"px":void 0,background:"linear-gradient(to "+R+", "+(void 0===o?"rgba(255,255,255,0.2)":o)+", "+r+" "+e+"%, "+r+" 100%)"}}},[gt,st,R,ct,Bt]),Lt=r(function(){if(Et.current){var t=Et.current.style.width,e=window.getComputedStyle(Et.current).width;Et.current.style.width=parseFloat(e)-.1+"px",null==window.requestAnimationFrame||window.requestAnimationFrame(function(){Et.current&&(Et.current.style.width=t)})}},[]),Pt=r(function(t,e){void 0===e&&(e=!Ht.fold),Ht.fold=e,dt(e)},[]),Tt=i(function(){/*#__PURE__*/return t.createElement("div",{className:s("btn-fold-wrapper","btn-fold-wrapper-"+R,"bottom"===R&&"placement-"+_),style:Nt,ref:St,onClick:Pt},D?D(st):/*#__PURE__*/t.createElement("div",{className:"btn-fold"},st?P:N))},[Nt,st,N,Pt,D,_,R,P]),Rt=i(function(){return
|
|
1
|
+
import t,{forwardRef as e,useState as n,useRef as o,useMemo as i,useCallback as r,useEffect as l}from"react";import{prefixClassname as a,classNames as s}from"@ohkit/prefix-classname";import{useSyncPropsState as d,useRuntime as f,useCompatibleEffect as c,assignRef as u}from"@ohkit/react-helper";import{isSafari as h}from"@ohkit/platform";import{rgbaToObj as g,findEffectiveBgColor as p}from"@ohkit/dom-helper";import{Measure as v}from"@ohkit/measure";function m(){return m=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var o in n)({}).hasOwnProperty.call(n,o)&&(t[o]=n[o])}return t},m.apply(null,arguments)}var C=a("ohkit-text-ellipsis__"),x=e(function(e,a){var x=e.className,b=e.style,w=e.lineHeight,F=void 0===w?"":w,H=e.lines,E=e.maskBgColor,y=e.resetFoldWhenChildrenOrEllipsisChange,k=void 0!==y&&y,S=e.showTitleWhenFold,M=e.titleWhenFold,O=e.showFoldControl,W=void 0===O||O,B=e.foldText,N=void 0===B?"收起":B,L=e.unfoldText,P=void 0===L?"展开":L,T=e.uiType,R=void 0===T?"right":T,z=e.truncateMode,j=void 0===z?"line":z,q=e.maxHeight,A=e.controlPlacement,_=void 0===A?"center":A,I=e.whiteSpace,V=e.width,D=e.renderFoldButton,G=e.onEllipsisChange,J=e.onFoldChange,K=e.onStatusChange,Q=e.onMouseEnter,U=e.onMouseLeave,X=e.onPointerEnter,Y=e.onPointerLeave,Z=e.onClick,$=e.onFocus,tt=e.content||e.children,et=n(!1),nt=et[0],ot=et[1],it=n(!1),rt=it[0],lt=it[1],at=d(e,"fold",{defaultValue:!0,onChange:J}),st=at[0],dt=at[1],ft=n(1),ct=ft[0],ut=ft[1],ht=n("string"==typeof F&&F.endsWith("px")?parseFloat(F):0),gt=ht[0],pt=ht[1],vt=n(H),mt=vt[0],Ct=void 0===mt?0:mt,xt=vt[1],bt=n(""),wt=bt[0],Ft=bt[1],Ht=f({inited:!1,contentOffsetHeight:0,containerContentHeight:0,ellipsis:nt,defaultFold:st,fold:st,foldBtnWidth:ct,textContent:wt,onEllipsisChange:G,onFoldChange:J,onStatusChange:K},["fold","onEllipsisChange","onFoldChange","onStatusChange"])[0],Et=o(null),yt=o(null),kt=o(null),St=o(null),Mt=i(function(){return m({lineHeight:rt?"1.4":F||void 0},b)},[b,F,rt]),Ot=i(function(){return{whiteSpace:I,width:V}},[I,V]),Wt=i(function(){var t="height"===j;if(!nt||!(t||Ct&>))return Ot;var e=W&&"bottom"===R&&!st?gt+"px":void 0;return m({},Ot,{minHeight:!t&&st?(Ct-.2)*gt+"px":void 0,WebkitLineClamp:t?void 0:st?Ct:void 0,maxHeight:t&&st?q||Ct*gt||Ht.containerContentHeight||0:void 0,paddingBottom:e,boxSizing:e?"border-box":void 0})},[Ct,gt,nt,st,W,R,j,q,Ot]),Bt=i(function(){if(!W||!nt)return null;var t=g(E||"")||p(kt.current),e=t.r,n=t.g,o=t.b;return{startColor:"rgba("+e+", "+n+", "+o+", 0.2)",endColor:"rgba("+e+", "+n+", "+o+", 1)"}},[E,nt,W]),Nt=i(function(){if(st){var t=gt,e="right"===R?Math.min(t/ct*100,80):60,n=Bt||{},o=n.startColor,i=n.endColor,r=void 0===i?"rgba(255,255,255,1)":i;return{boxSizing:"content-box",height:gt+"px",lineHeight:gt+"px",paddingTop:"bottom"===R?t+"px":void 0,paddingLeft:"right"===R?t+"px":void 0,background:"linear-gradient(to "+R+", "+(void 0===o?"rgba(255,255,255,0.2)":o)+", "+r+" "+e+"%, "+r+" 100%)"}}},[gt,st,R,ct,Bt]),Lt=r(function(){if(Et.current){var t=Et.current.style.width,e=window.getComputedStyle(Et.current).width;Et.current.style.width=parseFloat(e)-.1+"px",null==window.requestAnimationFrame||window.requestAnimationFrame(function(){Et.current&&(Et.current.style.width=t)})}},[]),Pt=r(function(t,e){void 0===e&&(e=!Ht.fold),Ht.fold=e,dt(e)},[]),Tt=i(function(){/*#__PURE__*/return t.createElement("div",{className:s("btn-fold-wrapper","btn-fold-wrapper-"+R,"bottom"===R&&"placement-"+_),style:Nt,ref:St,onClick:Pt},D?D(st):/*#__PURE__*/t.createElement("div",{className:"btn-fold"},st?P:N))},[Nt,st,N,Pt,D,_,R,P]),Rt=i(function(){return nt&&W&&"right"===R&&!st?/*#__PURE__*/t.createElement("span",{style:Nt,className:"btn-fold-right-shadow"},D?D(st):N):null},[nt,R,W,st,Nt,N,D]),zt=r(function(t,e){void 0===t&&(t=Ht.ellipsis);var n=(void 0===e?{}:e).forceResetFold,o=void 0!==n&&n,i=Ht.ellipsis,r=Ht.fold,l=Ht.defaultFold;t!==i&&(ot(t),Ht.ellipsis=t,null==Ht.onEllipsisChange||Ht.onEllipsisChange(t)),k&&(o||!i&&t)&&r!==l&&Pt(void 0,l)},[Pt,tt,k]),jt=r(function(){var t=yt.current,e=kt.current;if(t&&e){Ht.contentOffsetHeight=t.offsetHeight;var n=window.getComputedStyle(e),o=parseFloat(n.paddingTop),i=parseFloat(n.paddingBottom),r=Ht.containerContentHeight=e.clientHeight-o-i,l=0;if(!l&&t){var a=(n||{}).lineHeight;a&&((l=parseFloat(a))||lt(!0))}if(gt===l||(pt(l),l))if("height"===j)zt(Ht.contentOffsetHeight>(q||r));else if(H)Ct!==H&&xt(H),zt(Ht.contentOffsetHeight>=(H+1)*Math.floor(l)-1);else if(Ht.contentOffsetHeight>r){var s=Math.floor(r/l)||1;Ct!==s&&xt(s),zt(!0)}else zt(!1)}},[H,gt,j,q,zt]);c(function(){zt(Ht.ellipsis,{forceResetFold:!0}),jt()},[jt,zt]),l(function(){if(nt&&St.current){var t=St.current.offsetWidth;t!==Ht.foldBtnWidth&&(Ht.foldBtnWidth=t,ut(t))}},[nt,P,W]),l(function(){h&&Lt()},[st,Lt]);var qt=r(function(){if(yt.current){var t=yt.current.textContent||"";t!==Ht.textContent&&(Ht.textContent=t,Ft(t))}},[]),At=r(function(t){var e=(t.offset||{}).height;void 0!==e&&Math.abs(e-Ht.contentOffsetHeight)>1&&jt()},[jt]),_t=i(function(){return nt&&st?"function"==typeof M?M(wt):M||wt:void 0},[M,nt,st,wt]);return l(function(){Ht.inited&&(null==Ht.onStatusChange||Ht.onStatusChange({ellipsis:nt,fold:st,title:_t}))},[st,nt,_t]),l(function(){Ht.inited=!0},[]),/*#__PURE__*/t.createElement("div",{className:s(C("container"),x),style:Mt,ref:function(t){u(kt,t),a&&u(a,t)},onMouseEnter:Q,onMouseLeave:U,onPointerEnter:X,onPointerLeave:Y,onClick:Z,onFocus:$},/*#__PURE__*/t.createElement(v,{offset:!0,throttleMs:100,onResize:At,triggerResizeInit:!1},function(e){var n=e.measureRef;/*#__PURE__*/return t.createElement("div",{style:Ot,className:"content-shadow-dom",ref:function(t){u(n,t),u(yt,t),qt()}},tt)}),/*#__PURE__*/t.createElement("div",{className:"text-ellipsis-inner",title:S?_t:void 0,style:Wt,ref:Et},nt&&W&&Tt,tt,Rt))});export{x as TextEllipsis,C as c};
|
|
2
2
|
//# sourceMappingURL=index.es.js.map
|
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @file 文本截断显示组件\n * @description 基于React封装一个文本截断显示组件,富文本(仅文字样式,图片和表格效果不一定好)同普通文本处理一致\n * @author <wuqiuyang305@126.com>\n */\n\nimport React, {\n forwardRef,\n useState,\n useMemo,\n useEffect,\n useCallback,\n useRef,\n PropsWithChildren,\n MouseEvent,\n} from \"react\";\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {\n assignRef,\n useRuntime,\n useCompatibleEffect,\n useSyncPropsState,\n} from \"@ohkit/react-helper\";\nimport {isSafari} from \"@ohkit/platform\";\nimport {rgbaToObj, findEffectiveBgColor} from \"@ohkit/dom-helper\";\nimport {Measure, MeasureProps} from \"@ohkit/measure\";\nimport \"./style.scss\";\n\nexport const c = p(\"ohkit-text-ellipsis__\");\n\ninterface ITextEllipsis\n extends Pick<\n React.DOMAttributes<HTMLDivElement>,\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onFocus\"\n | \"onClick\"\n > {\n /**\n * 自定义样式类名,会附加到根元素上\n */\n className?: string;\n /**\n * 自定义样式\n */\n style?: React.CSSProperties;\n /**\n * right | bottom 展开按钮在右下侧还是底部\n * @default right\n */\n uiType?: \"right\" | \"bottom\";\n /**\n * 截断模式 (若某些浏览器不支持 webkitLineClamp,可降级切换为 height 模式)\n * @default line\n */\n truncateMode?: \"line\" | \"height\";\n /**\n * truncateMode === \"height\" 时生效\n * 最大高度(number > 0),没传或者传入无效值不限制,尝试取 lines * lineHeight,若仍无效 自动截断到容器的最大高度\n * 单位: px\n */\n maxHeight?: number;\n /**\n * (单位:px)未传入或无效(0也视为无效)则自动取当前文本的行高\n */\n lineHeight?: React.CSSProperties[\"lineHeight\"];\n /**\n * truncateMode === \"line\" 时生效\n * 超过几行折叠(number > 0), 没传或者传入无效值不限制,自动截断到容器的最大高度\n */\n lines?: number;\n /**\n * 展开按钮蒙层背景色(仅支持16进制表示)\n * @default #fff\n */\n maskBgColor?: string;\n /**\n * text|ReactNode 与children任传一个\n */\n content?: React.ReactNode;\n /**\n * 当 content or children or ellipsis 变化时,重置 fold 状态 \n * @default false\n */\n resetFoldWhenChildrenOrEllipsisChange?: boolean;\n /**\n * 折叠状态\n * @default true\n */\n fold?: boolean;\n /**\n * 显示展开控制按钮\n * @default true\n */\n showFoldControl?: boolean;\n /**\n * 展开按钮位置 uiType='bottom'时有效\n * @default center\n */\n controlPlacement?: 'left' | 'center' | 'right';\n /**\n * 折叠按钮文字\n * @default 收起\n */\n foldText?: string;\n /**\n * 展开按钮文字\n * @default 展开\n */\n unfoldText?: string;\n /**\n * 折叠状态下是否显示title属性\n * @default false\n */\n showTitleWhenFold?: boolean;\n /**\n * 折叠状态自定义title属性内容\n */\n titleWhenFold?: string | ((title: string) => string);\n /**\n * 是否保留换行\n */\n whiteSpace?: React.CSSProperties['whiteSpace'];\n /**\n * 容器宽度(默认自适应内容)\n * 应用场景:whiteSpace='pre*' 时,支持展示换行符,自适应内容可能导致控制按钮位置不确定\n */\n width?: React.CSSProperties['width'];\n /**\n * 自定义渲染展开按钮\n */\n renderFoldButton?: (fold: boolean) => React.ReactNode;\n /**\n * @param fold 折叠状态,true 折叠,false 展开\n */\n onFoldChange?: (fold: boolean) => void;\n /**\n * @param ellipsis 是否截断,true 截断,false 未截断\n */\n onEllipsisChange?: (ellipsis: boolean) => void;\n /**\n * 关键状态变更触发\n * @param status\n */\n onStatusChange?: (status: {\n fold: boolean;\n ellipsis: boolean;\n title?: string;\n }) => void;\n}\n\nexport type TextEllipsisProps = PropsWithChildren<ITextEllipsis>;\n\nexport const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>((props, ref) => {\n const {\n className,\n style,\n lineHeight = \"\",\n lines,\n maskBgColor,\n content,\n children,\n resetFoldWhenChildrenOrEllipsisChange = false,\n showTitleWhenFold,\n titleWhenFold,\n showFoldControl = true,\n foldText = \"收起\",\n unfoldText = \"展开\",\n uiType = \"right\",\n truncateMode = \"line\",\n maxHeight,\n controlPlacement = 'center',\n whiteSpace,\n width,\n renderFoldButton,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n onMouseEnter,\n onMouseLeave,\n onPointerEnter,\n onPointerLeave,\n onClick,\n onFocus,\n } = props;\n const finalContent = content || children;\n // 是否截断\n const [ellipsis, setEllipsis] = useState(false);\n const [getLineHeightFail, setGetLineHeightFail] = useState(false);\n // 折叠状态\n const [fold, setFold] = useSyncPropsState(props, 'fold', {defaultValue: true, onChange: onFoldChange});\n const [foldBtnWidth, setFoldBtnWidth] = useState(1);\n const [innerLineHeight, setInnerLineHeight] = useState(\n typeof lineHeight === \"string\" && lineHeight.endsWith(\"px\")\n ? parseFloat(lineHeight)\n : 0\n );\n const [innerLines = 0, setInnerLines] = useState(lines);\n // children提取的纯文本\n const [textContent, setTextContent] = useState('');\n\n const [runtime] = useRuntime({\n inited: false, // mounted\n contentOffsetHeight: 0, // 内容节点offsetHeight\n containerContentHeight: 0, // 容器内容高度 = 容器高 - 上下padding\n ellipsis,\n defaultFold: fold, // 记录一下默认的折叠状态,用于 reset fold\n fold,\n foldBtnWidth,\n textContent,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n }, ['fold', 'onEllipsisChange', 'onFoldChange', 'onStatusChange']);\n\n const contentRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const btnWrapperRef = useRef<HTMLDivElement>(null);\n\n const containerStyle = useMemo(() => {\n return {\n lineHeight: getLineHeightFail // 未传入且获取 lineHeight(px) 失败,则设置 default lineHeight: 1.4(em)\n ? \"1.4\" // more brower normal default lineHeight\n : lineHeight ? lineHeight : undefined,\n ...style,\n };\n }, [style, lineHeight, getLineHeightFail]);\n\n const commonWrapStyle = useMemo(() => {\n return {\n whiteSpace,\n width,\n };\n }, [whiteSpace, width]);\n // 容器样式\n const wrapStyle = useMemo(() => {\n const lines = innerLines;\n const isHeightMode = truncateMode === 'height';\n if (!ellipsis || !isHeightMode && (!lines || !innerLineHeight)) {\n return commonWrapStyle;\n }\n const paddingBottom = showFoldControl && (uiType === \"bottom\" && !fold) ? `${innerLineHeight}px` : undefined;\n return {\n ...commonWrapStyle,\n // HACK: 兼容safari 15+ 富文本折叠高度丢失问题\n minHeight: !isHeightMode && fold ? `${(lines - 0.2) * innerLineHeight}px` : undefined,\n // Note: safari 对WebkitLineClamp支持太差劲 判断浏览器优雅降级为高度截断方案?目前先交给用户去判断,自行选择truncateMode\n // WebkitLineClamp: isSafari ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n // maxHeight: isSafari && fold ? lines * innerLineHeight : undefined,\n WebkitLineClamp: isHeightMode ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n maxHeight: isHeightMode && fold ? (maxHeight || lines * innerLineHeight || runtime.containerContentHeight || 0) : undefined,\n paddingBottom,\n boxSizing: paddingBottom ? 'border-box' as const : undefined,\n };\n }, [innerLines, innerLineHeight, ellipsis, fold, showFoldControl, uiType, truncateMode, maxHeight, commonWrapStyle]);\n\n // 计算折叠按钮蒙层的渐变颜色\n const validMaskBgColor = useMemo(() => {\n if (!showFoldControl || !ellipsis) {\n return null;\n }\n const {r, g, b} = rgbaToObj(maskBgColor || '') || findEffectiveBgColor(containerRef.current);\n return {\n startColor: `rgba(${r}, ${g}, ${b}, 0.2)`,\n endColor: `rgba(${r}, ${g}, ${b}, 1)`,\n };\n }, [maskBgColor, ellipsis, showFoldControl]);\n\n // 展开|收起 按钮样式\n const btnStyle = useMemo(() => {\n if (!fold) {\n return;\n }\n // 按钮padding,取行高\n const padding = innerLineHeight;\n // 蒙层透明度所占比例\n const ratio = uiType === \"right\" ? Math.min((padding / foldBtnWidth) * 100, 80) : 60;\n const {startColor = 'rgba(255,255,255,0.2)', endColor = 'rgba(255,255,255,1)'} = validMaskBgColor || {};\n return {\n boxSizing: 'content-box' as const,\n height: `${innerLineHeight}px`,\n lineHeight: `${innerLineHeight}px`,\n paddingTop: uiType === \"bottom\" ? `${padding}px` : undefined,\n paddingLeft: uiType === \"right\" ? `${padding}px` : undefined,\n // 渐变蒙层\n background: `linear-gradient(to ${uiType}, ${startColor}, ${endColor} ${ratio}%, ${endColor} 100%)`,\n };\n }, [innerLineHeight, fold, uiType, foldBtnWidth, validMaskBgColor]);\n\n const reorganizeDom = useCallback(() => {\n // Note: safari 中仅改变 WebkitLineClamp 没触发重排,调整微小宽度以触发\n if (contentRef.current) {\n const orginStyleWidth = contentRef.current.style.width;\n const orginWidth = window.getComputedStyle(contentRef.current).width;\n // console.log('orginWidth, orginStyleWidth:', orginWidth, orginStyleWidth);\n contentRef.current.style.width = `${parseFloat(orginWidth) - 0.1}px`;\n window.requestAnimationFrame?.(() => {\n if (contentRef.current) {\n contentRef.current.style.width = orginStyleWidth;\n }\n });\n }\n }, []);\n\n const handleFoldChange = useCallback(\n (evt?: MouseEvent<HTMLDivElement>, fold = !runtime.fold) => {\n runtime.fold = fold;\n setFold(fold);\n }, []);\n\n const ButtonComp = useMemo(() => {\n return (\n <div\n className={cx(\n \"btn-fold-wrapper\",\n `btn-fold-wrapper-${uiType}`,\n uiType === \"bottom\" && `placement-${controlPlacement}`\n )}\n style={btnStyle}\n ref={btnWrapperRef}\n onClick={handleFoldChange}\n >\n {renderFoldButton ? (\n renderFoldButton(fold)\n ) : (\n <div className={\"btn-fold\"}>{fold ? unfoldText : foldText}</div>\n )}\n </div>\n );\n }, [\n btnStyle,\n fold,\n foldText,\n handleFoldChange,\n renderFoldButton,\n controlPlacement,\n uiType,\n unfoldText,\n ]);\n\n // 占位按钮\n const ButtonShadowDom = useMemo(() => {\n if (!showFoldControl || uiType !== 'right' || fold) {\n return null;\n }\n return <span style={btnStyle} className=\"btn-fold-right-shadow\">\n {renderFoldButton ? renderFoldButton(fold) : foldText}\n </span>;\n }, [uiType, showFoldControl, fold, btnStyle, foldText, renderFoldButton]);\n\n // 重置状态\n const resetState = useCallback((newEllipsis = runtime.ellipsis, {\n forceResetFold = false, // 强制重置fold 比如child变化时\n } = {}) => {\n const {ellipsis, fold: preFold, defaultFold} = runtime;\n if (newEllipsis !== ellipsis) {\n setEllipsis(newEllipsis);\n runtime.ellipsis = newEllipsis;\n runtime.onEllipsisChange?.(newEllipsis);\n }\n // 从未截断状态切换为截断状态时,自动折叠(即:出现展开按钮)\n if (\n resetFoldWhenChildrenOrEllipsisChange\n && (forceResetFold || !ellipsis && newEllipsis)\n && preFold !== defaultFold\n ) {\n handleFoldChange(undefined, defaultFold);\n }\n }, [handleFoldChange, finalContent, resetFoldWhenChildrenOrEllipsisChange]);\n\n const calcEllipsis = useCallback(() => {\n const wrapDom = wrapperRef.current;\n const containerDom = containerRef.current;\n if (!wrapDom || !containerDom) {\n return;\n }\n runtime.contentOffsetHeight = wrapDom.offsetHeight;\n const containerStyle = window.getComputedStyle(containerDom);\n const paddingTop = parseFloat(containerStyle.paddingTop);\n const paddingBottom = parseFloat(containerStyle.paddingBottom);\n const containerContentHeight = runtime.containerContentHeight = containerDom.clientHeight - paddingTop - paddingBottom;\n\n // 计算真实行高\n let realLineHeight = 0;\n // 若外部未传入, 尝试读取当前文本的行高。\n if (!realLineHeight && wrapDom) {\n const {lineHeight} = containerStyle || {};\n if (lineHeight) {\n // 未设置行高的为 normal\n realLineHeight = parseFloat(lineHeight);\n if (!realLineHeight) {\n setGetLineHeightFail(true);\n }\n }\n }\n // lineHeight同步到innerLineHeight\n if (innerLineHeight !== realLineHeight) {\n setInnerLineHeight(realLineHeight);\n if (!realLineHeight) {\n return;\n }\n }\n\n const isHeightMode = truncateMode === 'height';\n // 高度截断模式,比较简单 直接判断是否超出容器高度\n if (isHeightMode) {\n resetState(runtime.contentOffsetHeight > (maxHeight || containerContentHeight));\n return;\n }\n\n // 行数截断模式,需要利用行高计算是否超出容器高度\n if (!lines) {\n if (runtime.contentOffsetHeight > containerContentHeight) {\n const adjustLines = Math.floor(containerContentHeight / realLineHeight) || 1;\n if (innerLines !== adjustLines) {\n setInnerLines(adjustLines);\n }\n resetState(true);\n } else {\n resetState(false);\n }\n } else {\n if (innerLines !== lines) {\n setInnerLines(lines);\n }\n // console.log('contentOffsetHeight, realLineHeight', runtime.contentOffsetHeight, realLineHeight);\n // 允许误差1px(行高为小数时, safari计算行高*行数和实践总高有差异,故将行高向下取整兼容)\n resetState(runtime.contentOffsetHeight >= (lines + 1) * Math.floor(realLineHeight) - 1);\n }\n }, [lines, innerLineHeight, truncateMode, maxHeight, resetState]);\n\n // 监听内容高度,是否需要折叠\n // 用useLayoutEffect方式闪屏显示\n useCompatibleEffect(() => {\n resetState(runtime.ellipsis, {\n forceResetFold: true,\n });\n calcEllipsis();\n }, [calcEllipsis, resetState]);\n\n // 监听\"展开\"按钮宽度变化\n useEffect(() => {\n if (ellipsis && btnWrapperRef.current) {\n const {offsetWidth} = btnWrapperRef.current;\n if (offsetWidth !== runtime.foldBtnWidth) {\n runtime.foldBtnWidth = offsetWidth;\n setFoldBtnWidth(offsetWidth);\n }\n }\n }, [ellipsis, unfoldText, showFoldControl]);\n useEffect(() => {\n if (isSafari) {\n reorganizeDom();\n }\n }, [fold, reorganizeDom]);\n const updateTextContent = useCallback(() => {\n if (!wrapperRef.current) {\n return;\n }\n const newTextContent = wrapperRef.current.textContent || '';\n if (newTextContent !== runtime.textContent) {\n runtime.textContent = newTextContent;\n setTextContent(newTextContent);\n }\n }, []);\n const handleResize = useCallback<NonNullable<MeasureProps['onResize']>>((rect) => {\n // console.log('[handleResize] rect: ', rect, runtime.contentOffsetHeight);\n const {height} = rect.offset || {};\n if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n calcEllipsis();\n }\n }, [calcEllipsis]);\n const hoverTitle = useMemo(() => {\n return ellipsis && fold\n ? (typeof titleWhenFold === 'function'\n ? titleWhenFold(textContent)\n : titleWhenFold || textContent)\n : undefined;\n }, [titleWhenFold, ellipsis, fold, textContent]);\n useEffect(() => {\n if (runtime.inited) { \n runtime.onStatusChange?.({\n ellipsis,\n fold,\n title: hoverTitle\n });\n }\n }, [fold, ellipsis, hoverTitle]);\n useEffect(() => {\n runtime.inited = true;\n }, []);\n // 高度自适应,容器高度变化时重新计算高度(容器也需要包装Measure,TODO: 待开发 hooks -> useMeasure, 使得观测dom尺寸的方式更简洁)\n // if (!maxHeight && !lines) {\n // calcEllipsis();\n // }\n // console.log('[render TextEllipsis]: ellipsis fold wrapStyle: ', ellipsis, fold, wrapStyle);\n return (\n <div\n className={cx(c(\"container\"), className)}\n style={containerStyle}\n ref={(r) => {\n assignRef(containerRef, r);\n ref && assignRef(ref, r);\n }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onPointerEnter={onPointerEnter}\n onPointerLeave={onPointerLeave}\n onClick={onClick}\n onFocus={onFocus}\n >\n {/* 此dom仅用于计算高度 用.text-ellipsis-inner计算 在不重新初始化情况下切换文本时高度计算有问题 */}\n <Measure offset throttleMs={100} onResize={handleResize} triggerResizeInit={false}>\n {({measureRef, /* contentRect */}) => {\n // console.log('contentRect:', contentRect, contentRect.offset?.height, runtime.contentOffsetHeight);\n // const {height} = contentRect.offset || {};\n // if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n // calcEllipsis();\n // }\n return <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={(r) => {\n assignRef(measureRef, r);\n assignRef(wrapperRef, r);\n updateTextContent();\n }}>\n {finalContent}\n </div>\n }}\n </Measure>\n {/* <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={wrapperRef}>\n {finalContent}\n </div> */}\n {/* 主文本显示 */}\n <div\n className={\"text-ellipsis-inner\"}\n title={showTitleWhenFold ? hoverTitle : undefined}\n style={wrapStyle}\n ref={contentRef}\n >\n {/* {finalContent} */}\n {/* firefox >= 133 绝对定位的按钮放文本后面也会被截断隐藏!! , 放文本前面可解决 */}\n {ellipsis && showFoldControl && ButtonComp}\n {finalContent}\n {ButtonShadowDom}\n </div>\n </div>\n );\n});\n"],"names":["c","p","TextEllipsis","forwardRef","props","ref","className","style","_props$lineHeight","lineHeight","lines","maskBgColor","_props$resetFoldWhenC","resetFoldWhenChildrenOrEllipsisChange","showTitleWhenFold","titleWhenFold","_props$showFoldContro","showFoldControl","_props$foldText","foldText","_props$unfoldText","unfoldText","_props$uiType","uiType","_props$truncateMode","truncateMode","maxHeight","_props$controlPlaceme","controlPlacement","whiteSpace","width","renderFoldButton","onEllipsisChange","onFoldChange","onStatusChange","onMouseEnter","onMouseLeave","onPointerEnter","onPointerLeave","onClick","onFocus","finalContent","content","children","_useState","useState","ellipsis","setEllipsis","_useState2","getLineHeightFail","setGetLineHeightFail","_useSyncPropsState","useSyncPropsState","defaultValue","onChange","fold","setFold","_useState3","foldBtnWidth","setFoldBtnWidth","_useState4","endsWith","parseFloat","innerLineHeight","setInnerLineHeight","_useState5","_useState5$","innerLines","setInnerLines","_useState6","textContent","setTextContent","runtime","useRuntime","inited","contentOffsetHeight","containerContentHeight","defaultFold","contentRef","useRef","wrapperRef","containerRef","btnWrapperRef","containerStyle","useMemo","_extends","undefined","commonWrapStyle","wrapStyle","isHeightMode","paddingBottom","minHeight","WebkitLineClamp","boxSizing","validMaskBgColor","_ref","rgbaToObj","findEffectiveBgColor","current","r","g","b","startColor","endColor","btnStyle","padding","ratio","Math","min","_ref2","_ref2$startColor","_ref2$endColor","height","paddingTop","paddingLeft","background","reorganizeDom","useCallback","orginStyleWidth","orginWidth","window","getComputedStyle","requestAnimationFrame","handleFoldChange","evt","ButtonComp","React","createElement","cx","ButtonShadowDom","resetState","newEllipsis","_temp","_ref3$forceResetFold","forceResetFold","preFold","calcEllipsis","wrapDom","containerDom","offsetHeight","clientHeight","realLineHeight","floor","adjustLines","useCompatibleEffect","useEffect","offsetWidth","isSafari","updateTextContent","newTextContent","handleResize","rect","offset","abs","hoverTitle","title","assignRef","Measure","throttleMs","onResize","triggerResizeInit","_ref6","measureRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @file 文本截断显示组件\n * @description 基于React封装一个文本截断显示组件,富文本(仅文字样式,图片和表格效果不一定好)同普通文本处理一致\n * @author <wuqiuyang305@126.com>\n */\n\nimport React, {\n forwardRef,\n useState,\n useMemo,\n useEffect,\n useCallback,\n useRef,\n PropsWithChildren,\n MouseEvent,\n} from \"react\";\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {\n assignRef,\n useRuntime,\n useCompatibleEffect,\n useSyncPropsState,\n} from \"@ohkit/react-helper\";\nimport {isSafari} from \"@ohkit/platform\";\nimport {rgbaToObj, findEffectiveBgColor} from \"@ohkit/dom-helper\";\nimport {Measure, MeasureProps} from \"@ohkit/measure\";\nimport \"./style.scss\";\n\nexport const c = p(\"ohkit-text-ellipsis__\");\n\ninterface ITextEllipsis\n extends Pick<\n React.DOMAttributes<HTMLDivElement>,\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onFocus\"\n | \"onClick\"\n > {\n /**\n * 自定义样式类名,会附加到根元素上\n */\n className?: string;\n /**\n * 自定义样式\n */\n style?: React.CSSProperties;\n /**\n * right | bottom 展开按钮在右下侧还是底部\n * @default right\n */\n uiType?: \"right\" | \"bottom\";\n /**\n * 截断模式 (若某些浏览器不支持 webkitLineClamp,可降级切换为 height 模式)\n * @default line\n */\n truncateMode?: \"line\" | \"height\";\n /**\n * truncateMode === \"height\" 时生效\n * 最大高度(number > 0),没传或者传入无效值不限制,尝试取 lines * lineHeight,若仍无效 自动截断到容器的最大高度\n * 单位: px\n */\n maxHeight?: number;\n /**\n * (单位:px)未传入或无效(0也视为无效)则自动取当前文本的行高\n */\n lineHeight?: React.CSSProperties[\"lineHeight\"];\n /**\n * truncateMode === \"line\" 时生效\n * 超过几行折叠(number > 0), 没传或者传入无效值不限制,自动截断到容器的最大高度\n */\n lines?: number;\n /**\n * 展开按钮蒙层背景色(仅支持16进制表示)\n * @default #fff\n */\n maskBgColor?: string;\n /**\n * text|ReactNode 与children任传一个\n */\n content?: React.ReactNode;\n /**\n * 当 content or children or ellipsis 变化时,重置 fold 状态 \n * @default false\n */\n resetFoldWhenChildrenOrEllipsisChange?: boolean;\n /**\n * 折叠状态\n * @default true\n */\n fold?: boolean;\n /**\n * 显示展开控制按钮\n * @default true\n */\n showFoldControl?: boolean;\n /**\n * 展开按钮位置 uiType='bottom'时有效\n * @default center\n */\n controlPlacement?: 'left' | 'center' | 'right';\n /**\n * 折叠按钮文字\n * @default 收起\n */\n foldText?: string;\n /**\n * 展开按钮文字\n * @default 展开\n */\n unfoldText?: string;\n /**\n * 折叠状态下是否显示title属性\n * @default false\n */\n showTitleWhenFold?: boolean;\n /**\n * 折叠状态自定义title属性内容\n */\n titleWhenFold?: string | ((title: string) => string);\n /**\n * 是否保留换行\n */\n whiteSpace?: React.CSSProperties['whiteSpace'];\n /**\n * 容器宽度(默认自适应内容)\n * 应用场景:whiteSpace='pre*' 时,支持展示换行符,自适应内容可能导致控制按钮位置不确定\n */\n width?: React.CSSProperties['width'];\n /**\n * 自定义渲染展开按钮\n */\n renderFoldButton?: (fold: boolean) => React.ReactNode;\n /**\n * @param fold 折叠状态,true 折叠,false 展开\n */\n onFoldChange?: (fold: boolean) => void;\n /**\n * @param ellipsis 是否截断,true 截断,false 未截断\n */\n onEllipsisChange?: (ellipsis: boolean) => void;\n /**\n * 关键状态变更触发\n * @param status\n */\n onStatusChange?: (status: {\n fold: boolean;\n ellipsis: boolean;\n title?: string;\n }) => void;\n}\n\nexport type TextEllipsisProps = PropsWithChildren<ITextEllipsis>;\n\nexport const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>(function TextEllipsis(props, ref) {\n const {\n className,\n style,\n lineHeight = \"\",\n lines,\n maskBgColor,\n content,\n children,\n resetFoldWhenChildrenOrEllipsisChange = false,\n showTitleWhenFold,\n titleWhenFold,\n showFoldControl = true,\n foldText = \"收起\",\n unfoldText = \"展开\",\n uiType = \"right\",\n truncateMode = \"line\",\n maxHeight,\n controlPlacement = 'center',\n whiteSpace,\n width,\n renderFoldButton,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n onMouseEnter,\n onMouseLeave,\n onPointerEnter,\n onPointerLeave,\n onClick,\n onFocus,\n } = props;\n const finalContent = content || children;\n // 是否截断\n const [ellipsis, setEllipsis] = useState(false);\n const [getLineHeightFail, setGetLineHeightFail] = useState(false);\n // 折叠状态\n const [fold, setFold] = useSyncPropsState(props, 'fold', {defaultValue: true, onChange: onFoldChange});\n const [foldBtnWidth, setFoldBtnWidth] = useState(1);\n const [innerLineHeight, setInnerLineHeight] = useState(\n typeof lineHeight === \"string\" && lineHeight.endsWith(\"px\")\n ? parseFloat(lineHeight)\n : 0\n );\n const [innerLines = 0, setInnerLines] = useState(lines);\n // children提取的纯文本\n const [textContent, setTextContent] = useState('');\n\n const [runtime] = useRuntime({\n inited: false, // mounted\n contentOffsetHeight: 0, // 内容节点offsetHeight\n containerContentHeight: 0, // 容器内容高度 = 容器高 - 上下padding\n ellipsis,\n defaultFold: fold, // 记录一下默认的折叠状态,用于 reset fold\n fold,\n foldBtnWidth,\n textContent,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n }, ['fold', 'onEllipsisChange', 'onFoldChange', 'onStatusChange']);\n\n const contentRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const btnWrapperRef = useRef<HTMLDivElement>(null);\n\n const containerStyle = useMemo(() => {\n return {\n lineHeight: getLineHeightFail // 未传入且获取 lineHeight(px) 失败,则设置 default lineHeight: 1.4(em)\n ? \"1.4\" // more brower normal default lineHeight\n : lineHeight ? lineHeight : undefined,\n ...style,\n };\n }, [style, lineHeight, getLineHeightFail]);\n\n const commonWrapStyle = useMemo(() => {\n return {\n whiteSpace,\n width,\n };\n }, [whiteSpace, width]);\n // 容器样式\n const wrapStyle = useMemo(() => {\n const lines = innerLines;\n const isHeightMode = truncateMode === 'height';\n if (!ellipsis || !isHeightMode && (!lines || !innerLineHeight)) {\n return commonWrapStyle;\n }\n const paddingBottom = showFoldControl && (uiType === \"bottom\" && !fold) ? `${innerLineHeight}px` : undefined;\n return {\n ...commonWrapStyle,\n // HACK: 兼容safari 15+ 富文本折叠高度丢失问题\n minHeight: !isHeightMode && fold ? `${(lines - 0.2) * innerLineHeight}px` : undefined,\n // Note: safari 对WebkitLineClamp支持太差劲 判断浏览器优雅降级为高度截断方案?目前先交给用户去判断,自行选择truncateMode\n // WebkitLineClamp: isSafari ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n // maxHeight: isSafari && fold ? lines * innerLineHeight : undefined,\n WebkitLineClamp: isHeightMode ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n maxHeight: isHeightMode && fold ? (maxHeight || lines * innerLineHeight || runtime.containerContentHeight || 0) : undefined,\n paddingBottom,\n boxSizing: paddingBottom ? 'border-box' as const : undefined,\n };\n }, [innerLines, innerLineHeight, ellipsis, fold, showFoldControl, uiType, truncateMode, maxHeight, commonWrapStyle]);\n\n // 计算折叠按钮蒙层的渐变颜色\n const validMaskBgColor = useMemo(() => {\n if (!showFoldControl || !ellipsis) {\n return null;\n }\n const {r, g, b} = rgbaToObj(maskBgColor || '') || findEffectiveBgColor(containerRef.current);\n return {\n startColor: `rgba(${r}, ${g}, ${b}, 0.2)`,\n endColor: `rgba(${r}, ${g}, ${b}, 1)`,\n };\n }, [maskBgColor, ellipsis, showFoldControl]);\n\n // 展开|收起 按钮样式\n const btnStyle = useMemo(() => {\n if (!fold) {\n return;\n }\n // 按钮padding,取行高\n const padding = innerLineHeight;\n // 蒙层透明度所占比例\n const ratio = uiType === \"right\" ? Math.min((padding / foldBtnWidth) * 100, 80) : 60;\n const {startColor = 'rgba(255,255,255,0.2)', endColor = 'rgba(255,255,255,1)'} = validMaskBgColor || {};\n return {\n boxSizing: 'content-box' as const,\n height: `${innerLineHeight}px`,\n lineHeight: `${innerLineHeight}px`,\n paddingTop: uiType === \"bottom\" ? `${padding}px` : undefined,\n paddingLeft: uiType === \"right\" ? `${padding}px` : undefined,\n // 渐变蒙层\n background: `linear-gradient(to ${uiType}, ${startColor}, ${endColor} ${ratio}%, ${endColor} 100%)`,\n };\n }, [innerLineHeight, fold, uiType, foldBtnWidth, validMaskBgColor]);\n\n const reorganizeDom = useCallback(() => {\n // Note: safari 中仅改变 WebkitLineClamp 没触发重排,调整微小宽度以触发\n if (contentRef.current) {\n const orginStyleWidth = contentRef.current.style.width;\n const orginWidth = window.getComputedStyle(contentRef.current).width;\n // console.log('orginWidth, orginStyleWidth:', orginWidth, orginStyleWidth);\n contentRef.current.style.width = `${parseFloat(orginWidth) - 0.1}px`;\n window.requestAnimationFrame?.(() => {\n if (contentRef.current) {\n contentRef.current.style.width = orginStyleWidth;\n }\n });\n }\n }, []);\n\n const handleFoldChange = useCallback(\n (evt?: MouseEvent<HTMLDivElement>, fold = !runtime.fold) => {\n runtime.fold = fold;\n setFold(fold);\n }, []);\n\n const ButtonComp = useMemo(() => {\n return (\n <div\n className={cx(\n \"btn-fold-wrapper\",\n `btn-fold-wrapper-${uiType}`,\n uiType === \"bottom\" && `placement-${controlPlacement}`\n )}\n style={btnStyle}\n ref={btnWrapperRef}\n onClick={handleFoldChange}\n >\n {renderFoldButton ? (\n renderFoldButton(fold)\n ) : (\n <div className={\"btn-fold\"}>{fold ? unfoldText : foldText}</div>\n )}\n </div>\n );\n }, [\n btnStyle,\n fold,\n foldText,\n handleFoldChange,\n renderFoldButton,\n controlPlacement,\n uiType,\n unfoldText,\n ]);\n\n // 占位按钮\n const ButtonShadowDom = useMemo(() => {\n if (!ellipsis || !showFoldControl || uiType !== 'right' || fold) {\n return null;\n }\n return <span style={btnStyle} className=\"btn-fold-right-shadow\">\n {renderFoldButton ? renderFoldButton(fold) : foldText}\n </span>;\n }, [ellipsis, uiType, showFoldControl, fold, btnStyle, foldText, renderFoldButton]);\n\n // 重置状态\n const resetState = useCallback((newEllipsis = runtime.ellipsis, {\n forceResetFold = false, // 强制重置fold 比如child变化时\n } = {}) => {\n const {ellipsis, fold: preFold, defaultFold} = runtime;\n if (newEllipsis !== ellipsis) {\n setEllipsis(newEllipsis);\n runtime.ellipsis = newEllipsis;\n runtime.onEllipsisChange?.(newEllipsis);\n }\n // 从未截断状态切换为截断状态时,自动折叠(即:出现展开按钮)\n if (\n resetFoldWhenChildrenOrEllipsisChange\n && (forceResetFold || !ellipsis && newEllipsis)\n && preFold !== defaultFold\n ) {\n handleFoldChange(undefined, defaultFold);\n }\n }, [handleFoldChange, finalContent, resetFoldWhenChildrenOrEllipsisChange]);\n\n const calcEllipsis = useCallback(() => {\n const wrapDom = wrapperRef.current;\n const containerDom = containerRef.current;\n if (!wrapDom || !containerDom) {\n return;\n }\n runtime.contentOffsetHeight = wrapDom.offsetHeight;\n const containerStyle = window.getComputedStyle(containerDom);\n const paddingTop = parseFloat(containerStyle.paddingTop);\n const paddingBottom = parseFloat(containerStyle.paddingBottom);\n const containerContentHeight = runtime.containerContentHeight = containerDom.clientHeight - paddingTop - paddingBottom;\n\n // 计算真实行高\n let realLineHeight = 0;\n // 若外部未传入, 尝试读取当前文本的行高。\n if (!realLineHeight && wrapDom) {\n const {lineHeight} = containerStyle || {};\n if (lineHeight) {\n // 未设置行高的为 normal\n realLineHeight = parseFloat(lineHeight);\n if (!realLineHeight) {\n setGetLineHeightFail(true);\n }\n }\n }\n // lineHeight同步到innerLineHeight\n if (innerLineHeight !== realLineHeight) {\n setInnerLineHeight(realLineHeight);\n if (!realLineHeight) {\n return;\n }\n }\n\n const isHeightMode = truncateMode === 'height';\n // 高度截断模式,比较简单 直接判断是否超出容器高度\n if (isHeightMode) {\n resetState(runtime.contentOffsetHeight > (maxHeight || containerContentHeight));\n return;\n }\n\n // 行数截断模式,需要利用行高计算是否超出容器高度\n if (!lines) {\n if (runtime.contentOffsetHeight > containerContentHeight) {\n const adjustLines = Math.floor(containerContentHeight / realLineHeight) || 1;\n if (innerLines !== adjustLines) {\n setInnerLines(adjustLines);\n }\n resetState(true);\n } else {\n resetState(false);\n }\n } else {\n if (innerLines !== lines) {\n setInnerLines(lines);\n }\n // console.log('contentOffsetHeight, realLineHeight', runtime.contentOffsetHeight, realLineHeight);\n // 允许误差1px(行高为小数时, safari计算行高*行数和实践总高有差异,故将行高向下取整兼容)\n resetState(runtime.contentOffsetHeight >= (lines + 1) * Math.floor(realLineHeight) - 1);\n }\n }, [lines, innerLineHeight, truncateMode, maxHeight, resetState]);\n\n // 监听内容高度,是否需要折叠\n // 用useLayoutEffect方式闪屏显示\n useCompatibleEffect(() => {\n resetState(runtime.ellipsis, {\n forceResetFold: true,\n });\n calcEllipsis();\n }, [calcEllipsis, resetState]);\n\n // 监听\"展开\"按钮宽度变化\n useEffect(() => {\n if (ellipsis && btnWrapperRef.current) {\n const {offsetWidth} = btnWrapperRef.current;\n if (offsetWidth !== runtime.foldBtnWidth) {\n runtime.foldBtnWidth = offsetWidth;\n setFoldBtnWidth(offsetWidth);\n }\n }\n }, [ellipsis, unfoldText, showFoldControl]);\n useEffect(() => {\n if (isSafari) {\n reorganizeDom();\n }\n }, [fold, reorganizeDom]);\n const updateTextContent = useCallback(() => {\n if (!wrapperRef.current) {\n return;\n }\n const newTextContent = wrapperRef.current.textContent || '';\n if (newTextContent !== runtime.textContent) {\n runtime.textContent = newTextContent;\n setTextContent(newTextContent);\n }\n }, []);\n const handleResize = useCallback<NonNullable<MeasureProps['onResize']>>((rect) => {\n // console.log('[handleResize] rect: ', rect, runtime.contentOffsetHeight);\n const {height} = rect.offset || {};\n if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n calcEllipsis();\n }\n }, [calcEllipsis]);\n const hoverTitle = useMemo(() => {\n return ellipsis && fold\n ? (typeof titleWhenFold === 'function'\n ? titleWhenFold(textContent)\n : titleWhenFold || textContent)\n : undefined;\n }, [titleWhenFold, ellipsis, fold, textContent]);\n useEffect(() => {\n if (runtime.inited) { \n runtime.onStatusChange?.({\n ellipsis,\n fold,\n title: hoverTitle\n });\n }\n }, [fold, ellipsis, hoverTitle]);\n useEffect(() => {\n runtime.inited = true;\n }, []);\n // 高度自适应,容器高度变化时重新计算高度(容器也需要包装Measure,TODO: 待开发 hooks -> useMeasure, 使得观测dom尺寸的方式更简洁)\n // if (!maxHeight && !lines) {\n // calcEllipsis();\n // }\n // console.log('[render TextEllipsis]: ellipsis fold wrapStyle: ', ellipsis, fold, wrapStyle);\n return (\n <div\n className={cx(c(\"container\"), className)}\n style={containerStyle}\n ref={(r) => {\n assignRef(containerRef, r);\n if (ref) {\n assignRef(ref, r);\n }\n }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onPointerEnter={onPointerEnter}\n onPointerLeave={onPointerLeave}\n onClick={onClick}\n onFocus={onFocus}\n >\n {/* 此dom仅用于计算高度 用.text-ellipsis-inner计算 在不重新初始化情况下切换文本时高度计算有问题 */}\n <Measure offset throttleMs={100} onResize={handleResize} triggerResizeInit={false}>\n {({measureRef, /* contentRect */}) => {\n // console.log('contentRect:', contentRect, contentRect.offset?.height, runtime.contentOffsetHeight);\n // const {height} = contentRect.offset || {};\n // if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n // calcEllipsis();\n // }\n return <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={(r) => {\n assignRef(measureRef, r);\n assignRef(wrapperRef, r);\n updateTextContent();\n }}>\n {finalContent}\n </div>\n }}\n </Measure>\n {/* <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={wrapperRef}>\n {finalContent}\n </div> */}\n {/* 主文本显示 */}\n <div\n className={\"text-ellipsis-inner\"}\n title={showTitleWhenFold ? hoverTitle : undefined}\n style={wrapStyle}\n ref={contentRef}\n >\n {/* {finalContent} */}\n {/* firefox >= 133 绝对定位的按钮放文本后面也会被截断隐藏!! , 放文本前面可解决 */}\n {ellipsis && showFoldControl && ButtonComp}\n {finalContent}\n {ButtonShadowDom}\n </div>\n </div>\n );\n});\n"],"names":["c","p","TextEllipsis","forwardRef","props","ref","className","style","_props$lineHeight","lineHeight","lines","maskBgColor","_props$resetFoldWhenC","resetFoldWhenChildrenOrEllipsisChange","showTitleWhenFold","titleWhenFold","_props$showFoldContro","showFoldControl","_props$foldText","foldText","_props$unfoldText","unfoldText","_props$uiType","uiType","_props$truncateMode","truncateMode","maxHeight","_props$controlPlaceme","controlPlacement","whiteSpace","width","renderFoldButton","onEllipsisChange","onFoldChange","onStatusChange","onMouseEnter","onMouseLeave","onPointerEnter","onPointerLeave","onClick","onFocus","finalContent","content","children","_useState","useState","ellipsis","setEllipsis","_useState2","getLineHeightFail","setGetLineHeightFail","_useSyncPropsState","useSyncPropsState","defaultValue","onChange","fold","setFold","_useState3","foldBtnWidth","setFoldBtnWidth","_useState4","endsWith","parseFloat","innerLineHeight","setInnerLineHeight","_useState5","_useState5$","innerLines","setInnerLines","_useState6","textContent","setTextContent","runtime","useRuntime","inited","contentOffsetHeight","containerContentHeight","defaultFold","contentRef","useRef","wrapperRef","containerRef","btnWrapperRef","containerStyle","useMemo","_extends","undefined","commonWrapStyle","wrapStyle","isHeightMode","paddingBottom","minHeight","WebkitLineClamp","boxSizing","validMaskBgColor","_ref","rgbaToObj","findEffectiveBgColor","current","r","g","b","startColor","endColor","btnStyle","padding","ratio","Math","min","_ref2","_ref2$startColor","_ref2$endColor","height","paddingTop","paddingLeft","background","reorganizeDom","useCallback","orginStyleWidth","orginWidth","window","getComputedStyle","requestAnimationFrame","handleFoldChange","evt","ButtonComp","React","createElement","cx","ButtonShadowDom","resetState","newEllipsis","_temp","_ref3$forceResetFold","forceResetFold","preFold","calcEllipsis","wrapDom","containerDom","offsetHeight","clientHeight","realLineHeight","floor","adjustLines","useCompatibleEffect","useEffect","offsetWidth","isSafari","updateTextContent","newTextContent","handleResize","rect","offset","abs","hoverTitle","title","assignRef","Measure","throttleMs","onResize","triggerResizeInit","_ref6","measureRef"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=require("react"),t=require("@ohkit/prefix-classname"),n=require("@ohkit/react-helper"),o=require("@ohkit/platform"),i=require("@ohkit/dom-helper"),r=require("@ohkit/measure");function l(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a=/*#__PURE__*/l(e);function s(){return s=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)({}).hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},s.apply(null,arguments)}var u=t.prefixClassname("ohkit-text-ellipsis__"),f=e.forwardRef(function(l,f){var d=l.className,c=l.style,h=l.lineHeight,g=void 0===h?"":h,p=l.lines,v=l.maskBgColor,m=l.resetFoldWhenChildrenOrEllipsisChange,C=void 0!==m&&m,b=l.showTitleWhenFold,x=l.titleWhenFold,w=l.showFoldControl,E=void 0===w||w,F=l.foldText,S=void 0===F?"收起":F,M=l.unfoldText,k=void 0===M?"展开":M,y=l.uiType,H=void 0===y?"right":y,R=l.truncateMode,O=void 0===R?"line":R,N=l.maxHeight,W=l.controlPlacement,q=void 0===W?"center":W,B=l.whiteSpace,T=l.width,P=l.renderFoldButton,L=l.onEllipsisChange,j=l.onFoldChange,z=l.onStatusChange,A=l.onMouseEnter,_=l.onMouseLeave,I=l.onPointerEnter,V=l.onPointerLeave,D=l.onClick,G=l.onFocus,J=l.content||l.children,K=e.useState(!1),Q=K[0],U=K[1],X=e.useState(!1),Y=X[0],Z=X[1],$=n.useSyncPropsState(l,"fold",{defaultValue:!0,onChange:j}),ee=$[0],te=$[1],ne=e.useState(1),oe=ne[0],ie=ne[1],re=e.useState("string"==typeof g&&g.endsWith("px")?parseFloat(g):0),le=re[0],ae=re[1],se=e.useState(p),ue=se[0],fe=void 0===ue?0:ue,de=se[1],ce=e.useState(""),he=ce[0],ge=ce[1],pe=n.useRuntime({inited:!1,contentOffsetHeight:0,containerContentHeight:0,ellipsis:Q,defaultFold:ee,fold:ee,foldBtnWidth:oe,textContent:he,onEllipsisChange:L,onFoldChange:j,onStatusChange:z},["fold","onEllipsisChange","onFoldChange","onStatusChange"])[0],ve=e.useRef(null),me=e.useRef(null),Ce=e.useRef(null),be=e.useRef(null),xe=e.useMemo(function(){return s({lineHeight:Y?"1.4":g||void 0},c)},[c,g,Y]),we=e.useMemo(function(){return{whiteSpace:B,width:T}},[B,T]),Ee=e.useMemo(function(){var e="height"===O;if(!Q||!(e||fe&&le))return we;var t=E&&"bottom"===H&&!ee?le+"px":void 0;return s({},we,{minHeight:!e&&ee?(fe-.2)*le+"px":void 0,WebkitLineClamp:e?void 0:ee?fe:void 0,maxHeight:e&&ee?N||fe*le||pe.containerContentHeight||0:void 0,paddingBottom:t,boxSizing:t?"border-box":void 0})},[fe,le,Q,ee,E,H,O,N,we]),Fe=e.useMemo(function(){if(!E||!Q)return null;var e=i.rgbaToObj(v||"")||i.findEffectiveBgColor(Ce.current),t=e.r,n=e.g,o=e.b;return{startColor:"rgba("+t+", "+n+", "+o+", 0.2)",endColor:"rgba("+t+", "+n+", "+o+", 1)"}},[v,Q,E]),Se=e.useMemo(function(){if(ee){var e=le,t="right"===H?Math.min(e/oe*100,80):60,n=Fe||{},o=n.startColor,i=n.endColor,r=void 0===i?"rgba(255,255,255,1)":i;return{boxSizing:"content-box",height:le+"px",lineHeight:le+"px",paddingTop:"bottom"===H?e+"px":void 0,paddingLeft:"right"===H?e+"px":void 0,background:"linear-gradient(to "+H+", "+(void 0===o?"rgba(255,255,255,0.2)":o)+", "+r+" "+t+"%, "+r+" 100%)"}}},[le,ee,H,oe,Fe]),Me=e.useCallback(function(){if(ve.current){var e=ve.current.style.width,t=window.getComputedStyle(ve.current).width;ve.current.style.width=parseFloat(t)-.1+"px",null==window.requestAnimationFrame||window.requestAnimationFrame(function(){ve.current&&(ve.current.style.width=e)})}},[]),ke=e.useCallback(function(e,t){void 0===t&&(t=!pe.fold),pe.fold=t,te(t)},[]),ye=e.useMemo(function(){/*#__PURE__*/return a.default.createElement("div",{className:t.classNames("btn-fold-wrapper","btn-fold-wrapper-"+H,"bottom"===H&&"placement-"+q),style:Se,ref:be,onClick:ke},P?P(ee):/*#__PURE__*/a.default.createElement("div",{className:"btn-fold"},ee?k:S))},[Se,ee,S,ke,P,q,H,k]),He=e.useMemo(function(){return
|
|
1
|
+
var e=require("react"),t=require("@ohkit/prefix-classname"),n=require("@ohkit/react-helper"),o=require("@ohkit/platform"),i=require("@ohkit/dom-helper"),r=require("@ohkit/measure");function l(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a=/*#__PURE__*/l(e);function s(){return s=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)({}).hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},s.apply(null,arguments)}var u=t.prefixClassname("ohkit-text-ellipsis__"),f=e.forwardRef(function(l,f){var d=l.className,c=l.style,h=l.lineHeight,g=void 0===h?"":h,p=l.lines,v=l.maskBgColor,m=l.resetFoldWhenChildrenOrEllipsisChange,C=void 0!==m&&m,b=l.showTitleWhenFold,x=l.titleWhenFold,w=l.showFoldControl,E=void 0===w||w,F=l.foldText,S=void 0===F?"收起":F,M=l.unfoldText,k=void 0===M?"展开":M,y=l.uiType,H=void 0===y?"right":y,R=l.truncateMode,O=void 0===R?"line":R,N=l.maxHeight,W=l.controlPlacement,q=void 0===W?"center":W,B=l.whiteSpace,T=l.width,P=l.renderFoldButton,L=l.onEllipsisChange,j=l.onFoldChange,z=l.onStatusChange,A=l.onMouseEnter,_=l.onMouseLeave,I=l.onPointerEnter,V=l.onPointerLeave,D=l.onClick,G=l.onFocus,J=l.content||l.children,K=e.useState(!1),Q=K[0],U=K[1],X=e.useState(!1),Y=X[0],Z=X[1],$=n.useSyncPropsState(l,"fold",{defaultValue:!0,onChange:j}),ee=$[0],te=$[1],ne=e.useState(1),oe=ne[0],ie=ne[1],re=e.useState("string"==typeof g&&g.endsWith("px")?parseFloat(g):0),le=re[0],ae=re[1],se=e.useState(p),ue=se[0],fe=void 0===ue?0:ue,de=se[1],ce=e.useState(""),he=ce[0],ge=ce[1],pe=n.useRuntime({inited:!1,contentOffsetHeight:0,containerContentHeight:0,ellipsis:Q,defaultFold:ee,fold:ee,foldBtnWidth:oe,textContent:he,onEllipsisChange:L,onFoldChange:j,onStatusChange:z},["fold","onEllipsisChange","onFoldChange","onStatusChange"])[0],ve=e.useRef(null),me=e.useRef(null),Ce=e.useRef(null),be=e.useRef(null),xe=e.useMemo(function(){return s({lineHeight:Y?"1.4":g||void 0},c)},[c,g,Y]),we=e.useMemo(function(){return{whiteSpace:B,width:T}},[B,T]),Ee=e.useMemo(function(){var e="height"===O;if(!Q||!(e||fe&&le))return we;var t=E&&"bottom"===H&&!ee?le+"px":void 0;return s({},we,{minHeight:!e&&ee?(fe-.2)*le+"px":void 0,WebkitLineClamp:e?void 0:ee?fe:void 0,maxHeight:e&&ee?N||fe*le||pe.containerContentHeight||0:void 0,paddingBottom:t,boxSizing:t?"border-box":void 0})},[fe,le,Q,ee,E,H,O,N,we]),Fe=e.useMemo(function(){if(!E||!Q)return null;var e=i.rgbaToObj(v||"")||i.findEffectiveBgColor(Ce.current),t=e.r,n=e.g,o=e.b;return{startColor:"rgba("+t+", "+n+", "+o+", 0.2)",endColor:"rgba("+t+", "+n+", "+o+", 1)"}},[v,Q,E]),Se=e.useMemo(function(){if(ee){var e=le,t="right"===H?Math.min(e/oe*100,80):60,n=Fe||{},o=n.startColor,i=n.endColor,r=void 0===i?"rgba(255,255,255,1)":i;return{boxSizing:"content-box",height:le+"px",lineHeight:le+"px",paddingTop:"bottom"===H?e+"px":void 0,paddingLeft:"right"===H?e+"px":void 0,background:"linear-gradient(to "+H+", "+(void 0===o?"rgba(255,255,255,0.2)":o)+", "+r+" "+t+"%, "+r+" 100%)"}}},[le,ee,H,oe,Fe]),Me=e.useCallback(function(){if(ve.current){var e=ve.current.style.width,t=window.getComputedStyle(ve.current).width;ve.current.style.width=parseFloat(t)-.1+"px",null==window.requestAnimationFrame||window.requestAnimationFrame(function(){ve.current&&(ve.current.style.width=e)})}},[]),ke=e.useCallback(function(e,t){void 0===t&&(t=!pe.fold),pe.fold=t,te(t)},[]),ye=e.useMemo(function(){/*#__PURE__*/return a.default.createElement("div",{className:t.classNames("btn-fold-wrapper","btn-fold-wrapper-"+H,"bottom"===H&&"placement-"+q),style:Se,ref:be,onClick:ke},P?P(ee):/*#__PURE__*/a.default.createElement("div",{className:"btn-fold"},ee?k:S))},[Se,ee,S,ke,P,q,H,k]),He=e.useMemo(function(){return Q&&E&&"right"===H&&!ee?/*#__PURE__*/a.default.createElement("span",{style:Se,className:"btn-fold-right-shadow"},P?P(ee):S):null},[Q,H,E,ee,Se,S,P]),Re=e.useCallback(function(e,t){void 0===e&&(e=pe.ellipsis);var n=(void 0===t?{}:t).forceResetFold,o=void 0!==n&&n,i=pe.ellipsis,r=pe.fold,l=pe.defaultFold;e!==i&&(U(e),pe.ellipsis=e,null==pe.onEllipsisChange||pe.onEllipsisChange(e)),C&&(o||!i&&e)&&r!==l&&ke(void 0,l)},[ke,J,C]),Oe=e.useCallback(function(){var e=me.current,t=Ce.current;if(e&&t){pe.contentOffsetHeight=e.offsetHeight;var n=window.getComputedStyle(t),o=parseFloat(n.paddingTop),i=parseFloat(n.paddingBottom),r=pe.containerContentHeight=t.clientHeight-o-i,l=0;if(!l&&e){var a=(n||{}).lineHeight;a&&((l=parseFloat(a))||Z(!0))}if(le===l||(ae(l),l))if("height"===O)Re(pe.contentOffsetHeight>(N||r));else if(p)fe!==p&&de(p),Re(pe.contentOffsetHeight>=(p+1)*Math.floor(l)-1);else if(pe.contentOffsetHeight>r){var s=Math.floor(r/l)||1;fe!==s&&de(s),Re(!0)}else Re(!1)}},[p,le,O,N,Re]);n.useCompatibleEffect(function(){Re(pe.ellipsis,{forceResetFold:!0}),Oe()},[Oe,Re]),e.useEffect(function(){if(Q&&be.current){var e=be.current.offsetWidth;e!==pe.foldBtnWidth&&(pe.foldBtnWidth=e,ie(e))}},[Q,k,E]),e.useEffect(function(){o.isSafari&&Me()},[ee,Me]);var Ne=e.useCallback(function(){if(me.current){var e=me.current.textContent||"";e!==pe.textContent&&(pe.textContent=e,ge(e))}},[]),We=e.useCallback(function(e){var t=(e.offset||{}).height;void 0!==t&&Math.abs(t-pe.contentOffsetHeight)>1&&Oe()},[Oe]),qe=e.useMemo(function(){return Q&&ee?"function"==typeof x?x(he):x||he:void 0},[x,Q,ee,he]);return e.useEffect(function(){pe.inited&&(null==pe.onStatusChange||pe.onStatusChange({ellipsis:Q,fold:ee,title:qe}))},[ee,Q,qe]),e.useEffect(function(){pe.inited=!0},[]),/*#__PURE__*/a.default.createElement("div",{className:t.classNames(u("container"),d),style:xe,ref:function(e){n.assignRef(Ce,e),f&&n.assignRef(f,e)},onMouseEnter:A,onMouseLeave:_,onPointerEnter:I,onPointerLeave:V,onClick:D,onFocus:G},/*#__PURE__*/a.default.createElement(r.Measure,{offset:!0,throttleMs:100,onResize:We,triggerResizeInit:!1},function(e){var t=e.measureRef;/*#__PURE__*/return a.default.createElement("div",{style:we,className:"content-shadow-dom",ref:function(e){n.assignRef(t,e),n.assignRef(me,e),Ne()}},J)}),/*#__PURE__*/a.default.createElement("div",{className:"text-ellipsis-inner",title:b?qe:void 0,style:Ee,ref:ve},Q&&E&&ye,J,He))});exports.TextEllipsis=f,exports.c=u;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @file 文本截断显示组件\n * @description 基于React封装一个文本截断显示组件,富文本(仅文字样式,图片和表格效果不一定好)同普通文本处理一致\n * @author <wuqiuyang305@126.com>\n */\n\nimport React, {\n forwardRef,\n useState,\n useMemo,\n useEffect,\n useCallback,\n useRef,\n PropsWithChildren,\n MouseEvent,\n} from \"react\";\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {\n assignRef,\n useRuntime,\n useCompatibleEffect,\n useSyncPropsState,\n} from \"@ohkit/react-helper\";\nimport {isSafari} from \"@ohkit/platform\";\nimport {rgbaToObj, findEffectiveBgColor} from \"@ohkit/dom-helper\";\nimport {Measure, MeasureProps} from \"@ohkit/measure\";\nimport \"./style.scss\";\n\nexport const c = p(\"ohkit-text-ellipsis__\");\n\ninterface ITextEllipsis\n extends Pick<\n React.DOMAttributes<HTMLDivElement>,\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onFocus\"\n | \"onClick\"\n > {\n /**\n * 自定义样式类名,会附加到根元素上\n */\n className?: string;\n /**\n * 自定义样式\n */\n style?: React.CSSProperties;\n /**\n * right | bottom 展开按钮在右下侧还是底部\n * @default right\n */\n uiType?: \"right\" | \"bottom\";\n /**\n * 截断模式 (若某些浏览器不支持 webkitLineClamp,可降级切换为 height 模式)\n * @default line\n */\n truncateMode?: \"line\" | \"height\";\n /**\n * truncateMode === \"height\" 时生效\n * 最大高度(number > 0),没传或者传入无效值不限制,尝试取 lines * lineHeight,若仍无效 自动截断到容器的最大高度\n * 单位: px\n */\n maxHeight?: number;\n /**\n * (单位:px)未传入或无效(0也视为无效)则自动取当前文本的行高\n */\n lineHeight?: React.CSSProperties[\"lineHeight\"];\n /**\n * truncateMode === \"line\" 时生效\n * 超过几行折叠(number > 0), 没传或者传入无效值不限制,自动截断到容器的最大高度\n */\n lines?: number;\n /**\n * 展开按钮蒙层背景色(仅支持16进制表示)\n * @default #fff\n */\n maskBgColor?: string;\n /**\n * text|ReactNode 与children任传一个\n */\n content?: React.ReactNode;\n /**\n * 当 content or children or ellipsis 变化时,重置 fold 状态 \n * @default false\n */\n resetFoldWhenChildrenOrEllipsisChange?: boolean;\n /**\n * 折叠状态\n * @default true\n */\n fold?: boolean;\n /**\n * 显示展开控制按钮\n * @default true\n */\n showFoldControl?: boolean;\n /**\n * 展开按钮位置 uiType='bottom'时有效\n * @default center\n */\n controlPlacement?: 'left' | 'center' | 'right';\n /**\n * 折叠按钮文字\n * @default 收起\n */\n foldText?: string;\n /**\n * 展开按钮文字\n * @default 展开\n */\n unfoldText?: string;\n /**\n * 折叠状态下是否显示title属性\n * @default false\n */\n showTitleWhenFold?: boolean;\n /**\n * 折叠状态自定义title属性内容\n */\n titleWhenFold?: string | ((title: string) => string);\n /**\n * 是否保留换行\n */\n whiteSpace?: React.CSSProperties['whiteSpace'];\n /**\n * 容器宽度(默认自适应内容)\n * 应用场景:whiteSpace='pre*' 时,支持展示换行符,自适应内容可能导致控制按钮位置不确定\n */\n width?: React.CSSProperties['width'];\n /**\n * 自定义渲染展开按钮\n */\n renderFoldButton?: (fold: boolean) => React.ReactNode;\n /**\n * @param fold 折叠状态,true 折叠,false 展开\n */\n onFoldChange?: (fold: boolean) => void;\n /**\n * @param ellipsis 是否截断,true 截断,false 未截断\n */\n onEllipsisChange?: (ellipsis: boolean) => void;\n /**\n * 关键状态变更触发\n * @param status\n */\n onStatusChange?: (status: {\n fold: boolean;\n ellipsis: boolean;\n title?: string;\n }) => void;\n}\n\nexport type TextEllipsisProps = PropsWithChildren<ITextEllipsis>;\n\nexport const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>((props, ref) => {\n const {\n className,\n style,\n lineHeight = \"\",\n lines,\n maskBgColor,\n content,\n children,\n resetFoldWhenChildrenOrEllipsisChange = false,\n showTitleWhenFold,\n titleWhenFold,\n showFoldControl = true,\n foldText = \"收起\",\n unfoldText = \"展开\",\n uiType = \"right\",\n truncateMode = \"line\",\n maxHeight,\n controlPlacement = 'center',\n whiteSpace,\n width,\n renderFoldButton,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n onMouseEnter,\n onMouseLeave,\n onPointerEnter,\n onPointerLeave,\n onClick,\n onFocus,\n } = props;\n const finalContent = content || children;\n // 是否截断\n const [ellipsis, setEllipsis] = useState(false);\n const [getLineHeightFail, setGetLineHeightFail] = useState(false);\n // 折叠状态\n const [fold, setFold] = useSyncPropsState(props, 'fold', {defaultValue: true, onChange: onFoldChange});\n const [foldBtnWidth, setFoldBtnWidth] = useState(1);\n const [innerLineHeight, setInnerLineHeight] = useState(\n typeof lineHeight === \"string\" && lineHeight.endsWith(\"px\")\n ? parseFloat(lineHeight)\n : 0\n );\n const [innerLines = 0, setInnerLines] = useState(lines);\n // children提取的纯文本\n const [textContent, setTextContent] = useState('');\n\n const [runtime] = useRuntime({\n inited: false, // mounted\n contentOffsetHeight: 0, // 内容节点offsetHeight\n containerContentHeight: 0, // 容器内容高度 = 容器高 - 上下padding\n ellipsis,\n defaultFold: fold, // 记录一下默认的折叠状态,用于 reset fold\n fold,\n foldBtnWidth,\n textContent,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n }, ['fold', 'onEllipsisChange', 'onFoldChange', 'onStatusChange']);\n\n const contentRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const btnWrapperRef = useRef<HTMLDivElement>(null);\n\n const containerStyle = useMemo(() => {\n return {\n lineHeight: getLineHeightFail // 未传入且获取 lineHeight(px) 失败,则设置 default lineHeight: 1.4(em)\n ? \"1.4\" // more brower normal default lineHeight\n : lineHeight ? lineHeight : undefined,\n ...style,\n };\n }, [style, lineHeight, getLineHeightFail]);\n\n const commonWrapStyle = useMemo(() => {\n return {\n whiteSpace,\n width,\n };\n }, [whiteSpace, width]);\n // 容器样式\n const wrapStyle = useMemo(() => {\n const lines = innerLines;\n const isHeightMode = truncateMode === 'height';\n if (!ellipsis || !isHeightMode && (!lines || !innerLineHeight)) {\n return commonWrapStyle;\n }\n const paddingBottom = showFoldControl && (uiType === \"bottom\" && !fold) ? `${innerLineHeight}px` : undefined;\n return {\n ...commonWrapStyle,\n // HACK: 兼容safari 15+ 富文本折叠高度丢失问题\n minHeight: !isHeightMode && fold ? `${(lines - 0.2) * innerLineHeight}px` : undefined,\n // Note: safari 对WebkitLineClamp支持太差劲 判断浏览器优雅降级为高度截断方案?目前先交给用户去判断,自行选择truncateMode\n // WebkitLineClamp: isSafari ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n // maxHeight: isSafari && fold ? lines * innerLineHeight : undefined,\n WebkitLineClamp: isHeightMode ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n maxHeight: isHeightMode && fold ? (maxHeight || lines * innerLineHeight || runtime.containerContentHeight || 0) : undefined,\n paddingBottom,\n boxSizing: paddingBottom ? 'border-box' as const : undefined,\n };\n }, [innerLines, innerLineHeight, ellipsis, fold, showFoldControl, uiType, truncateMode, maxHeight, commonWrapStyle]);\n\n // 计算折叠按钮蒙层的渐变颜色\n const validMaskBgColor = useMemo(() => {\n if (!showFoldControl || !ellipsis) {\n return null;\n }\n const {r, g, b} = rgbaToObj(maskBgColor || '') || findEffectiveBgColor(containerRef.current);\n return {\n startColor: `rgba(${r}, ${g}, ${b}, 0.2)`,\n endColor: `rgba(${r}, ${g}, ${b}, 1)`,\n };\n }, [maskBgColor, ellipsis, showFoldControl]);\n\n // 展开|收起 按钮样式\n const btnStyle = useMemo(() => {\n if (!fold) {\n return;\n }\n // 按钮padding,取行高\n const padding = innerLineHeight;\n // 蒙层透明度所占比例\n const ratio = uiType === \"right\" ? Math.min((padding / foldBtnWidth) * 100, 80) : 60;\n const {startColor = 'rgba(255,255,255,0.2)', endColor = 'rgba(255,255,255,1)'} = validMaskBgColor || {};\n return {\n boxSizing: 'content-box' as const,\n height: `${innerLineHeight}px`,\n lineHeight: `${innerLineHeight}px`,\n paddingTop: uiType === \"bottom\" ? `${padding}px` : undefined,\n paddingLeft: uiType === \"right\" ? `${padding}px` : undefined,\n // 渐变蒙层\n background: `linear-gradient(to ${uiType}, ${startColor}, ${endColor} ${ratio}%, ${endColor} 100%)`,\n };\n }, [innerLineHeight, fold, uiType, foldBtnWidth, validMaskBgColor]);\n\n const reorganizeDom = useCallback(() => {\n // Note: safari 中仅改变 WebkitLineClamp 没触发重排,调整微小宽度以触发\n if (contentRef.current) {\n const orginStyleWidth = contentRef.current.style.width;\n const orginWidth = window.getComputedStyle(contentRef.current).width;\n // console.log('orginWidth, orginStyleWidth:', orginWidth, orginStyleWidth);\n contentRef.current.style.width = `${parseFloat(orginWidth) - 0.1}px`;\n window.requestAnimationFrame?.(() => {\n if (contentRef.current) {\n contentRef.current.style.width = orginStyleWidth;\n }\n });\n }\n }, []);\n\n const handleFoldChange = useCallback(\n (evt?: MouseEvent<HTMLDivElement>, fold = !runtime.fold) => {\n runtime.fold = fold;\n setFold(fold);\n }, []);\n\n const ButtonComp = useMemo(() => {\n return (\n <div\n className={cx(\n \"btn-fold-wrapper\",\n `btn-fold-wrapper-${uiType}`,\n uiType === \"bottom\" && `placement-${controlPlacement}`\n )}\n style={btnStyle}\n ref={btnWrapperRef}\n onClick={handleFoldChange}\n >\n {renderFoldButton ? (\n renderFoldButton(fold)\n ) : (\n <div className={\"btn-fold\"}>{fold ? unfoldText : foldText}</div>\n )}\n </div>\n );\n }, [\n btnStyle,\n fold,\n foldText,\n handleFoldChange,\n renderFoldButton,\n controlPlacement,\n uiType,\n unfoldText,\n ]);\n\n // 占位按钮\n const ButtonShadowDom = useMemo(() => {\n if (!showFoldControl || uiType !== 'right' || fold) {\n return null;\n }\n return <span style={btnStyle} className=\"btn-fold-right-shadow\">\n {renderFoldButton ? renderFoldButton(fold) : foldText}\n </span>;\n }, [uiType, showFoldControl, fold, btnStyle, foldText, renderFoldButton]);\n\n // 重置状态\n const resetState = useCallback((newEllipsis = runtime.ellipsis, {\n forceResetFold = false, // 强制重置fold 比如child变化时\n } = {}) => {\n const {ellipsis, fold: preFold, defaultFold} = runtime;\n if (newEllipsis !== ellipsis) {\n setEllipsis(newEllipsis);\n runtime.ellipsis = newEllipsis;\n runtime.onEllipsisChange?.(newEllipsis);\n }\n // 从未截断状态切换为截断状态时,自动折叠(即:出现展开按钮)\n if (\n resetFoldWhenChildrenOrEllipsisChange\n && (forceResetFold || !ellipsis && newEllipsis)\n && preFold !== defaultFold\n ) {\n handleFoldChange(undefined, defaultFold);\n }\n }, [handleFoldChange, finalContent, resetFoldWhenChildrenOrEllipsisChange]);\n\n const calcEllipsis = useCallback(() => {\n const wrapDom = wrapperRef.current;\n const containerDom = containerRef.current;\n if (!wrapDom || !containerDom) {\n return;\n }\n runtime.contentOffsetHeight = wrapDom.offsetHeight;\n const containerStyle = window.getComputedStyle(containerDom);\n const paddingTop = parseFloat(containerStyle.paddingTop);\n const paddingBottom = parseFloat(containerStyle.paddingBottom);\n const containerContentHeight = runtime.containerContentHeight = containerDom.clientHeight - paddingTop - paddingBottom;\n\n // 计算真实行高\n let realLineHeight = 0;\n // 若外部未传入, 尝试读取当前文本的行高。\n if (!realLineHeight && wrapDom) {\n const {lineHeight} = containerStyle || {};\n if (lineHeight) {\n // 未设置行高的为 normal\n realLineHeight = parseFloat(lineHeight);\n if (!realLineHeight) {\n setGetLineHeightFail(true);\n }\n }\n }\n // lineHeight同步到innerLineHeight\n if (innerLineHeight !== realLineHeight) {\n setInnerLineHeight(realLineHeight);\n if (!realLineHeight) {\n return;\n }\n }\n\n const isHeightMode = truncateMode === 'height';\n // 高度截断模式,比较简单 直接判断是否超出容器高度\n if (isHeightMode) {\n resetState(runtime.contentOffsetHeight > (maxHeight || containerContentHeight));\n return;\n }\n\n // 行数截断模式,需要利用行高计算是否超出容器高度\n if (!lines) {\n if (runtime.contentOffsetHeight > containerContentHeight) {\n const adjustLines = Math.floor(containerContentHeight / realLineHeight) || 1;\n if (innerLines !== adjustLines) {\n setInnerLines(adjustLines);\n }\n resetState(true);\n } else {\n resetState(false);\n }\n } else {\n if (innerLines !== lines) {\n setInnerLines(lines);\n }\n // console.log('contentOffsetHeight, realLineHeight', runtime.contentOffsetHeight, realLineHeight);\n // 允许误差1px(行高为小数时, safari计算行高*行数和实践总高有差异,故将行高向下取整兼容)\n resetState(runtime.contentOffsetHeight >= (lines + 1) * Math.floor(realLineHeight) - 1);\n }\n }, [lines, innerLineHeight, truncateMode, maxHeight, resetState]);\n\n // 监听内容高度,是否需要折叠\n // 用useLayoutEffect方式闪屏显示\n useCompatibleEffect(() => {\n resetState(runtime.ellipsis, {\n forceResetFold: true,\n });\n calcEllipsis();\n }, [calcEllipsis, resetState]);\n\n // 监听\"展开\"按钮宽度变化\n useEffect(() => {\n if (ellipsis && btnWrapperRef.current) {\n const {offsetWidth} = btnWrapperRef.current;\n if (offsetWidth !== runtime.foldBtnWidth) {\n runtime.foldBtnWidth = offsetWidth;\n setFoldBtnWidth(offsetWidth);\n }\n }\n }, [ellipsis, unfoldText, showFoldControl]);\n useEffect(() => {\n if (isSafari) {\n reorganizeDom();\n }\n }, [fold, reorganizeDom]);\n const updateTextContent = useCallback(() => {\n if (!wrapperRef.current) {\n return;\n }\n const newTextContent = wrapperRef.current.textContent || '';\n if (newTextContent !== runtime.textContent) {\n runtime.textContent = newTextContent;\n setTextContent(newTextContent);\n }\n }, []);\n const handleResize = useCallback<NonNullable<MeasureProps['onResize']>>((rect) => {\n // console.log('[handleResize] rect: ', rect, runtime.contentOffsetHeight);\n const {height} = rect.offset || {};\n if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n calcEllipsis();\n }\n }, [calcEllipsis]);\n const hoverTitle = useMemo(() => {\n return ellipsis && fold\n ? (typeof titleWhenFold === 'function'\n ? titleWhenFold(textContent)\n : titleWhenFold || textContent)\n : undefined;\n }, [titleWhenFold, ellipsis, fold, textContent]);\n useEffect(() => {\n if (runtime.inited) { \n runtime.onStatusChange?.({\n ellipsis,\n fold,\n title: hoverTitle\n });\n }\n }, [fold, ellipsis, hoverTitle]);\n useEffect(() => {\n runtime.inited = true;\n }, []);\n // 高度自适应,容器高度变化时重新计算高度(容器也需要包装Measure,TODO: 待开发 hooks -> useMeasure, 使得观测dom尺寸的方式更简洁)\n // if (!maxHeight && !lines) {\n // calcEllipsis();\n // }\n // console.log('[render TextEllipsis]: ellipsis fold wrapStyle: ', ellipsis, fold, wrapStyle);\n return (\n <div\n className={cx(c(\"container\"), className)}\n style={containerStyle}\n ref={(r) => {\n assignRef(containerRef, r);\n ref && assignRef(ref, r);\n }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onPointerEnter={onPointerEnter}\n onPointerLeave={onPointerLeave}\n onClick={onClick}\n onFocus={onFocus}\n >\n {/* 此dom仅用于计算高度 用.text-ellipsis-inner计算 在不重新初始化情况下切换文本时高度计算有问题 */}\n <Measure offset throttleMs={100} onResize={handleResize} triggerResizeInit={false}>\n {({measureRef, /* contentRect */}) => {\n // console.log('contentRect:', contentRect, contentRect.offset?.height, runtime.contentOffsetHeight);\n // const {height} = contentRect.offset || {};\n // if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n // calcEllipsis();\n // }\n return <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={(r) => {\n assignRef(measureRef, r);\n assignRef(wrapperRef, r);\n updateTextContent();\n }}>\n {finalContent}\n </div>\n }}\n </Measure>\n {/* <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={wrapperRef}>\n {finalContent}\n </div> */}\n {/* 主文本显示 */}\n <div\n className={\"text-ellipsis-inner\"}\n title={showTitleWhenFold ? hoverTitle : undefined}\n style={wrapStyle}\n ref={contentRef}\n >\n {/* {finalContent} */}\n {/* firefox >= 133 绝对定位的按钮放文本后面也会被截断隐藏!! , 放文本前面可解决 */}\n {ellipsis && showFoldControl && ButtonComp}\n {finalContent}\n {ButtonShadowDom}\n </div>\n </div>\n );\n});\n"],"names":["c","p","prefixClassname","TextEllipsis","forwardRef","props","ref","className","style","_props$lineHeight","lineHeight","lines","maskBgColor","_props$resetFoldWhenC","resetFoldWhenChildrenOrEllipsisChange","showTitleWhenFold","titleWhenFold","_props$showFoldContro","showFoldControl","_props$foldText","foldText","_props$unfoldText","unfoldText","_props$uiType","uiType","_props$truncateMode","truncateMode","maxHeight","_props$controlPlaceme","controlPlacement","whiteSpace","width","renderFoldButton","onEllipsisChange","onFoldChange","onStatusChange","onMouseEnter","onMouseLeave","onPointerEnter","onPointerLeave","onClick","onFocus","finalContent","content","children","_useState","useState","ellipsis","setEllipsis","_useState2","getLineHeightFail","setGetLineHeightFail","_useSyncPropsState","useSyncPropsState","defaultValue","onChange","fold","setFold","_useState3","foldBtnWidth","setFoldBtnWidth","_useState4","endsWith","parseFloat","innerLineHeight","setInnerLineHeight","_useState5","_useState5$","innerLines","setInnerLines","_useState6","textContent","setTextContent","runtime","useRuntime","inited","contentOffsetHeight","containerContentHeight","defaultFold","contentRef","useRef","wrapperRef","containerRef","btnWrapperRef","containerStyle","useMemo","_extends","undefined","commonWrapStyle","wrapStyle","isHeightMode","paddingBottom","minHeight","WebkitLineClamp","boxSizing","validMaskBgColor","_ref","rgbaToObj","findEffectiveBgColor","current","r","g","b","startColor","endColor","btnStyle","padding","ratio","Math","min","_ref2","_ref2$startColor","_ref2$endColor","height","paddingTop","paddingLeft","background","reorganizeDom","useCallback","orginStyleWidth","orginWidth","window","getComputedStyle","requestAnimationFrame","handleFoldChange","evt","ButtonComp","React","createElement","cx","ButtonShadowDom","resetState","newEllipsis","_temp","_ref3$forceResetFold","forceResetFold","preFold","calcEllipsis","wrapDom","containerDom","offsetHeight","clientHeight","realLineHeight","floor","adjustLines","useCompatibleEffect","useEffect","offsetWidth","isSafari","updateTextContent","newTextContent","handleResize","rect","offset","abs","hoverTitle","title","assignRef","Measure","throttleMs","onResize","triggerResizeInit","_ref6","measureRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @file 文本截断显示组件\n * @description 基于React封装一个文本截断显示组件,富文本(仅文字样式,图片和表格效果不一定好)同普通文本处理一致\n * @author <wuqiuyang305@126.com>\n */\n\nimport React, {\n forwardRef,\n useState,\n useMemo,\n useEffect,\n useCallback,\n useRef,\n PropsWithChildren,\n MouseEvent,\n} from \"react\";\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {\n assignRef,\n useRuntime,\n useCompatibleEffect,\n useSyncPropsState,\n} from \"@ohkit/react-helper\";\nimport {isSafari} from \"@ohkit/platform\";\nimport {rgbaToObj, findEffectiveBgColor} from \"@ohkit/dom-helper\";\nimport {Measure, MeasureProps} from \"@ohkit/measure\";\nimport \"./style.scss\";\n\nexport const c = p(\"ohkit-text-ellipsis__\");\n\ninterface ITextEllipsis\n extends Pick<\n React.DOMAttributes<HTMLDivElement>,\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onFocus\"\n | \"onClick\"\n > {\n /**\n * 自定义样式类名,会附加到根元素上\n */\n className?: string;\n /**\n * 自定义样式\n */\n style?: React.CSSProperties;\n /**\n * right | bottom 展开按钮在右下侧还是底部\n * @default right\n */\n uiType?: \"right\" | \"bottom\";\n /**\n * 截断模式 (若某些浏览器不支持 webkitLineClamp,可降级切换为 height 模式)\n * @default line\n */\n truncateMode?: \"line\" | \"height\";\n /**\n * truncateMode === \"height\" 时生效\n * 最大高度(number > 0),没传或者传入无效值不限制,尝试取 lines * lineHeight,若仍无效 自动截断到容器的最大高度\n * 单位: px\n */\n maxHeight?: number;\n /**\n * (单位:px)未传入或无效(0也视为无效)则自动取当前文本的行高\n */\n lineHeight?: React.CSSProperties[\"lineHeight\"];\n /**\n * truncateMode === \"line\" 时生效\n * 超过几行折叠(number > 0), 没传或者传入无效值不限制,自动截断到容器的最大高度\n */\n lines?: number;\n /**\n * 展开按钮蒙层背景色(仅支持16进制表示)\n * @default #fff\n */\n maskBgColor?: string;\n /**\n * text|ReactNode 与children任传一个\n */\n content?: React.ReactNode;\n /**\n * 当 content or children or ellipsis 变化时,重置 fold 状态 \n * @default false\n */\n resetFoldWhenChildrenOrEllipsisChange?: boolean;\n /**\n * 折叠状态\n * @default true\n */\n fold?: boolean;\n /**\n * 显示展开控制按钮\n * @default true\n */\n showFoldControl?: boolean;\n /**\n * 展开按钮位置 uiType='bottom'时有效\n * @default center\n */\n controlPlacement?: 'left' | 'center' | 'right';\n /**\n * 折叠按钮文字\n * @default 收起\n */\n foldText?: string;\n /**\n * 展开按钮文字\n * @default 展开\n */\n unfoldText?: string;\n /**\n * 折叠状态下是否显示title属性\n * @default false\n */\n showTitleWhenFold?: boolean;\n /**\n * 折叠状态自定义title属性内容\n */\n titleWhenFold?: string | ((title: string) => string);\n /**\n * 是否保留换行\n */\n whiteSpace?: React.CSSProperties['whiteSpace'];\n /**\n * 容器宽度(默认自适应内容)\n * 应用场景:whiteSpace='pre*' 时,支持展示换行符,自适应内容可能导致控制按钮位置不确定\n */\n width?: React.CSSProperties['width'];\n /**\n * 自定义渲染展开按钮\n */\n renderFoldButton?: (fold: boolean) => React.ReactNode;\n /**\n * @param fold 折叠状态,true 折叠,false 展开\n */\n onFoldChange?: (fold: boolean) => void;\n /**\n * @param ellipsis 是否截断,true 截断,false 未截断\n */\n onEllipsisChange?: (ellipsis: boolean) => void;\n /**\n * 关键状态变更触发\n * @param status\n */\n onStatusChange?: (status: {\n fold: boolean;\n ellipsis: boolean;\n title?: string;\n }) => void;\n}\n\nexport type TextEllipsisProps = PropsWithChildren<ITextEllipsis>;\n\nexport const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>(function TextEllipsis(props, ref) {\n const {\n className,\n style,\n lineHeight = \"\",\n lines,\n maskBgColor,\n content,\n children,\n resetFoldWhenChildrenOrEllipsisChange = false,\n showTitleWhenFold,\n titleWhenFold,\n showFoldControl = true,\n foldText = \"收起\",\n unfoldText = \"展开\",\n uiType = \"right\",\n truncateMode = \"line\",\n maxHeight,\n controlPlacement = 'center',\n whiteSpace,\n width,\n renderFoldButton,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n onMouseEnter,\n onMouseLeave,\n onPointerEnter,\n onPointerLeave,\n onClick,\n onFocus,\n } = props;\n const finalContent = content || children;\n // 是否截断\n const [ellipsis, setEllipsis] = useState(false);\n const [getLineHeightFail, setGetLineHeightFail] = useState(false);\n // 折叠状态\n const [fold, setFold] = useSyncPropsState(props, 'fold', {defaultValue: true, onChange: onFoldChange});\n const [foldBtnWidth, setFoldBtnWidth] = useState(1);\n const [innerLineHeight, setInnerLineHeight] = useState(\n typeof lineHeight === \"string\" && lineHeight.endsWith(\"px\")\n ? parseFloat(lineHeight)\n : 0\n );\n const [innerLines = 0, setInnerLines] = useState(lines);\n // children提取的纯文本\n const [textContent, setTextContent] = useState('');\n\n const [runtime] = useRuntime({\n inited: false, // mounted\n contentOffsetHeight: 0, // 内容节点offsetHeight\n containerContentHeight: 0, // 容器内容高度 = 容器高 - 上下padding\n ellipsis,\n defaultFold: fold, // 记录一下默认的折叠状态,用于 reset fold\n fold,\n foldBtnWidth,\n textContent,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n }, ['fold', 'onEllipsisChange', 'onFoldChange', 'onStatusChange']);\n\n const contentRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const btnWrapperRef = useRef<HTMLDivElement>(null);\n\n const containerStyle = useMemo(() => {\n return {\n lineHeight: getLineHeightFail // 未传入且获取 lineHeight(px) 失败,则设置 default lineHeight: 1.4(em)\n ? \"1.4\" // more brower normal default lineHeight\n : lineHeight ? lineHeight : undefined,\n ...style,\n };\n }, [style, lineHeight, getLineHeightFail]);\n\n const commonWrapStyle = useMemo(() => {\n return {\n whiteSpace,\n width,\n };\n }, [whiteSpace, width]);\n // 容器样式\n const wrapStyle = useMemo(() => {\n const lines = innerLines;\n const isHeightMode = truncateMode === 'height';\n if (!ellipsis || !isHeightMode && (!lines || !innerLineHeight)) {\n return commonWrapStyle;\n }\n const paddingBottom = showFoldControl && (uiType === \"bottom\" && !fold) ? `${innerLineHeight}px` : undefined;\n return {\n ...commonWrapStyle,\n // HACK: 兼容safari 15+ 富文本折叠高度丢失问题\n minHeight: !isHeightMode && fold ? `${(lines - 0.2) * innerLineHeight}px` : undefined,\n // Note: safari 对WebkitLineClamp支持太差劲 判断浏览器优雅降级为高度截断方案?目前先交给用户去判断,自行选择truncateMode\n // WebkitLineClamp: isSafari ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n // maxHeight: isSafari && fold ? lines * innerLineHeight : undefined,\n WebkitLineClamp: isHeightMode ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n maxHeight: isHeightMode && fold ? (maxHeight || lines * innerLineHeight || runtime.containerContentHeight || 0) : undefined,\n paddingBottom,\n boxSizing: paddingBottom ? 'border-box' as const : undefined,\n };\n }, [innerLines, innerLineHeight, ellipsis, fold, showFoldControl, uiType, truncateMode, maxHeight, commonWrapStyle]);\n\n // 计算折叠按钮蒙层的渐变颜色\n const validMaskBgColor = useMemo(() => {\n if (!showFoldControl || !ellipsis) {\n return null;\n }\n const {r, g, b} = rgbaToObj(maskBgColor || '') || findEffectiveBgColor(containerRef.current);\n return {\n startColor: `rgba(${r}, ${g}, ${b}, 0.2)`,\n endColor: `rgba(${r}, ${g}, ${b}, 1)`,\n };\n }, [maskBgColor, ellipsis, showFoldControl]);\n\n // 展开|收起 按钮样式\n const btnStyle = useMemo(() => {\n if (!fold) {\n return;\n }\n // 按钮padding,取行高\n const padding = innerLineHeight;\n // 蒙层透明度所占比例\n const ratio = uiType === \"right\" ? Math.min((padding / foldBtnWidth) * 100, 80) : 60;\n const {startColor = 'rgba(255,255,255,0.2)', endColor = 'rgba(255,255,255,1)'} = validMaskBgColor || {};\n return {\n boxSizing: 'content-box' as const,\n height: `${innerLineHeight}px`,\n lineHeight: `${innerLineHeight}px`,\n paddingTop: uiType === \"bottom\" ? `${padding}px` : undefined,\n paddingLeft: uiType === \"right\" ? `${padding}px` : undefined,\n // 渐变蒙层\n background: `linear-gradient(to ${uiType}, ${startColor}, ${endColor} ${ratio}%, ${endColor} 100%)`,\n };\n }, [innerLineHeight, fold, uiType, foldBtnWidth, validMaskBgColor]);\n\n const reorganizeDom = useCallback(() => {\n // Note: safari 中仅改变 WebkitLineClamp 没触发重排,调整微小宽度以触发\n if (contentRef.current) {\n const orginStyleWidth = contentRef.current.style.width;\n const orginWidth = window.getComputedStyle(contentRef.current).width;\n // console.log('orginWidth, orginStyleWidth:', orginWidth, orginStyleWidth);\n contentRef.current.style.width = `${parseFloat(orginWidth) - 0.1}px`;\n window.requestAnimationFrame?.(() => {\n if (contentRef.current) {\n contentRef.current.style.width = orginStyleWidth;\n }\n });\n }\n }, []);\n\n const handleFoldChange = useCallback(\n (evt?: MouseEvent<HTMLDivElement>, fold = !runtime.fold) => {\n runtime.fold = fold;\n setFold(fold);\n }, []);\n\n const ButtonComp = useMemo(() => {\n return (\n <div\n className={cx(\n \"btn-fold-wrapper\",\n `btn-fold-wrapper-${uiType}`,\n uiType === \"bottom\" && `placement-${controlPlacement}`\n )}\n style={btnStyle}\n ref={btnWrapperRef}\n onClick={handleFoldChange}\n >\n {renderFoldButton ? (\n renderFoldButton(fold)\n ) : (\n <div className={\"btn-fold\"}>{fold ? unfoldText : foldText}</div>\n )}\n </div>\n );\n }, [\n btnStyle,\n fold,\n foldText,\n handleFoldChange,\n renderFoldButton,\n controlPlacement,\n uiType,\n unfoldText,\n ]);\n\n // 占位按钮\n const ButtonShadowDom = useMemo(() => {\n if (!ellipsis || !showFoldControl || uiType !== 'right' || fold) {\n return null;\n }\n return <span style={btnStyle} className=\"btn-fold-right-shadow\">\n {renderFoldButton ? renderFoldButton(fold) : foldText}\n </span>;\n }, [ellipsis, uiType, showFoldControl, fold, btnStyle, foldText, renderFoldButton]);\n\n // 重置状态\n const resetState = useCallback((newEllipsis = runtime.ellipsis, {\n forceResetFold = false, // 强制重置fold 比如child变化时\n } = {}) => {\n const {ellipsis, fold: preFold, defaultFold} = runtime;\n if (newEllipsis !== ellipsis) {\n setEllipsis(newEllipsis);\n runtime.ellipsis = newEllipsis;\n runtime.onEllipsisChange?.(newEllipsis);\n }\n // 从未截断状态切换为截断状态时,自动折叠(即:出现展开按钮)\n if (\n resetFoldWhenChildrenOrEllipsisChange\n && (forceResetFold || !ellipsis && newEllipsis)\n && preFold !== defaultFold\n ) {\n handleFoldChange(undefined, defaultFold);\n }\n }, [handleFoldChange, finalContent, resetFoldWhenChildrenOrEllipsisChange]);\n\n const calcEllipsis = useCallback(() => {\n const wrapDom = wrapperRef.current;\n const containerDom = containerRef.current;\n if (!wrapDom || !containerDom) {\n return;\n }\n runtime.contentOffsetHeight = wrapDom.offsetHeight;\n const containerStyle = window.getComputedStyle(containerDom);\n const paddingTop = parseFloat(containerStyle.paddingTop);\n const paddingBottom = parseFloat(containerStyle.paddingBottom);\n const containerContentHeight = runtime.containerContentHeight = containerDom.clientHeight - paddingTop - paddingBottom;\n\n // 计算真实行高\n let realLineHeight = 0;\n // 若外部未传入, 尝试读取当前文本的行高。\n if (!realLineHeight && wrapDom) {\n const {lineHeight} = containerStyle || {};\n if (lineHeight) {\n // 未设置行高的为 normal\n realLineHeight = parseFloat(lineHeight);\n if (!realLineHeight) {\n setGetLineHeightFail(true);\n }\n }\n }\n // lineHeight同步到innerLineHeight\n if (innerLineHeight !== realLineHeight) {\n setInnerLineHeight(realLineHeight);\n if (!realLineHeight) {\n return;\n }\n }\n\n const isHeightMode = truncateMode === 'height';\n // 高度截断模式,比较简单 直接判断是否超出容器高度\n if (isHeightMode) {\n resetState(runtime.contentOffsetHeight > (maxHeight || containerContentHeight));\n return;\n }\n\n // 行数截断模式,需要利用行高计算是否超出容器高度\n if (!lines) {\n if (runtime.contentOffsetHeight > containerContentHeight) {\n const adjustLines = Math.floor(containerContentHeight / realLineHeight) || 1;\n if (innerLines !== adjustLines) {\n setInnerLines(adjustLines);\n }\n resetState(true);\n } else {\n resetState(false);\n }\n } else {\n if (innerLines !== lines) {\n setInnerLines(lines);\n }\n // console.log('contentOffsetHeight, realLineHeight', runtime.contentOffsetHeight, realLineHeight);\n // 允许误差1px(行高为小数时, safari计算行高*行数和实践总高有差异,故将行高向下取整兼容)\n resetState(runtime.contentOffsetHeight >= (lines + 1) * Math.floor(realLineHeight) - 1);\n }\n }, [lines, innerLineHeight, truncateMode, maxHeight, resetState]);\n\n // 监听内容高度,是否需要折叠\n // 用useLayoutEffect方式闪屏显示\n useCompatibleEffect(() => {\n resetState(runtime.ellipsis, {\n forceResetFold: true,\n });\n calcEllipsis();\n }, [calcEllipsis, resetState]);\n\n // 监听\"展开\"按钮宽度变化\n useEffect(() => {\n if (ellipsis && btnWrapperRef.current) {\n const {offsetWidth} = btnWrapperRef.current;\n if (offsetWidth !== runtime.foldBtnWidth) {\n runtime.foldBtnWidth = offsetWidth;\n setFoldBtnWidth(offsetWidth);\n }\n }\n }, [ellipsis, unfoldText, showFoldControl]);\n useEffect(() => {\n if (isSafari) {\n reorganizeDom();\n }\n }, [fold, reorganizeDom]);\n const updateTextContent = useCallback(() => {\n if (!wrapperRef.current) {\n return;\n }\n const newTextContent = wrapperRef.current.textContent || '';\n if (newTextContent !== runtime.textContent) {\n runtime.textContent = newTextContent;\n setTextContent(newTextContent);\n }\n }, []);\n const handleResize = useCallback<NonNullable<MeasureProps['onResize']>>((rect) => {\n // console.log('[handleResize] rect: ', rect, runtime.contentOffsetHeight);\n const {height} = rect.offset || {};\n if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n calcEllipsis();\n }\n }, [calcEllipsis]);\n const hoverTitle = useMemo(() => {\n return ellipsis && fold\n ? (typeof titleWhenFold === 'function'\n ? titleWhenFold(textContent)\n : titleWhenFold || textContent)\n : undefined;\n }, [titleWhenFold, ellipsis, fold, textContent]);\n useEffect(() => {\n if (runtime.inited) { \n runtime.onStatusChange?.({\n ellipsis,\n fold,\n title: hoverTitle\n });\n }\n }, [fold, ellipsis, hoverTitle]);\n useEffect(() => {\n runtime.inited = true;\n }, []);\n // 高度自适应,容器高度变化时重新计算高度(容器也需要包装Measure,TODO: 待开发 hooks -> useMeasure, 使得观测dom尺寸的方式更简洁)\n // if (!maxHeight && !lines) {\n // calcEllipsis();\n // }\n // console.log('[render TextEllipsis]: ellipsis fold wrapStyle: ', ellipsis, fold, wrapStyle);\n return (\n <div\n className={cx(c(\"container\"), className)}\n style={containerStyle}\n ref={(r) => {\n assignRef(containerRef, r);\n if (ref) {\n assignRef(ref, r);\n }\n }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onPointerEnter={onPointerEnter}\n onPointerLeave={onPointerLeave}\n onClick={onClick}\n onFocus={onFocus}\n >\n {/* 此dom仅用于计算高度 用.text-ellipsis-inner计算 在不重新初始化情况下切换文本时高度计算有问题 */}\n <Measure offset throttleMs={100} onResize={handleResize} triggerResizeInit={false}>\n {({measureRef, /* contentRect */}) => {\n // console.log('contentRect:', contentRect, contentRect.offset?.height, runtime.contentOffsetHeight);\n // const {height} = contentRect.offset || {};\n // if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n // calcEllipsis();\n // }\n return <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={(r) => {\n assignRef(measureRef, r);\n assignRef(wrapperRef, r);\n updateTextContent();\n }}>\n {finalContent}\n </div>\n }}\n </Measure>\n {/* <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={wrapperRef}>\n {finalContent}\n </div> */}\n {/* 主文本显示 */}\n <div\n className={\"text-ellipsis-inner\"}\n title={showTitleWhenFold ? hoverTitle : undefined}\n style={wrapStyle}\n ref={contentRef}\n >\n {/* {finalContent} */}\n {/* firefox >= 133 绝对定位的按钮放文本后面也会被截断隐藏!! , 放文本前面可解决 */}\n {ellipsis && showFoldControl && ButtonComp}\n {finalContent}\n {ButtonShadowDom}\n </div>\n </div>\n );\n});\n"],"names":["c","p","prefixClassname","TextEllipsis","forwardRef","props","ref","className","style","_props$lineHeight","lineHeight","lines","maskBgColor","_props$resetFoldWhenC","resetFoldWhenChildrenOrEllipsisChange","showTitleWhenFold","titleWhenFold","_props$showFoldContro","showFoldControl","_props$foldText","foldText","_props$unfoldText","unfoldText","_props$uiType","uiType","_props$truncateMode","truncateMode","maxHeight","_props$controlPlaceme","controlPlacement","whiteSpace","width","renderFoldButton","onEllipsisChange","onFoldChange","onStatusChange","onMouseEnter","onMouseLeave","onPointerEnter","onPointerLeave","onClick","onFocus","finalContent","content","children","_useState","useState","ellipsis","setEllipsis","_useState2","getLineHeightFail","setGetLineHeightFail","_useSyncPropsState","useSyncPropsState","defaultValue","onChange","fold","setFold","_useState3","foldBtnWidth","setFoldBtnWidth","_useState4","endsWith","parseFloat","innerLineHeight","setInnerLineHeight","_useState5","_useState5$","innerLines","setInnerLines","_useState6","textContent","setTextContent","runtime","useRuntime","inited","contentOffsetHeight","containerContentHeight","defaultFold","contentRef","useRef","wrapperRef","containerRef","btnWrapperRef","containerStyle","useMemo","_extends","undefined","commonWrapStyle","wrapStyle","isHeightMode","paddingBottom","minHeight","WebkitLineClamp","boxSizing","validMaskBgColor","_ref","rgbaToObj","findEffectiveBgColor","current","r","g","b","startColor","endColor","btnStyle","padding","ratio","Math","min","_ref2","_ref2$startColor","_ref2$endColor","height","paddingTop","paddingLeft","background","reorganizeDom","useCallback","orginStyleWidth","orginWidth","window","getComputedStyle","requestAnimationFrame","handleFoldChange","evt","ButtonComp","React","createElement","cx","classNames","ButtonShadowDom","resetState","newEllipsis","_temp","_ref3$forceResetFold","forceResetFold","preFold","calcEllipsis","wrapDom","containerDom","offsetHeight","clientHeight","realLineHeight","floor","adjustLines","useCompatibleEffect","useEffect","offsetWidth","isSafari","updateTextContent","newTextContent","handleResize","rect","offset","abs","hoverTitle","title","assignRef","Measure","throttleMs","onResize","triggerResizeInit","_ref6","measureRef"],"mappings":"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"}
|
package/dist/index.modern.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import t,{forwardRef as e,useState as n,useRef as o,useMemo as i,useCallback as r,useEffect as l}from"react";import{prefixClassname as s,classNames as a}from"@ohkit/prefix-classname";import{useSyncPropsState as d,useRuntime as c,useCompatibleEffect as h,assignRef as f}from"@ohkit/react-helper";import{isSafari as g}from"@ohkit/platform";import{rgbaToObj as u,findEffectiveBgColor as p}from"@ohkit/dom-helper";import{Measure as m}from"@ohkit/measure";function C(){return C=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var o in n)({}).hasOwnProperty.call(n,o)&&(t[o]=n[o])}return t},C.apply(null,arguments)}const v=s("ohkit-text-ellipsis__"),x=e(function(e,s){const{className:x,style:b,lineHeight:w="",lines:F,maskBgColor:H,content:$,children:E,resetFoldWhenChildrenOrEllipsisChange:y=!1,showTitleWhenFold:k,titleWhenFold:S,showFoldControl:M=!0,foldText:O="收起",unfoldText:W="展开",uiType:B="right",truncateMode:N="line",maxHeight:L,controlPlacement:P="center",whiteSpace:T,width:R,renderFoldButton:z,onEllipsisChange:j,onFoldChange:q,onStatusChange:A,onMouseEnter:_,onMouseLeave:I,onPointerEnter:V,onPointerLeave:D,onClick:G,onFocus:J}=e,K=$||E,[Q,U]=n(!1),[X,Y]=n(!1),[Z,tt]=d(e,"fold",{defaultValue:!0,onChange:q}),[et,nt]=n(1),[ot,it]=n("string"==typeof w&&w.endsWith("px")?parseFloat(w):0),[rt=0,lt]=n(F),[st,at]=n(""),[dt]=c({inited:!1,contentOffsetHeight:0,containerContentHeight:0,ellipsis:Q,defaultFold:Z,fold:Z,foldBtnWidth:et,textContent:st,onEllipsisChange:j,onFoldChange:q,onStatusChange:A},["fold","onEllipsisChange","onFoldChange","onStatusChange"]),ct=o(null),ht=o(null),ft=o(null),gt=o(null),ut=i(()=>C({lineHeight:X?"1.4":w||void 0},b),[b,w,X]),pt=i(()=>({whiteSpace:T,width:R}),[T,R]),mt=i(()=>{const t="height"===N;if(!Q||!(t||rt&&ot))return pt;const e=M&&"bottom"===B&&!Z?`${ot}px`:void 0;return C({},pt,{minHeight:!t&&Z?(rt-.2)*ot+"px":void 0,WebkitLineClamp:t?void 0:Z?rt:void 0,maxHeight:t&&Z?L||rt*ot||dt.containerContentHeight||0:void 0,paddingBottom:e,boxSizing:e?"border-box":void 0})},[rt,ot,Q,Z,M,B,N,L,pt]),Ct=i(()=>{if(!M||!Q)return null;const{r:t,g:e,b:n}=u(H||"")||p(ft.current);return{startColor:`rgba(${t}, ${e}, ${n}, 0.2)`,endColor:`rgba(${t}, ${e}, ${n}, 1)`}},[H,Q,M]),vt=i(()=>{if(!Z)return;const t=ot,e="right"===B?Math.min(t/et*100,80):60,{startColor:n="rgba(255,255,255,0.2)",endColor:o="rgba(255,255,255,1)"}=Ct||{};return{boxSizing:"content-box",height:`${ot}px`,lineHeight:`${ot}px`,paddingTop:"bottom"===B?`${t}px`:void 0,paddingLeft:"right"===B?`${t}px`:void 0,background:`linear-gradient(to ${B}, ${n}, ${o} ${e}%, ${o} 100%)`}},[ot,Z,B,et,Ct]),xt=r(()=>{if(ct.current){const t=ct.current.style.width,e=window.getComputedStyle(ct.current).width;ct.current.style.width=parseFloat(e)-.1+"px",null==window.requestAnimationFrame||window.requestAnimationFrame(()=>{ct.current&&(ct.current.style.width=t)})}},[]),bt=r((t,e=!dt.fold)=>{dt.fold=e,tt(e)},[]),wt=i(()=>/*#__PURE__*/t.createElement("div",{className:a("btn-fold-wrapper",`btn-fold-wrapper-${B}`,"bottom"===B&&`placement-${P}`),style:vt,ref:gt,onClick:bt},z?z(Z):/*#__PURE__*/t.createElement("div",{className:"btn-fold"},Z?W:O)),[vt,Z,O,bt,z,P,B,W]),Ft=i(()=>Q&&M&&"right"===B&&!Z?/*#__PURE__*/t.createElement("span",{style:vt,className:"btn-fold-right-shadow"},z?z(Z):O):null,[Q,B,M,Z,vt,O,z]),Ht=r((t=dt.ellipsis,{forceResetFold:e=!1}={})=>{const{ellipsis:n,fold:o,defaultFold:i}=dt;t!==n&&(U(t),dt.ellipsis=t,null==dt.onEllipsisChange||dt.onEllipsisChange(t)),y&&(e||!n&&t)&&o!==i&&bt(void 0,i)},[bt,K,y]),$t=r(()=>{const t=ht.current,e=ft.current;if(!t||!e)return;dt.contentOffsetHeight=t.offsetHeight;const n=window.getComputedStyle(e),o=parseFloat(n.paddingTop),i=parseFloat(n.paddingBottom),r=dt.containerContentHeight=e.clientHeight-o-i;let l=0;if(!l&&t){const{lineHeight:t}=n||{};t&&(l=parseFloat(t),l||Y(!0))}if(ot===l||(it(l),l))if("height"===N)Ht(dt.contentOffsetHeight>(L||r));else if(F)rt!==F&<(F),Ht(dt.contentOffsetHeight>=(F+1)*Math.floor(l)-1);else if(dt.contentOffsetHeight>r){const t=Math.floor(r/l)||1;rt!==t&<(t),Ht(!0)}else Ht(!1)},[F,ot,N,L,Ht]);h(()=>{Ht(dt.ellipsis,{forceResetFold:!0}),$t()},[$t,Ht]),l(()=>{if(Q&>.current){const{offsetWidth:t}=gt.current;t!==dt.foldBtnWidth&&(dt.foldBtnWidth=t,nt(t))}},[Q,W,M]),l(()=>{g&&xt()},[Z,xt]);const Et=r(()=>{if(!ht.current)return;const t=ht.current.textContent||"";t!==dt.textContent&&(dt.textContent=t,at(t))},[]),yt=r(t=>{const{height:e}=t.offset||{};void 0!==e&&Math.abs(e-dt.contentOffsetHeight)>1&&$t()},[$t]),kt=i(()=>Q&&Z?"function"==typeof S?S(st):S||st:void 0,[S,Q,Z,st]);return l(()=>{dt.inited&&(null==dt.onStatusChange||dt.onStatusChange({ellipsis:Q,fold:Z,title:kt}))},[Z,Q,kt]),l(()=>{dt.inited=!0},[]),/*#__PURE__*/t.createElement("div",{className:a(v("container"),x),style:ut,ref:t=>{f(ft,t),s&&f(s,t)},onMouseEnter:_,onMouseLeave:I,onPointerEnter:V,onPointerLeave:D,onClick:G,onFocus:J},/*#__PURE__*/t.createElement(m,{offset:!0,throttleMs:100,onResize:yt,triggerResizeInit:!1},({measureRef:e})=>/*#__PURE__*/t.createElement("div",{style:pt,className:"content-shadow-dom",ref:t=>{f(e,t),f(ht,t),Et()}},K)),/*#__PURE__*/t.createElement("div",{className:"text-ellipsis-inner",title:k?kt:void 0,style:mt,ref:ct},Q&&M&&wt,K,Ft))});export{x as TextEllipsis,v as c};
|
|
2
2
|
//# sourceMappingURL=index.modern.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.modern.mjs","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @file 文本截断显示组件\n * @description 基于React封装一个文本截断显示组件,富文本(仅文字样式,图片和表格效果不一定好)同普通文本处理一致\n * @author <wuqiuyang305@126.com>\n */\n\nimport React, {\n forwardRef,\n useState,\n useMemo,\n useEffect,\n useCallback,\n useRef,\n PropsWithChildren,\n MouseEvent,\n} from \"react\";\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {\n assignRef,\n useRuntime,\n useCompatibleEffect,\n useSyncPropsState,\n} from \"@ohkit/react-helper\";\nimport {isSafari} from \"@ohkit/platform\";\nimport {rgbaToObj, findEffectiveBgColor} from \"@ohkit/dom-helper\";\nimport {Measure, MeasureProps} from \"@ohkit/measure\";\nimport \"./style.scss\";\n\nexport const c = p(\"ohkit-text-ellipsis__\");\n\ninterface ITextEllipsis\n extends Pick<\n React.DOMAttributes<HTMLDivElement>,\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onFocus\"\n | \"onClick\"\n > {\n /**\n * 自定义样式类名,会附加到根元素上\n */\n className?: string;\n /**\n * 自定义样式\n */\n style?: React.CSSProperties;\n /**\n * right | bottom 展开按钮在右下侧还是底部\n * @default right\n */\n uiType?: \"right\" | \"bottom\";\n /**\n * 截断模式 (若某些浏览器不支持 webkitLineClamp,可降级切换为 height 模式)\n * @default line\n */\n truncateMode?: \"line\" | \"height\";\n /**\n * truncateMode === \"height\" 时生效\n * 最大高度(number > 0),没传或者传入无效值不限制,尝试取 lines * lineHeight,若仍无效 自动截断到容器的最大高度\n * 单位: px\n */\n maxHeight?: number;\n /**\n * (单位:px)未传入或无效(0也视为无效)则自动取当前文本的行高\n */\n lineHeight?: React.CSSProperties[\"lineHeight\"];\n /**\n * truncateMode === \"line\" 时生效\n * 超过几行折叠(number > 0), 没传或者传入无效值不限制,自动截断到容器的最大高度\n */\n lines?: number;\n /**\n * 展开按钮蒙层背景色(仅支持16进制表示)\n * @default #fff\n */\n maskBgColor?: string;\n /**\n * text|ReactNode 与children任传一个\n */\n content?: React.ReactNode;\n /**\n * 当 content or children or ellipsis 变化时,重置 fold 状态 \n * @default false\n */\n resetFoldWhenChildrenOrEllipsisChange?: boolean;\n /**\n * 折叠状态\n * @default true\n */\n fold?: boolean;\n /**\n * 显示展开控制按钮\n * @default true\n */\n showFoldControl?: boolean;\n /**\n * 展开按钮位置 uiType='bottom'时有效\n * @default center\n */\n controlPlacement?: 'left' | 'center' | 'right';\n /**\n * 折叠按钮文字\n * @default 收起\n */\n foldText?: string;\n /**\n * 展开按钮文字\n * @default 展开\n */\n unfoldText?: string;\n /**\n * 折叠状态下是否显示title属性\n * @default false\n */\n showTitleWhenFold?: boolean;\n /**\n * 折叠状态自定义title属性内容\n */\n titleWhenFold?: string | ((title: string) => string);\n /**\n * 是否保留换行\n */\n whiteSpace?: React.CSSProperties['whiteSpace'];\n /**\n * 容器宽度(默认自适应内容)\n * 应用场景:whiteSpace='pre*' 时,支持展示换行符,自适应内容可能导致控制按钮位置不确定\n */\n width?: React.CSSProperties['width'];\n /**\n * 自定义渲染展开按钮\n */\n renderFoldButton?: (fold: boolean) => React.ReactNode;\n /**\n * @param fold 折叠状态,true 折叠,false 展开\n */\n onFoldChange?: (fold: boolean) => void;\n /**\n * @param ellipsis 是否截断,true 截断,false 未截断\n */\n onEllipsisChange?: (ellipsis: boolean) => void;\n /**\n * 关键状态变更触发\n * @param status\n */\n onStatusChange?: (status: {\n fold: boolean;\n ellipsis: boolean;\n title?: string;\n }) => void;\n}\n\nexport type TextEllipsisProps = PropsWithChildren<ITextEllipsis>;\n\nexport const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>((props, ref) => {\n const {\n className,\n style,\n lineHeight = \"\",\n lines,\n maskBgColor,\n content,\n children,\n resetFoldWhenChildrenOrEllipsisChange = false,\n showTitleWhenFold,\n titleWhenFold,\n showFoldControl = true,\n foldText = \"收起\",\n unfoldText = \"展开\",\n uiType = \"right\",\n truncateMode = \"line\",\n maxHeight,\n controlPlacement = 'center',\n whiteSpace,\n width,\n renderFoldButton,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n onMouseEnter,\n onMouseLeave,\n onPointerEnter,\n onPointerLeave,\n onClick,\n onFocus,\n } = props;\n const finalContent = content || children;\n // 是否截断\n const [ellipsis, setEllipsis] = useState(false);\n const [getLineHeightFail, setGetLineHeightFail] = useState(false);\n // 折叠状态\n const [fold, setFold] = useSyncPropsState(props, 'fold', {defaultValue: true, onChange: onFoldChange});\n const [foldBtnWidth, setFoldBtnWidth] = useState(1);\n const [innerLineHeight, setInnerLineHeight] = useState(\n typeof lineHeight === \"string\" && lineHeight.endsWith(\"px\")\n ? parseFloat(lineHeight)\n : 0\n );\n const [innerLines = 0, setInnerLines] = useState(lines);\n // children提取的纯文本\n const [textContent, setTextContent] = useState('');\n\n const [runtime] = useRuntime({\n inited: false, // mounted\n contentOffsetHeight: 0, // 内容节点offsetHeight\n containerContentHeight: 0, // 容器内容高度 = 容器高 - 上下padding\n ellipsis,\n defaultFold: fold, // 记录一下默认的折叠状态,用于 reset fold\n fold,\n foldBtnWidth,\n textContent,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n }, ['fold', 'onEllipsisChange', 'onFoldChange', 'onStatusChange']);\n\n const contentRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const btnWrapperRef = useRef<HTMLDivElement>(null);\n\n const containerStyle = useMemo(() => {\n return {\n lineHeight: getLineHeightFail // 未传入且获取 lineHeight(px) 失败,则设置 default lineHeight: 1.4(em)\n ? \"1.4\" // more brower normal default lineHeight\n : lineHeight ? lineHeight : undefined,\n ...style,\n };\n }, [style, lineHeight, getLineHeightFail]);\n\n const commonWrapStyle = useMemo(() => {\n return {\n whiteSpace,\n width,\n };\n }, [whiteSpace, width]);\n // 容器样式\n const wrapStyle = useMemo(() => {\n const lines = innerLines;\n const isHeightMode = truncateMode === 'height';\n if (!ellipsis || !isHeightMode && (!lines || !innerLineHeight)) {\n return commonWrapStyle;\n }\n const paddingBottom = showFoldControl && (uiType === \"bottom\" && !fold) ? `${innerLineHeight}px` : undefined;\n return {\n ...commonWrapStyle,\n // HACK: 兼容safari 15+ 富文本折叠高度丢失问题\n minHeight: !isHeightMode && fold ? `${(lines - 0.2) * innerLineHeight}px` : undefined,\n // Note: safari 对WebkitLineClamp支持太差劲 判断浏览器优雅降级为高度截断方案?目前先交给用户去判断,自行选择truncateMode\n // WebkitLineClamp: isSafari ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n // maxHeight: isSafari && fold ? lines * innerLineHeight : undefined,\n WebkitLineClamp: isHeightMode ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n maxHeight: isHeightMode && fold ? (maxHeight || lines * innerLineHeight || runtime.containerContentHeight || 0) : undefined,\n paddingBottom,\n boxSizing: paddingBottom ? 'border-box' as const : undefined,\n };\n }, [innerLines, innerLineHeight, ellipsis, fold, showFoldControl, uiType, truncateMode, maxHeight, commonWrapStyle]);\n\n // 计算折叠按钮蒙层的渐变颜色\n const validMaskBgColor = useMemo(() => {\n if (!showFoldControl || !ellipsis) {\n return null;\n }\n const {r, g, b} = rgbaToObj(maskBgColor || '') || findEffectiveBgColor(containerRef.current);\n return {\n startColor: `rgba(${r}, ${g}, ${b}, 0.2)`,\n endColor: `rgba(${r}, ${g}, ${b}, 1)`,\n };\n }, [maskBgColor, ellipsis, showFoldControl]);\n\n // 展开|收起 按钮样式\n const btnStyle = useMemo(() => {\n if (!fold) {\n return;\n }\n // 按钮padding,取行高\n const padding = innerLineHeight;\n // 蒙层透明度所占比例\n const ratio = uiType === \"right\" ? Math.min((padding / foldBtnWidth) * 100, 80) : 60;\n const {startColor = 'rgba(255,255,255,0.2)', endColor = 'rgba(255,255,255,1)'} = validMaskBgColor || {};\n return {\n boxSizing: 'content-box' as const,\n height: `${innerLineHeight}px`,\n lineHeight: `${innerLineHeight}px`,\n paddingTop: uiType === \"bottom\" ? `${padding}px` : undefined,\n paddingLeft: uiType === \"right\" ? `${padding}px` : undefined,\n // 渐变蒙层\n background: `linear-gradient(to ${uiType}, ${startColor}, ${endColor} ${ratio}%, ${endColor} 100%)`,\n };\n }, [innerLineHeight, fold, uiType, foldBtnWidth, validMaskBgColor]);\n\n const reorganizeDom = useCallback(() => {\n // Note: safari 中仅改变 WebkitLineClamp 没触发重排,调整微小宽度以触发\n if (contentRef.current) {\n const orginStyleWidth = contentRef.current.style.width;\n const orginWidth = window.getComputedStyle(contentRef.current).width;\n // console.log('orginWidth, orginStyleWidth:', orginWidth, orginStyleWidth);\n contentRef.current.style.width = `${parseFloat(orginWidth) - 0.1}px`;\n window.requestAnimationFrame?.(() => {\n if (contentRef.current) {\n contentRef.current.style.width = orginStyleWidth;\n }\n });\n }\n }, []);\n\n const handleFoldChange = useCallback(\n (evt?: MouseEvent<HTMLDivElement>, fold = !runtime.fold) => {\n runtime.fold = fold;\n setFold(fold);\n }, []);\n\n const ButtonComp = useMemo(() => {\n return (\n <div\n className={cx(\n \"btn-fold-wrapper\",\n `btn-fold-wrapper-${uiType}`,\n uiType === \"bottom\" && `placement-${controlPlacement}`\n )}\n style={btnStyle}\n ref={btnWrapperRef}\n onClick={handleFoldChange}\n >\n {renderFoldButton ? (\n renderFoldButton(fold)\n ) : (\n <div className={\"btn-fold\"}>{fold ? unfoldText : foldText}</div>\n )}\n </div>\n );\n }, [\n btnStyle,\n fold,\n foldText,\n handleFoldChange,\n renderFoldButton,\n controlPlacement,\n uiType,\n unfoldText,\n ]);\n\n // 占位按钮\n const ButtonShadowDom = useMemo(() => {\n if (!showFoldControl || uiType !== 'right' || fold) {\n return null;\n }\n return <span style={btnStyle} className=\"btn-fold-right-shadow\">\n {renderFoldButton ? renderFoldButton(fold) : foldText}\n </span>;\n }, [uiType, showFoldControl, fold, btnStyle, foldText, renderFoldButton]);\n\n // 重置状态\n const resetState = useCallback((newEllipsis = runtime.ellipsis, {\n forceResetFold = false, // 强制重置fold 比如child变化时\n } = {}) => {\n const {ellipsis, fold: preFold, defaultFold} = runtime;\n if (newEllipsis !== ellipsis) {\n setEllipsis(newEllipsis);\n runtime.ellipsis = newEllipsis;\n runtime.onEllipsisChange?.(newEllipsis);\n }\n // 从未截断状态切换为截断状态时,自动折叠(即:出现展开按钮)\n if (\n resetFoldWhenChildrenOrEllipsisChange\n && (forceResetFold || !ellipsis && newEllipsis)\n && preFold !== defaultFold\n ) {\n handleFoldChange(undefined, defaultFold);\n }\n }, [handleFoldChange, finalContent, resetFoldWhenChildrenOrEllipsisChange]);\n\n const calcEllipsis = useCallback(() => {\n const wrapDom = wrapperRef.current;\n const containerDom = containerRef.current;\n if (!wrapDom || !containerDom) {\n return;\n }\n runtime.contentOffsetHeight = wrapDom.offsetHeight;\n const containerStyle = window.getComputedStyle(containerDom);\n const paddingTop = parseFloat(containerStyle.paddingTop);\n const paddingBottom = parseFloat(containerStyle.paddingBottom);\n const containerContentHeight = runtime.containerContentHeight = containerDom.clientHeight - paddingTop - paddingBottom;\n\n // 计算真实行高\n let realLineHeight = 0;\n // 若外部未传入, 尝试读取当前文本的行高。\n if (!realLineHeight && wrapDom) {\n const {lineHeight} = containerStyle || {};\n if (lineHeight) {\n // 未设置行高的为 normal\n realLineHeight = parseFloat(lineHeight);\n if (!realLineHeight) {\n setGetLineHeightFail(true);\n }\n }\n }\n // lineHeight同步到innerLineHeight\n if (innerLineHeight !== realLineHeight) {\n setInnerLineHeight(realLineHeight);\n if (!realLineHeight) {\n return;\n }\n }\n\n const isHeightMode = truncateMode === 'height';\n // 高度截断模式,比较简单 直接判断是否超出容器高度\n if (isHeightMode) {\n resetState(runtime.contentOffsetHeight > (maxHeight || containerContentHeight));\n return;\n }\n\n // 行数截断模式,需要利用行高计算是否超出容器高度\n if (!lines) {\n if (runtime.contentOffsetHeight > containerContentHeight) {\n const adjustLines = Math.floor(containerContentHeight / realLineHeight) || 1;\n if (innerLines !== adjustLines) {\n setInnerLines(adjustLines);\n }\n resetState(true);\n } else {\n resetState(false);\n }\n } else {\n if (innerLines !== lines) {\n setInnerLines(lines);\n }\n // console.log('contentOffsetHeight, realLineHeight', runtime.contentOffsetHeight, realLineHeight);\n // 允许误差1px(行高为小数时, safari计算行高*行数和实践总高有差异,故将行高向下取整兼容)\n resetState(runtime.contentOffsetHeight >= (lines + 1) * Math.floor(realLineHeight) - 1);\n }\n }, [lines, innerLineHeight, truncateMode, maxHeight, resetState]);\n\n // 监听内容高度,是否需要折叠\n // 用useLayoutEffect方式闪屏显示\n useCompatibleEffect(() => {\n resetState(runtime.ellipsis, {\n forceResetFold: true,\n });\n calcEllipsis();\n }, [calcEllipsis, resetState]);\n\n // 监听\"展开\"按钮宽度变化\n useEffect(() => {\n if (ellipsis && btnWrapperRef.current) {\n const {offsetWidth} = btnWrapperRef.current;\n if (offsetWidth !== runtime.foldBtnWidth) {\n runtime.foldBtnWidth = offsetWidth;\n setFoldBtnWidth(offsetWidth);\n }\n }\n }, [ellipsis, unfoldText, showFoldControl]);\n useEffect(() => {\n if (isSafari) {\n reorganizeDom();\n }\n }, [fold, reorganizeDom]);\n const updateTextContent = useCallback(() => {\n if (!wrapperRef.current) {\n return;\n }\n const newTextContent = wrapperRef.current.textContent || '';\n if (newTextContent !== runtime.textContent) {\n runtime.textContent = newTextContent;\n setTextContent(newTextContent);\n }\n }, []);\n const handleResize = useCallback<NonNullable<MeasureProps['onResize']>>((rect) => {\n // console.log('[handleResize] rect: ', rect, runtime.contentOffsetHeight);\n const {height} = rect.offset || {};\n if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n calcEllipsis();\n }\n }, [calcEllipsis]);\n const hoverTitle = useMemo(() => {\n return ellipsis && fold\n ? (typeof titleWhenFold === 'function'\n ? titleWhenFold(textContent)\n : titleWhenFold || textContent)\n : undefined;\n }, [titleWhenFold, ellipsis, fold, textContent]);\n useEffect(() => {\n if (runtime.inited) { \n runtime.onStatusChange?.({\n ellipsis,\n fold,\n title: hoverTitle\n });\n }\n }, [fold, ellipsis, hoverTitle]);\n useEffect(() => {\n runtime.inited = true;\n }, []);\n // 高度自适应,容器高度变化时重新计算高度(容器也需要包装Measure,TODO: 待开发 hooks -> useMeasure, 使得观测dom尺寸的方式更简洁)\n // if (!maxHeight && !lines) {\n // calcEllipsis();\n // }\n // console.log('[render TextEllipsis]: ellipsis fold wrapStyle: ', ellipsis, fold, wrapStyle);\n return (\n <div\n className={cx(c(\"container\"), className)}\n style={containerStyle}\n ref={(r) => {\n assignRef(containerRef, r);\n ref && assignRef(ref, r);\n }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onPointerEnter={onPointerEnter}\n onPointerLeave={onPointerLeave}\n onClick={onClick}\n onFocus={onFocus}\n >\n {/* 此dom仅用于计算高度 用.text-ellipsis-inner计算 在不重新初始化情况下切换文本时高度计算有问题 */}\n <Measure offset throttleMs={100} onResize={handleResize} triggerResizeInit={false}>\n {({measureRef, /* contentRect */}) => {\n // console.log('contentRect:', contentRect, contentRect.offset?.height, runtime.contentOffsetHeight);\n // const {height} = contentRect.offset || {};\n // if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n // calcEllipsis();\n // }\n return <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={(r) => {\n assignRef(measureRef, r);\n assignRef(wrapperRef, r);\n updateTextContent();\n }}>\n {finalContent}\n </div>\n }}\n </Measure>\n {/* <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={wrapperRef}>\n {finalContent}\n </div> */}\n {/* 主文本显示 */}\n <div\n className={\"text-ellipsis-inner\"}\n title={showTitleWhenFold ? hoverTitle : undefined}\n style={wrapStyle}\n ref={contentRef}\n >\n {/* {finalContent} */}\n {/* firefox >= 133 绝对定位的按钮放文本后面也会被截断隐藏!! , 放文本前面可解决 */}\n {ellipsis && showFoldControl && ButtonComp}\n {finalContent}\n {ButtonShadowDom}\n </div>\n </div>\n );\n});\n"],"names":["c","p","TextEllipsis","forwardRef","props","ref","className","style","lineHeight","lines","maskBgColor","content","children","resetFoldWhenChildrenOrEllipsisChange","showTitleWhenFold","titleWhenFold","showFoldControl","foldText","unfoldText","uiType","truncateMode","maxHeight","controlPlacement","whiteSpace","width","renderFoldButton","onEllipsisChange","onFoldChange","onStatusChange","onMouseEnter","onMouseLeave","onPointerEnter","onPointerLeave","onClick","onFocus","finalContent","ellipsis","setEllipsis","useState","getLineHeightFail","setGetLineHeightFail","fold","setFold","useSyncPropsState","defaultValue","onChange","foldBtnWidth","setFoldBtnWidth","innerLineHeight","setInnerLineHeight","endsWith","parseFloat","innerLines","setInnerLines","textContent","setTextContent","runtime","useRuntime","inited","contentOffsetHeight","containerContentHeight","defaultFold","contentRef","useRef","wrapperRef","containerRef","btnWrapperRef","containerStyle","useMemo","_extends","undefined","commonWrapStyle","wrapStyle","isHeightMode","paddingBottom","minHeight","WebkitLineClamp","boxSizing","validMaskBgColor","r","g","b","rgbaToObj","findEffectiveBgColor","current","startColor","endColor","btnStyle","padding","ratio","Math","min","height","paddingTop","paddingLeft","background","reorganizeDom","useCallback","orginStyleWidth","orginWidth","window","getComputedStyle","requestAnimationFrame","handleFoldChange","evt","ButtonComp","React","createElement","cx","ButtonShadowDom","resetState","newEllipsis","forceResetFold","preFold","calcEllipsis","wrapDom","containerDom","offsetHeight","clientHeight","realLineHeight","floor","adjustLines","useCompatibleEffect","useEffect","offsetWidth","isSafari","updateTextContent","newTextContent","handleResize","rect","offset","abs","hoverTitle","title","assignRef","Measure","throttleMs","onResize","triggerResizeInit","measureRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.modern.mjs","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @file 文本截断显示组件\n * @description 基于React封装一个文本截断显示组件,富文本(仅文字样式,图片和表格效果不一定好)同普通文本处理一致\n * @author <wuqiuyang305@126.com>\n */\n\nimport React, {\n forwardRef,\n useState,\n useMemo,\n useEffect,\n useCallback,\n useRef,\n PropsWithChildren,\n MouseEvent,\n} from \"react\";\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {\n assignRef,\n useRuntime,\n useCompatibleEffect,\n useSyncPropsState,\n} from \"@ohkit/react-helper\";\nimport {isSafari} from \"@ohkit/platform\";\nimport {rgbaToObj, findEffectiveBgColor} from \"@ohkit/dom-helper\";\nimport {Measure, MeasureProps} from \"@ohkit/measure\";\nimport \"./style.scss\";\n\nexport const c = p(\"ohkit-text-ellipsis__\");\n\ninterface ITextEllipsis\n extends Pick<\n React.DOMAttributes<HTMLDivElement>,\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onFocus\"\n | \"onClick\"\n > {\n /**\n * 自定义样式类名,会附加到根元素上\n */\n className?: string;\n /**\n * 自定义样式\n */\n style?: React.CSSProperties;\n /**\n * right | bottom 展开按钮在右下侧还是底部\n * @default right\n */\n uiType?: \"right\" | \"bottom\";\n /**\n * 截断模式 (若某些浏览器不支持 webkitLineClamp,可降级切换为 height 模式)\n * @default line\n */\n truncateMode?: \"line\" | \"height\";\n /**\n * truncateMode === \"height\" 时生效\n * 最大高度(number > 0),没传或者传入无效值不限制,尝试取 lines * lineHeight,若仍无效 自动截断到容器的最大高度\n * 单位: px\n */\n maxHeight?: number;\n /**\n * (单位:px)未传入或无效(0也视为无效)则自动取当前文本的行高\n */\n lineHeight?: React.CSSProperties[\"lineHeight\"];\n /**\n * truncateMode === \"line\" 时生效\n * 超过几行折叠(number > 0), 没传或者传入无效值不限制,自动截断到容器的最大高度\n */\n lines?: number;\n /**\n * 展开按钮蒙层背景色(仅支持16进制表示)\n * @default #fff\n */\n maskBgColor?: string;\n /**\n * text|ReactNode 与children任传一个\n */\n content?: React.ReactNode;\n /**\n * 当 content or children or ellipsis 变化时,重置 fold 状态 \n * @default false\n */\n resetFoldWhenChildrenOrEllipsisChange?: boolean;\n /**\n * 折叠状态\n * @default true\n */\n fold?: boolean;\n /**\n * 显示展开控制按钮\n * @default true\n */\n showFoldControl?: boolean;\n /**\n * 展开按钮位置 uiType='bottom'时有效\n * @default center\n */\n controlPlacement?: 'left' | 'center' | 'right';\n /**\n * 折叠按钮文字\n * @default 收起\n */\n foldText?: string;\n /**\n * 展开按钮文字\n * @default 展开\n */\n unfoldText?: string;\n /**\n * 折叠状态下是否显示title属性\n * @default false\n */\n showTitleWhenFold?: boolean;\n /**\n * 折叠状态自定义title属性内容\n */\n titleWhenFold?: string | ((title: string) => string);\n /**\n * 是否保留换行\n */\n whiteSpace?: React.CSSProperties['whiteSpace'];\n /**\n * 容器宽度(默认自适应内容)\n * 应用场景:whiteSpace='pre*' 时,支持展示换行符,自适应内容可能导致控制按钮位置不确定\n */\n width?: React.CSSProperties['width'];\n /**\n * 自定义渲染展开按钮\n */\n renderFoldButton?: (fold: boolean) => React.ReactNode;\n /**\n * @param fold 折叠状态,true 折叠,false 展开\n */\n onFoldChange?: (fold: boolean) => void;\n /**\n * @param ellipsis 是否截断,true 截断,false 未截断\n */\n onEllipsisChange?: (ellipsis: boolean) => void;\n /**\n * 关键状态变更触发\n * @param status\n */\n onStatusChange?: (status: {\n fold: boolean;\n ellipsis: boolean;\n title?: string;\n }) => void;\n}\n\nexport type TextEllipsisProps = PropsWithChildren<ITextEllipsis>;\n\nexport const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>(function TextEllipsis(props, ref) {\n const {\n className,\n style,\n lineHeight = \"\",\n lines,\n maskBgColor,\n content,\n children,\n resetFoldWhenChildrenOrEllipsisChange = false,\n showTitleWhenFold,\n titleWhenFold,\n showFoldControl = true,\n foldText = \"收起\",\n unfoldText = \"展开\",\n uiType = \"right\",\n truncateMode = \"line\",\n maxHeight,\n controlPlacement = 'center',\n whiteSpace,\n width,\n renderFoldButton,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n onMouseEnter,\n onMouseLeave,\n onPointerEnter,\n onPointerLeave,\n onClick,\n onFocus,\n } = props;\n const finalContent = content || children;\n // 是否截断\n const [ellipsis, setEllipsis] = useState(false);\n const [getLineHeightFail, setGetLineHeightFail] = useState(false);\n // 折叠状态\n const [fold, setFold] = useSyncPropsState(props, 'fold', {defaultValue: true, onChange: onFoldChange});\n const [foldBtnWidth, setFoldBtnWidth] = useState(1);\n const [innerLineHeight, setInnerLineHeight] = useState(\n typeof lineHeight === \"string\" && lineHeight.endsWith(\"px\")\n ? parseFloat(lineHeight)\n : 0\n );\n const [innerLines = 0, setInnerLines] = useState(lines);\n // children提取的纯文本\n const [textContent, setTextContent] = useState('');\n\n const [runtime] = useRuntime({\n inited: false, // mounted\n contentOffsetHeight: 0, // 内容节点offsetHeight\n containerContentHeight: 0, // 容器内容高度 = 容器高 - 上下padding\n ellipsis,\n defaultFold: fold, // 记录一下默认的折叠状态,用于 reset fold\n fold,\n foldBtnWidth,\n textContent,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n }, ['fold', 'onEllipsisChange', 'onFoldChange', 'onStatusChange']);\n\n const contentRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const btnWrapperRef = useRef<HTMLDivElement>(null);\n\n const containerStyle = useMemo(() => {\n return {\n lineHeight: getLineHeightFail // 未传入且获取 lineHeight(px) 失败,则设置 default lineHeight: 1.4(em)\n ? \"1.4\" // more brower normal default lineHeight\n : lineHeight ? lineHeight : undefined,\n ...style,\n };\n }, [style, lineHeight, getLineHeightFail]);\n\n const commonWrapStyle = useMemo(() => {\n return {\n whiteSpace,\n width,\n };\n }, [whiteSpace, width]);\n // 容器样式\n const wrapStyle = useMemo(() => {\n const lines = innerLines;\n const isHeightMode = truncateMode === 'height';\n if (!ellipsis || !isHeightMode && (!lines || !innerLineHeight)) {\n return commonWrapStyle;\n }\n const paddingBottom = showFoldControl && (uiType === \"bottom\" && !fold) ? `${innerLineHeight}px` : undefined;\n return {\n ...commonWrapStyle,\n // HACK: 兼容safari 15+ 富文本折叠高度丢失问题\n minHeight: !isHeightMode && fold ? `${(lines - 0.2) * innerLineHeight}px` : undefined,\n // Note: safari 对WebkitLineClamp支持太差劲 判断浏览器优雅降级为高度截断方案?目前先交给用户去判断,自行选择truncateMode\n // WebkitLineClamp: isSafari ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n // maxHeight: isSafari && fold ? lines * innerLineHeight : undefined,\n WebkitLineClamp: isHeightMode ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n maxHeight: isHeightMode && fold ? (maxHeight || lines * innerLineHeight || runtime.containerContentHeight || 0) : undefined,\n paddingBottom,\n boxSizing: paddingBottom ? 'border-box' as const : undefined,\n };\n }, [innerLines, innerLineHeight, ellipsis, fold, showFoldControl, uiType, truncateMode, maxHeight, commonWrapStyle]);\n\n // 计算折叠按钮蒙层的渐变颜色\n const validMaskBgColor = useMemo(() => {\n if (!showFoldControl || !ellipsis) {\n return null;\n }\n const {r, g, b} = rgbaToObj(maskBgColor || '') || findEffectiveBgColor(containerRef.current);\n return {\n startColor: `rgba(${r}, ${g}, ${b}, 0.2)`,\n endColor: `rgba(${r}, ${g}, ${b}, 1)`,\n };\n }, [maskBgColor, ellipsis, showFoldControl]);\n\n // 展开|收起 按钮样式\n const btnStyle = useMemo(() => {\n if (!fold) {\n return;\n }\n // 按钮padding,取行高\n const padding = innerLineHeight;\n // 蒙层透明度所占比例\n const ratio = uiType === \"right\" ? Math.min((padding / foldBtnWidth) * 100, 80) : 60;\n const {startColor = 'rgba(255,255,255,0.2)', endColor = 'rgba(255,255,255,1)'} = validMaskBgColor || {};\n return {\n boxSizing: 'content-box' as const,\n height: `${innerLineHeight}px`,\n lineHeight: `${innerLineHeight}px`,\n paddingTop: uiType === \"bottom\" ? `${padding}px` : undefined,\n paddingLeft: uiType === \"right\" ? `${padding}px` : undefined,\n // 渐变蒙层\n background: `linear-gradient(to ${uiType}, ${startColor}, ${endColor} ${ratio}%, ${endColor} 100%)`,\n };\n }, [innerLineHeight, fold, uiType, foldBtnWidth, validMaskBgColor]);\n\n const reorganizeDom = useCallback(() => {\n // Note: safari 中仅改变 WebkitLineClamp 没触发重排,调整微小宽度以触发\n if (contentRef.current) {\n const orginStyleWidth = contentRef.current.style.width;\n const orginWidth = window.getComputedStyle(contentRef.current).width;\n // console.log('orginWidth, orginStyleWidth:', orginWidth, orginStyleWidth);\n contentRef.current.style.width = `${parseFloat(orginWidth) - 0.1}px`;\n window.requestAnimationFrame?.(() => {\n if (contentRef.current) {\n contentRef.current.style.width = orginStyleWidth;\n }\n });\n }\n }, []);\n\n const handleFoldChange = useCallback(\n (evt?: MouseEvent<HTMLDivElement>, fold = !runtime.fold) => {\n runtime.fold = fold;\n setFold(fold);\n }, []);\n\n const ButtonComp = useMemo(() => {\n return (\n <div\n className={cx(\n \"btn-fold-wrapper\",\n `btn-fold-wrapper-${uiType}`,\n uiType === \"bottom\" && `placement-${controlPlacement}`\n )}\n style={btnStyle}\n ref={btnWrapperRef}\n onClick={handleFoldChange}\n >\n {renderFoldButton ? (\n renderFoldButton(fold)\n ) : (\n <div className={\"btn-fold\"}>{fold ? unfoldText : foldText}</div>\n )}\n </div>\n );\n }, [\n btnStyle,\n fold,\n foldText,\n handleFoldChange,\n renderFoldButton,\n controlPlacement,\n uiType,\n unfoldText,\n ]);\n\n // 占位按钮\n const ButtonShadowDom = useMemo(() => {\n if (!ellipsis || !showFoldControl || uiType !== 'right' || fold) {\n return null;\n }\n return <span style={btnStyle} className=\"btn-fold-right-shadow\">\n {renderFoldButton ? renderFoldButton(fold) : foldText}\n </span>;\n }, [ellipsis, uiType, showFoldControl, fold, btnStyle, foldText, renderFoldButton]);\n\n // 重置状态\n const resetState = useCallback((newEllipsis = runtime.ellipsis, {\n forceResetFold = false, // 强制重置fold 比如child变化时\n } = {}) => {\n const {ellipsis, fold: preFold, defaultFold} = runtime;\n if (newEllipsis !== ellipsis) {\n setEllipsis(newEllipsis);\n runtime.ellipsis = newEllipsis;\n runtime.onEllipsisChange?.(newEllipsis);\n }\n // 从未截断状态切换为截断状态时,自动折叠(即:出现展开按钮)\n if (\n resetFoldWhenChildrenOrEllipsisChange\n && (forceResetFold || !ellipsis && newEllipsis)\n && preFold !== defaultFold\n ) {\n handleFoldChange(undefined, defaultFold);\n }\n }, [handleFoldChange, finalContent, resetFoldWhenChildrenOrEllipsisChange]);\n\n const calcEllipsis = useCallback(() => {\n const wrapDom = wrapperRef.current;\n const containerDom = containerRef.current;\n if (!wrapDom || !containerDom) {\n return;\n }\n runtime.contentOffsetHeight = wrapDom.offsetHeight;\n const containerStyle = window.getComputedStyle(containerDom);\n const paddingTop = parseFloat(containerStyle.paddingTop);\n const paddingBottom = parseFloat(containerStyle.paddingBottom);\n const containerContentHeight = runtime.containerContentHeight = containerDom.clientHeight - paddingTop - paddingBottom;\n\n // 计算真实行高\n let realLineHeight = 0;\n // 若外部未传入, 尝试读取当前文本的行高。\n if (!realLineHeight && wrapDom) {\n const {lineHeight} = containerStyle || {};\n if (lineHeight) {\n // 未设置行高的为 normal\n realLineHeight = parseFloat(lineHeight);\n if (!realLineHeight) {\n setGetLineHeightFail(true);\n }\n }\n }\n // lineHeight同步到innerLineHeight\n if (innerLineHeight !== realLineHeight) {\n setInnerLineHeight(realLineHeight);\n if (!realLineHeight) {\n return;\n }\n }\n\n const isHeightMode = truncateMode === 'height';\n // 高度截断模式,比较简单 直接判断是否超出容器高度\n if (isHeightMode) {\n resetState(runtime.contentOffsetHeight > (maxHeight || containerContentHeight));\n return;\n }\n\n // 行数截断模式,需要利用行高计算是否超出容器高度\n if (!lines) {\n if (runtime.contentOffsetHeight > containerContentHeight) {\n const adjustLines = Math.floor(containerContentHeight / realLineHeight) || 1;\n if (innerLines !== adjustLines) {\n setInnerLines(adjustLines);\n }\n resetState(true);\n } else {\n resetState(false);\n }\n } else {\n if (innerLines !== lines) {\n setInnerLines(lines);\n }\n // console.log('contentOffsetHeight, realLineHeight', runtime.contentOffsetHeight, realLineHeight);\n // 允许误差1px(行高为小数时, safari计算行高*行数和实践总高有差异,故将行高向下取整兼容)\n resetState(runtime.contentOffsetHeight >= (lines + 1) * Math.floor(realLineHeight) - 1);\n }\n }, [lines, innerLineHeight, truncateMode, maxHeight, resetState]);\n\n // 监听内容高度,是否需要折叠\n // 用useLayoutEffect方式闪屏显示\n useCompatibleEffect(() => {\n resetState(runtime.ellipsis, {\n forceResetFold: true,\n });\n calcEllipsis();\n }, [calcEllipsis, resetState]);\n\n // 监听\"展开\"按钮宽度变化\n useEffect(() => {\n if (ellipsis && btnWrapperRef.current) {\n const {offsetWidth} = btnWrapperRef.current;\n if (offsetWidth !== runtime.foldBtnWidth) {\n runtime.foldBtnWidth = offsetWidth;\n setFoldBtnWidth(offsetWidth);\n }\n }\n }, [ellipsis, unfoldText, showFoldControl]);\n useEffect(() => {\n if (isSafari) {\n reorganizeDom();\n }\n }, [fold, reorganizeDom]);\n const updateTextContent = useCallback(() => {\n if (!wrapperRef.current) {\n return;\n }\n const newTextContent = wrapperRef.current.textContent || '';\n if (newTextContent !== runtime.textContent) {\n runtime.textContent = newTextContent;\n setTextContent(newTextContent);\n }\n }, []);\n const handleResize = useCallback<NonNullable<MeasureProps['onResize']>>((rect) => {\n // console.log('[handleResize] rect: ', rect, runtime.contentOffsetHeight);\n const {height} = rect.offset || {};\n if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n calcEllipsis();\n }\n }, [calcEllipsis]);\n const hoverTitle = useMemo(() => {\n return ellipsis && fold\n ? (typeof titleWhenFold === 'function'\n ? titleWhenFold(textContent)\n : titleWhenFold || textContent)\n : undefined;\n }, [titleWhenFold, ellipsis, fold, textContent]);\n useEffect(() => {\n if (runtime.inited) { \n runtime.onStatusChange?.({\n ellipsis,\n fold,\n title: hoverTitle\n });\n }\n }, [fold, ellipsis, hoverTitle]);\n useEffect(() => {\n runtime.inited = true;\n }, []);\n // 高度自适应,容器高度变化时重新计算高度(容器也需要包装Measure,TODO: 待开发 hooks -> useMeasure, 使得观测dom尺寸的方式更简洁)\n // if (!maxHeight && !lines) {\n // calcEllipsis();\n // }\n // console.log('[render TextEllipsis]: ellipsis fold wrapStyle: ', ellipsis, fold, wrapStyle);\n return (\n <div\n className={cx(c(\"container\"), className)}\n style={containerStyle}\n ref={(r) => {\n assignRef(containerRef, r);\n if (ref) {\n assignRef(ref, r);\n }\n }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onPointerEnter={onPointerEnter}\n onPointerLeave={onPointerLeave}\n onClick={onClick}\n onFocus={onFocus}\n >\n {/* 此dom仅用于计算高度 用.text-ellipsis-inner计算 在不重新初始化情况下切换文本时高度计算有问题 */}\n <Measure offset throttleMs={100} onResize={handleResize} triggerResizeInit={false}>\n {({measureRef, /* contentRect */}) => {\n // console.log('contentRect:', contentRect, contentRect.offset?.height, runtime.contentOffsetHeight);\n // const {height} = contentRect.offset || {};\n // if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n // calcEllipsis();\n // }\n return <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={(r) => {\n assignRef(measureRef, r);\n assignRef(wrapperRef, r);\n updateTextContent();\n }}>\n {finalContent}\n </div>\n }}\n </Measure>\n {/* <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={wrapperRef}>\n {finalContent}\n </div> */}\n {/* 主文本显示 */}\n <div\n className={\"text-ellipsis-inner\"}\n title={showTitleWhenFold ? hoverTitle : undefined}\n style={wrapStyle}\n ref={contentRef}\n >\n {/* {finalContent} */}\n {/* firefox >= 133 绝对定位的按钮放文本后面也会被截断隐藏!! , 放文本前面可解决 */}\n {ellipsis && showFoldControl && ButtonComp}\n {finalContent}\n {ButtonShadowDom}\n </div>\n </div>\n );\n});\n"],"names":["c","p","TextEllipsis","forwardRef","props","ref","className","style","lineHeight","lines","maskBgColor","content","children","resetFoldWhenChildrenOrEllipsisChange","showTitleWhenFold","titleWhenFold","showFoldControl","foldText","unfoldText","uiType","truncateMode","maxHeight","controlPlacement","whiteSpace","width","renderFoldButton","onEllipsisChange","onFoldChange","onStatusChange","onMouseEnter","onMouseLeave","onPointerEnter","onPointerLeave","onClick","onFocus","finalContent","ellipsis","setEllipsis","useState","getLineHeightFail","setGetLineHeightFail","fold","setFold","useSyncPropsState","defaultValue","onChange","foldBtnWidth","setFoldBtnWidth","innerLineHeight","setInnerLineHeight","endsWith","parseFloat","innerLines","setInnerLines","textContent","setTextContent","runtime","useRuntime","inited","contentOffsetHeight","containerContentHeight","defaultFold","contentRef","useRef","wrapperRef","containerRef","btnWrapperRef","containerStyle","useMemo","_extends","undefined","commonWrapStyle","wrapStyle","isHeightMode","paddingBottom","minHeight","WebkitLineClamp","boxSizing","validMaskBgColor","r","g","b","rgbaToObj","findEffectiveBgColor","current","startColor","endColor","btnStyle","padding","ratio","Math","min","height","paddingTop","paddingLeft","background","reorganizeDom","useCallback","orginStyleWidth","orginWidth","window","getComputedStyle","requestAnimationFrame","handleFoldChange","evt","ButtonComp","React","createElement","cx","ButtonShadowDom","resetState","newEllipsis","forceResetFold","preFold","calcEllipsis","wrapDom","containerDom","offsetHeight","clientHeight","realLineHeight","floor","adjustLines","useCompatibleEffect","useEffect","offsetWidth","isSafari","updateTextContent","newTextContent","handleResize","rect","offset","abs","hoverTitle","title","assignRef","Measure","throttleMs","onResize","triggerResizeInit","measureRef"],"mappings":"2pBA+Ba,MAAAA,EAAIC,EAAE,yBA+HNC,EAAeC,EAA8C,SAAsBC,EAAOC,GACrG,MAAMC,UACJA,EAASC,MACTA,EAAKC,WACLA,EAAa,GAAEC,MACfA,EAAKC,YACLA,EAAWC,QACXA,EAAOC,SACPA,EAAQC,sCACRA,GAAwC,EAAKC,kBAC7CA,EAAiBC,cACjBA,EAAaC,gBACbA,GAAkB,EAAIC,SACtBA,EAAW,KAAIC,WACfA,EAAa,KAAIC,OACjBA,EAAS,QAAOC,aAChBA,EAAe,OAAMC,UACrBA,EAASC,iBACTA,EAAmB,SAAQC,WAC3BA,EAAUC,MACVA,EAAKC,iBACLA,EAAgBC,iBAChBA,EAAgBC,aAChBA,EAAYC,eACZA,EAAcC,aACdA,EAAYC,aACZA,EAAYC,eACZA,EAAcC,eACdA,EAAcC,QACdA,EAAOC,QACPA,GACE9B,EACE+B,EAAexB,GAAWC,GAEzBwB,EAAUC,GAAeC,GAAS,IAClCC,EAAmBC,GAAwBF,GAAS,IAEpDG,EAAMC,IAAWC,EAAkBvC,EAAO,OAAQ,CAACwC,cAAc,EAAMC,SAAUlB,KACjFmB,GAAcC,IAAmBT,EAAS,IAC1CU,GAAiBC,IAAsBX,EACtB,iBAAf9B,GAA2BA,EAAW0C,SAAS,MAClDC,WAAW3C,GACX,IAEC4C,GAAa,EAAGC,IAAiBf,EAAS7B,IAE1C6C,GAAaC,IAAkBjB,EAAS,KAExCkB,IAAWC,EAAW,CAC3BC,QAAQ,EACRC,oBAAqB,EACrBC,uBAAwB,EACxBxB,WACAyB,YAAapB,EACbA,OACAK,gBACAQ,eACA5B,mBACAC,eACAC,kBACC,CAAC,OAAQ,mBAAoB,eAAgB,mBAE1CkC,GAAaC,EAAuB,MACpCC,GAAaD,EAAuB,MACpCE,GAAeF,EAAuB,MACtCG,GAAgBH,EAAuB,MAEvCI,GAAiBC,EAAQ,IAC7BC,EAAA,CACE7D,WAAY+B,EACR,MACA/B,QAA0B8D,GAC3B/D,GAEJ,CAACA,EAAOC,EAAY+B,IAEjBgC,GAAkBH,EAAQ,KACvB,CACL7C,aACAC,UAED,CAACD,EAAYC,IAEVgD,GAAYJ,EAAQ,KACxB,MACMK,EAAgC,WAAjBrD,EACrB,IAAKgB,KAAaqC,GAFJrB,IAEgCJ,IAC5C,OAAOuB,GAET,MAAMG,EAAgB1D,GAA+B,WAAXG,IAAwBsB,EAAQ,GAAGO,YAAsBsB,EACnG,OAAAD,EAAA,CAAA,EACKE,GAAe,CAElBI,WAAYF,GAAgBhC,GAThBW,GASmC,IAAOJ,GAAnB,UAAyCsB,EAI5EM,gBAAiBH,OAAeH,EAAY7B,EAbhCW,QAa+CkB,EAC3DjD,UAAWoD,GAAgBhC,EAAQpB,GAdvB+B,GAc4CJ,IAAmBQ,GAAQI,wBAA0B,OAAKU,EAClHI,gBACAG,UAAWH,EAAgB,kBAAwBJ,KAEpD,CAAClB,GAAYJ,GAAiBZ,EAAUK,EAAMzB,EAAiBG,EAAQC,EAAcC,EAAWkD,KAG7FO,GAAmBV,EAAQ,KAC/B,IAAKpD,IAAoBoB,EACvB,YAEF,MAAM2C,EAACA,EAACC,EAAEA,EAACC,EAAEA,GAAKC,EAAUxE,GAAe,KAAOyE,EAAqBlB,GAAamB,SACpF,MAAO,CACLC,WAAY,QAAQN,MAAMC,MAAMC,UAChCK,SAAU,QAAQP,MAAMC,MAAMC,UAE/B,CAACvE,EAAa0B,EAAUpB,IAGrBuE,GAAWnB,EAAQ,KACvB,IAAK3B,EACH,OAGF,MAAM+C,EAAUxC,GAEVyC,EAAmB,UAAXtE,EAAqBuE,KAAKC,IAAKH,EAAU1C,GAAgB,IAAK,IAAM,IAC5EuC,WAACA,EAAa,wBAAuBC,SAAEA,EAAW,uBAAyBR,IAAoB,CAAE,EACvG,MAAO,CACLD,UAAW,cACXe,OAAQ,GAAG5C,OACXxC,WAAY,GAAGwC,OACf6C,WAAuB,WAAX1E,EAAsB,GAAGqE,WAAclB,EACnDwB,YAAwB,UAAX3E,EAAqB,GAAGqE,WAAclB,EAEnDyB,WAAY,sBAAsB5E,MAAWkE,MAAeC,KAAYG,OAAWH,YAEpF,CAACtC,GAAiBP,EAAMtB,EAAQ2B,GAAcgC,KAE3CkB,GAAgBC,EAAY,KAEhC,GAAInC,GAAWsB,QAAS,CACtB,MAAMc,EAAkBpC,GAAWsB,QAAQ7E,MAAMiB,MAC3C2E,EAAaC,OAAOC,iBAAiBvC,GAAWsB,SAAS5D,MAE/DsC,GAAWsB,QAAQ7E,MAAMiB,MAAW2B,WAAWgD,GAAc,GAA5B,KACL,MAA5BC,OAAOE,uBAAPF,OAAOE,sBAAwB,KACzBxC,GAAWsB,UACbtB,GAAWsB,QAAQ7E,MAAMiB,MAAQ0E,IAGtC,GACA,IAEGK,GAAmBN,EACvB,CAACO,EAAkC/D,GAAQe,GAAQf,QACjDe,GAAQf,KAAOA,EACfC,GAAQD,IACT,IAEGgE,GAAarC,EAAQ,iBAEvBsC,EAAAC,cAAA,MAAA,CACErG,UAAWsG,EACT,mBACA,oBAAoBzF,IACT,WAAXA,GAAuB,aAAaG,KAEtCf,MAAOgF,GACPlF,IAAK6D,GACLjC,QAASsE,IAER9E,EACCA,EAAiBgB,gBAEjBiE,EAAAC,cAAA,MAAA,CAAKrG,UAAW,YAAamC,EAAOvB,EAAaD,IAItD,CACDsE,GACA9C,EACAxB,EACAsF,GACA9E,EACAH,EACAH,EACAD,IAII2F,GAAkBzC,EAAQ,IACzBhC,GAAapB,GAA8B,UAAXG,IAAsBsB,eAGpDiE,EAAAC,cAAA,OAAA,CAAMpG,MAAOgF,GAAUjF,UAAU,yBACrCmB,EAAmBA,EAAiBgB,GAAQxB,QAE9C,CAACmB,EAAUjB,EAAQH,EAAiByB,EAAM8C,GAAUtE,EAAUQ,IAG3DqF,GAAab,EAAY,CAACc,EAAcvD,GAAQpB,UACpD4E,eAAAA,GAAiB,GACf,CAAE,KACJ,MAAM5E,SAACA,EAAUK,KAAMwE,EAAOpD,YAAEA,GAAeL,GAC3CuD,IAAgB3E,IAClBC,EAAY0E,GACZvD,GAAQpB,SAAW2E,EACnBvD,MAAAA,GAAQ9B,kBAAR8B,GAAQ9B,iBAAmBqF,IAI3BlG,IACImG,IAAoB5E,GAAY2E,IACjCE,IAAYpD,GAEf0C,QAAiBjC,EAAWT,IAE7B,CAAC0C,GAAkBpE,EAActB,IAE9BqG,GAAejB,EAAY,KAC/B,MAAMkB,EAAUnD,GAAWoB,QACrBgC,EAAenD,GAAamB,QAClC,IAAK+B,IAAYC,EACf,OAEF5D,GAAQG,oBAAsBwD,EAAQE,aACtC,MAAMlD,EAAiBiC,OAAOC,iBAAiBe,GACzCvB,EAAa1C,WAAWgB,EAAe0B,YACvCnB,EAAgBvB,WAAWgB,EAAeO,eAC1Cd,EAAyBJ,GAAQI,uBAAyBwD,EAAaE,aAAezB,EAAanB,EAGzG,IAAI6C,EAAiB,EAErB,IAAKA,GAAkBJ,EAAS,CAC9B,MAAM3G,WAACA,GAAc2D,GAAkB,CAAE,EACrC3D,IAEF+G,EAAiBpE,WAAW3C,GACvB+G,GACH/E,GAAqB,GAG1B,CAED,GAAIQ,KAAoBuE,IACtBtE,GAAmBsE,GACdA,GAOP,GAFsC,WAAjBnG,EAGnB0F,GAAWtD,GAAQG,qBAAuBtC,GAAauC,SAKzD,GAAKnD,EAWC2C,KAAe3C,GACjB4C,GAAc5C,GAIdqG,GAAWtD,GAAQG,sBAAwBlD,EAAQ,GAAKiF,KAAK8B,MAAMD,GAAkB,QAfvF,GAAI/D,GAAQG,oBAAsBC,EAAwB,CACtD,MAAM6D,EAAc/B,KAAK8B,MAAM5D,EAAyB2D,IAAmB,EACvEnE,KAAeqE,GACjBpE,GAAcoE,GAEhBX,IAAW,EACd,MACCA,IAAW,IAUd,CAACrG,EAAOuC,GAAiB5B,EAAcC,EAAWyF,KAIrDY,EAAoB,KAClBZ,GAAWtD,GAAQpB,SAAU,CAC3B4E,gBAAgB,IAElBE,MACC,CAACA,GAAcJ,KAGlBa,EAAU,KACR,GAAIvF,GAAY8B,GAAckB,QAAS,CACrC,MAAMwC,YAACA,GAAe1D,GAAckB,QAChCwC,IAAgBpE,GAAQV,eAC1BU,GAAQV,aAAe8E,EACvB7E,GAAgB6E,GAEnB,GACA,CAACxF,EAAUlB,EAAYF,IAC1B2G,EAAU,KACJE,GACF7B,MAED,CAACvD,EAAMuD,KACV,MAAM8B,GAAoB7B,EAAY,KACpC,IAAKjC,GAAWoB,QACd,OAEF,MAAM2C,EAAiB/D,GAAWoB,QAAQ9B,aAAe,GACrDyE,IAAmBvE,GAAQF,cAC7BE,GAAQF,YAAcyE,EACtBxE,GAAewE,KAEhB,IACGC,GAAe/B,EAAoDgC,IAEvE,MAAMrC,OAACA,GAAUqC,EAAKC,QAAU,CAAA,OACjB5D,IAAXsB,GAAwBF,KAAKyC,IAAIvC,EAASpC,GAAQG,qBAAuB,GAC3EuD,MAED,CAACA,KACEkB,GAAahE,EAAQ,IAChBhC,GAAYK,EACW,mBAAlB1B,EACNA,EAAcuC,IACdvC,GAAiBuC,QACnBgB,EACL,CAACvD,EAAeqB,EAAUK,EAAMa,KAkBnC,OAjBAqE,EAAU,KACJnE,GAAQE,SACY,MAAtBF,GAAQ5B,gBAAR4B,GAAQ5B,eAAiB,CACrBQ,WACAK,OACA4F,MAAOD,OAGZ,CAAC3F,EAAML,EAAUgG,KACpBT,EAAU,KACRnE,GAAQE,QAAS,GAChB,iBAODgD,EAAAC,cAAA,MAAA,CACErG,UAAWsG,EAAG5G,EAAE,aAAcM,GAC9BC,MAAO4D,GACP9D,IAAM0E,IACJuD,EAAUrE,GAAcc,GACpB1E,GACFiI,EAAUjI,EAAK0E,IAGnBlD,aAAcA,EACdC,aAAcA,EACdC,eAAgBA,EAChBC,eAAgBA,EAChBC,QAASA,EACTC,QAASA,gBAGTwE,EAAAC,cAAC4B,EAAQL,CAAAA,QAAOM,EAAAA,WAAY,IAAKC,SAAUT,GAAcU,mBAAmB,GACzE,EAAEC,6BAMMjC,EAAAC,qBAAKpG,MAAOgE,GAAiBjE,UAAW,qBAAsBD,IAAM0E,IACzEuD,EAAUK,EAAY5D,GACtBuD,EAAUtE,GAAYe,GACtB+C,OAEC3F,iBAQPuE,EAAAC,cACErG,MAAAA,CAAAA,UAAW,sBACX+H,MAAOvH,EAAoBsH,QAAa9D,EACxC/D,MAAOiE,GACPnE,IAAKyD,IAIJ1B,GAAYpB,GAAmByF,GAC/BtE,EACA0E,IAIT"}
|
package/dist/index.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("@ohkit/prefix-classname"),require("@ohkit/react-helper"),require("@ohkit/platform"),require("@ohkit/dom-helper"),require("@ohkit/measure")):"function"==typeof define&&define.amd?define(["exports","react","@ohkit/prefix-classname","@ohkit/react-helper","@ohkit/platform","@ohkit/dom-helper","@ohkit/measure"],t):t((e||self).textEllipsis={},e.react,e.prefixClassname,e.reactHelper,e.platform,e.domHelper,e.measure)}(this,function(e,t,n,o,i,r,l){function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=/*#__PURE__*/a(t);function u(){return u=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)({}).hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},u.apply(null,arguments)}var f=n.prefixClassname("ohkit-text-ellipsis__"),d=t.forwardRef(function(e,a){var d=e.className,c=e.style,h=e.lineHeight,p=void 0===h?"":h,g=e.lines,m=e.maskBgColor,v=e.resetFoldWhenChildrenOrEllipsisChange,C=void 0!==v&&v,b=e.showTitleWhenFold,x=e.titleWhenFold,E=e.showFoldControl,w=void 0===E||E,k=e.foldText,y=void 0===k?"收起":k,F=e.unfoldText,H=void 0===F?"展开":F,S=e.uiType,M=void 0===S?"right":S,R=e.truncateMode,O=void 0===R?"line":R,T=e.maxHeight,N=e.controlPlacement,W=void 0===N?"center":N,q=e.whiteSpace,B=e.width,P=e.renderFoldButton,L=e.onEllipsisChange,j=e.onFoldChange,z=e.onStatusChange,A=e.onMouseEnter,_=e.onMouseLeave,I=e.onPointerEnter,V=e.onPointerLeave,D=e.onClick,G=e.onFocus,J=e.content||e.children,K=t.useState(!1),Q=K[0],U=K[1],X=t.useState(!1),Y=X[0],Z=X[1],$=o.useSyncPropsState(e,"fold",{defaultValue:!0,onChange:j}),ee=$[0],te=$[1],ne=t.useState(1),oe=ne[0],ie=ne[1],re=t.useState("string"==typeof p&&p.endsWith("px")?parseFloat(p):0),le=re[0],ae=re[1],se=t.useState(g),ue=se[0],fe=void 0===ue?0:ue,de=se[1],ce=t.useState(""),he=ce[0],pe=ce[1],ge=o.useRuntime({inited:!1,contentOffsetHeight:0,containerContentHeight:0,ellipsis:Q,defaultFold:ee,fold:ee,foldBtnWidth:oe,textContent:he,onEllipsisChange:L,onFoldChange:j,onStatusChange:z},["fold","onEllipsisChange","onFoldChange","onStatusChange"])[0],me=t.useRef(null),ve=t.useRef(null),Ce=t.useRef(null),be=t.useRef(null),xe=t.useMemo(function(){return u({lineHeight:Y?"1.4":p||void 0},c)},[c,p,Y]),Ee=t.useMemo(function(){return{whiteSpace:q,width:B}},[q,B]),we=t.useMemo(function(){var e="height"===O;if(!Q||!(e||fe&&le))return Ee;var t=w&&"bottom"===M&&!ee?le+"px":void 0;return u({},Ee,{minHeight:!e&&ee?(fe-.2)*le+"px":void 0,WebkitLineClamp:e?void 0:ee?fe:void 0,maxHeight:e&&ee?T||fe*le||ge.containerContentHeight||0:void 0,paddingBottom:t,boxSizing:t?"border-box":void 0})},[fe,le,Q,ee,w,M,O,T,Ee]),ke=t.useMemo(function(){if(!w||!Q)return null;var e=r.rgbaToObj(m||"")||r.findEffectiveBgColor(Ce.current),t=e.r,n=e.g,o=e.b;return{startColor:"rgba("+t+", "+n+", "+o+", 0.2)",endColor:"rgba("+t+", "+n+", "+o+", 1)"}},[m,Q,w]),ye=t.useMemo(function(){if(ee){var e=le,t="right"===M?Math.min(e/oe*100,80):60,n=ke||{},o=n.startColor,i=n.endColor,r=void 0===i?"rgba(255,255,255,1)":i;return{boxSizing:"content-box",height:le+"px",lineHeight:le+"px",paddingTop:"bottom"===M?e+"px":void 0,paddingLeft:"right"===M?e+"px":void 0,background:"linear-gradient(to "+M+", "+(void 0===o?"rgba(255,255,255,0.2)":o)+", "+r+" "+t+"%, "+r+" 100%)"}}},[le,ee,M,oe,ke]),Fe=t.useCallback(function(){if(me.current){var e=me.current.style.width,t=window.getComputedStyle(me.current).width;me.current.style.width=parseFloat(t)-.1+"px",null==window.requestAnimationFrame||window.requestAnimationFrame(function(){me.current&&(me.current.style.width=e)})}},[]),He=t.useCallback(function(e,t){void 0===t&&(t=!ge.fold),ge.fold=t,te(t)},[]),Se=t.useMemo(function(){/*#__PURE__*/return s.default.createElement("div",{className:n.classNames("btn-fold-wrapper","btn-fold-wrapper-"+M,"bottom"===M&&"placement-"+W),style:ye,ref:be,onClick:He},P?P(ee):/*#__PURE__*/s.default.createElement("div",{className:"btn-fold"},ee?H:y))},[ye,ee,y,He,P,W,M,H]),Me=t.useMemo(function(){return
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("@ohkit/prefix-classname"),require("@ohkit/react-helper"),require("@ohkit/platform"),require("@ohkit/dom-helper"),require("@ohkit/measure")):"function"==typeof define&&define.amd?define(["exports","react","@ohkit/prefix-classname","@ohkit/react-helper","@ohkit/platform","@ohkit/dom-helper","@ohkit/measure"],t):t((e||self).textEllipsis={},e.react,e.prefixClassname,e.reactHelper,e.platform,e.domHelper,e.measure)}(this,function(e,t,n,o,i,r,l){function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=/*#__PURE__*/a(t);function u(){return u=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)({}).hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},u.apply(null,arguments)}var f=n.prefixClassname("ohkit-text-ellipsis__"),d=t.forwardRef(function(e,a){var d=e.className,c=e.style,h=e.lineHeight,p=void 0===h?"":h,g=e.lines,m=e.maskBgColor,v=e.resetFoldWhenChildrenOrEllipsisChange,C=void 0!==v&&v,b=e.showTitleWhenFold,x=e.titleWhenFold,E=e.showFoldControl,w=void 0===E||E,k=e.foldText,y=void 0===k?"收起":k,F=e.unfoldText,H=void 0===F?"展开":F,S=e.uiType,M=void 0===S?"right":S,R=e.truncateMode,O=void 0===R?"line":R,T=e.maxHeight,N=e.controlPlacement,W=void 0===N?"center":N,q=e.whiteSpace,B=e.width,P=e.renderFoldButton,L=e.onEllipsisChange,j=e.onFoldChange,z=e.onStatusChange,A=e.onMouseEnter,_=e.onMouseLeave,I=e.onPointerEnter,V=e.onPointerLeave,D=e.onClick,G=e.onFocus,J=e.content||e.children,K=t.useState(!1),Q=K[0],U=K[1],X=t.useState(!1),Y=X[0],Z=X[1],$=o.useSyncPropsState(e,"fold",{defaultValue:!0,onChange:j}),ee=$[0],te=$[1],ne=t.useState(1),oe=ne[0],ie=ne[1],re=t.useState("string"==typeof p&&p.endsWith("px")?parseFloat(p):0),le=re[0],ae=re[1],se=t.useState(g),ue=se[0],fe=void 0===ue?0:ue,de=se[1],ce=t.useState(""),he=ce[0],pe=ce[1],ge=o.useRuntime({inited:!1,contentOffsetHeight:0,containerContentHeight:0,ellipsis:Q,defaultFold:ee,fold:ee,foldBtnWidth:oe,textContent:he,onEllipsisChange:L,onFoldChange:j,onStatusChange:z},["fold","onEllipsisChange","onFoldChange","onStatusChange"])[0],me=t.useRef(null),ve=t.useRef(null),Ce=t.useRef(null),be=t.useRef(null),xe=t.useMemo(function(){return u({lineHeight:Y?"1.4":p||void 0},c)},[c,p,Y]),Ee=t.useMemo(function(){return{whiteSpace:q,width:B}},[q,B]),we=t.useMemo(function(){var e="height"===O;if(!Q||!(e||fe&&le))return Ee;var t=w&&"bottom"===M&&!ee?le+"px":void 0;return u({},Ee,{minHeight:!e&&ee?(fe-.2)*le+"px":void 0,WebkitLineClamp:e?void 0:ee?fe:void 0,maxHeight:e&&ee?T||fe*le||ge.containerContentHeight||0:void 0,paddingBottom:t,boxSizing:t?"border-box":void 0})},[fe,le,Q,ee,w,M,O,T,Ee]),ke=t.useMemo(function(){if(!w||!Q)return null;var e=r.rgbaToObj(m||"")||r.findEffectiveBgColor(Ce.current),t=e.r,n=e.g,o=e.b;return{startColor:"rgba("+t+", "+n+", "+o+", 0.2)",endColor:"rgba("+t+", "+n+", "+o+", 1)"}},[m,Q,w]),ye=t.useMemo(function(){if(ee){var e=le,t="right"===M?Math.min(e/oe*100,80):60,n=ke||{},o=n.startColor,i=n.endColor,r=void 0===i?"rgba(255,255,255,1)":i;return{boxSizing:"content-box",height:le+"px",lineHeight:le+"px",paddingTop:"bottom"===M?e+"px":void 0,paddingLeft:"right"===M?e+"px":void 0,background:"linear-gradient(to "+M+", "+(void 0===o?"rgba(255,255,255,0.2)":o)+", "+r+" "+t+"%, "+r+" 100%)"}}},[le,ee,M,oe,ke]),Fe=t.useCallback(function(){if(me.current){var e=me.current.style.width,t=window.getComputedStyle(me.current).width;me.current.style.width=parseFloat(t)-.1+"px",null==window.requestAnimationFrame||window.requestAnimationFrame(function(){me.current&&(me.current.style.width=e)})}},[]),He=t.useCallback(function(e,t){void 0===t&&(t=!ge.fold),ge.fold=t,te(t)},[]),Se=t.useMemo(function(){/*#__PURE__*/return s.default.createElement("div",{className:n.classNames("btn-fold-wrapper","btn-fold-wrapper-"+M,"bottom"===M&&"placement-"+W),style:ye,ref:be,onClick:He},P?P(ee):/*#__PURE__*/s.default.createElement("div",{className:"btn-fold"},ee?H:y))},[ye,ee,y,He,P,W,M,H]),Me=t.useMemo(function(){return Q&&w&&"right"===M&&!ee?/*#__PURE__*/s.default.createElement("span",{style:ye,className:"btn-fold-right-shadow"},P?P(ee):y):null},[Q,M,w,ee,ye,y,P]),Re=t.useCallback(function(e,t){void 0===e&&(e=ge.ellipsis);var n=(void 0===t?{}:t).forceResetFold,o=void 0!==n&&n,i=ge.ellipsis,r=ge.fold,l=ge.defaultFold;e!==i&&(U(e),ge.ellipsis=e,null==ge.onEllipsisChange||ge.onEllipsisChange(e)),C&&(o||!i&&e)&&r!==l&&He(void 0,l)},[He,J,C]),Oe=t.useCallback(function(){var e=ve.current,t=Ce.current;if(e&&t){ge.contentOffsetHeight=e.offsetHeight;var n=window.getComputedStyle(t),o=parseFloat(n.paddingTop),i=parseFloat(n.paddingBottom),r=ge.containerContentHeight=t.clientHeight-o-i,l=0;if(!l&&e){var a=(n||{}).lineHeight;a&&((l=parseFloat(a))||Z(!0))}if(le===l||(ae(l),l))if("height"===O)Re(ge.contentOffsetHeight>(T||r));else if(g)fe!==g&&de(g),Re(ge.contentOffsetHeight>=(g+1)*Math.floor(l)-1);else if(ge.contentOffsetHeight>r){var s=Math.floor(r/l)||1;fe!==s&&de(s),Re(!0)}else Re(!1)}},[g,le,O,T,Re]);o.useCompatibleEffect(function(){Re(ge.ellipsis,{forceResetFold:!0}),Oe()},[Oe,Re]),t.useEffect(function(){if(Q&&be.current){var e=be.current.offsetWidth;e!==ge.foldBtnWidth&&(ge.foldBtnWidth=e,ie(e))}},[Q,H,w]),t.useEffect(function(){i.isSafari&&Fe()},[ee,Fe]);var Te=t.useCallback(function(){if(ve.current){var e=ve.current.textContent||"";e!==ge.textContent&&(ge.textContent=e,pe(e))}},[]),Ne=t.useCallback(function(e){var t=(e.offset||{}).height;void 0!==t&&Math.abs(t-ge.contentOffsetHeight)>1&&Oe()},[Oe]),We=t.useMemo(function(){return Q&&ee?"function"==typeof x?x(he):x||he:void 0},[x,Q,ee,he]);return t.useEffect(function(){ge.inited&&(null==ge.onStatusChange||ge.onStatusChange({ellipsis:Q,fold:ee,title:We}))},[ee,Q,We]),t.useEffect(function(){ge.inited=!0},[]),/*#__PURE__*/s.default.createElement("div",{className:n.classNames(f("container"),d),style:xe,ref:function(e){o.assignRef(Ce,e),a&&o.assignRef(a,e)},onMouseEnter:A,onMouseLeave:_,onPointerEnter:I,onPointerLeave:V,onClick:D,onFocus:G},/*#__PURE__*/s.default.createElement(l.Measure,{offset:!0,throttleMs:100,onResize:Ne,triggerResizeInit:!1},function(e){var t=e.measureRef;/*#__PURE__*/return s.default.createElement("div",{style:Ee,className:"content-shadow-dom",ref:function(e){o.assignRef(t,e),o.assignRef(ve,e),Te()}},J)}),/*#__PURE__*/s.default.createElement("div",{className:"text-ellipsis-inner",title:b?We:void 0,style:we,ref:me},Q&&w&&Se,J,Me))});e.TextEllipsis=d,e.c=f});
|
|
2
2
|
//# sourceMappingURL=index.umd.js.map
|
package/dist/index.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @file 文本截断显示组件\n * @description 基于React封装一个文本截断显示组件,富文本(仅文字样式,图片和表格效果不一定好)同普通文本处理一致\n * @author <wuqiuyang305@126.com>\n */\n\nimport React, {\n forwardRef,\n useState,\n useMemo,\n useEffect,\n useCallback,\n useRef,\n PropsWithChildren,\n MouseEvent,\n} from \"react\";\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {\n assignRef,\n useRuntime,\n useCompatibleEffect,\n useSyncPropsState,\n} from \"@ohkit/react-helper\";\nimport {isSafari} from \"@ohkit/platform\";\nimport {rgbaToObj, findEffectiveBgColor} from \"@ohkit/dom-helper\";\nimport {Measure, MeasureProps} from \"@ohkit/measure\";\nimport \"./style.scss\";\n\nexport const c = p(\"ohkit-text-ellipsis__\");\n\ninterface ITextEllipsis\n extends Pick<\n React.DOMAttributes<HTMLDivElement>,\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onFocus\"\n | \"onClick\"\n > {\n /**\n * 自定义样式类名,会附加到根元素上\n */\n className?: string;\n /**\n * 自定义样式\n */\n style?: React.CSSProperties;\n /**\n * right | bottom 展开按钮在右下侧还是底部\n * @default right\n */\n uiType?: \"right\" | \"bottom\";\n /**\n * 截断模式 (若某些浏览器不支持 webkitLineClamp,可降级切换为 height 模式)\n * @default line\n */\n truncateMode?: \"line\" | \"height\";\n /**\n * truncateMode === \"height\" 时生效\n * 最大高度(number > 0),没传或者传入无效值不限制,尝试取 lines * lineHeight,若仍无效 自动截断到容器的最大高度\n * 单位: px\n */\n maxHeight?: number;\n /**\n * (单位:px)未传入或无效(0也视为无效)则自动取当前文本的行高\n */\n lineHeight?: React.CSSProperties[\"lineHeight\"];\n /**\n * truncateMode === \"line\" 时生效\n * 超过几行折叠(number > 0), 没传或者传入无效值不限制,自动截断到容器的最大高度\n */\n lines?: number;\n /**\n * 展开按钮蒙层背景色(仅支持16进制表示)\n * @default #fff\n */\n maskBgColor?: string;\n /**\n * text|ReactNode 与children任传一个\n */\n content?: React.ReactNode;\n /**\n * 当 content or children or ellipsis 变化时,重置 fold 状态 \n * @default false\n */\n resetFoldWhenChildrenOrEllipsisChange?: boolean;\n /**\n * 折叠状态\n * @default true\n */\n fold?: boolean;\n /**\n * 显示展开控制按钮\n * @default true\n */\n showFoldControl?: boolean;\n /**\n * 展开按钮位置 uiType='bottom'时有效\n * @default center\n */\n controlPlacement?: 'left' | 'center' | 'right';\n /**\n * 折叠按钮文字\n * @default 收起\n */\n foldText?: string;\n /**\n * 展开按钮文字\n * @default 展开\n */\n unfoldText?: string;\n /**\n * 折叠状态下是否显示title属性\n * @default false\n */\n showTitleWhenFold?: boolean;\n /**\n * 折叠状态自定义title属性内容\n */\n titleWhenFold?: string | ((title: string) => string);\n /**\n * 是否保留换行\n */\n whiteSpace?: React.CSSProperties['whiteSpace'];\n /**\n * 容器宽度(默认自适应内容)\n * 应用场景:whiteSpace='pre*' 时,支持展示换行符,自适应内容可能导致控制按钮位置不确定\n */\n width?: React.CSSProperties['width'];\n /**\n * 自定义渲染展开按钮\n */\n renderFoldButton?: (fold: boolean) => React.ReactNode;\n /**\n * @param fold 折叠状态,true 折叠,false 展开\n */\n onFoldChange?: (fold: boolean) => void;\n /**\n * @param ellipsis 是否截断,true 截断,false 未截断\n */\n onEllipsisChange?: (ellipsis: boolean) => void;\n /**\n * 关键状态变更触发\n * @param status\n */\n onStatusChange?: (status: {\n fold: boolean;\n ellipsis: boolean;\n title?: string;\n }) => void;\n}\n\nexport type TextEllipsisProps = PropsWithChildren<ITextEllipsis>;\n\nexport const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>((props, ref) => {\n const {\n className,\n style,\n lineHeight = \"\",\n lines,\n maskBgColor,\n content,\n children,\n resetFoldWhenChildrenOrEllipsisChange = false,\n showTitleWhenFold,\n titleWhenFold,\n showFoldControl = true,\n foldText = \"收起\",\n unfoldText = \"展开\",\n uiType = \"right\",\n truncateMode = \"line\",\n maxHeight,\n controlPlacement = 'center',\n whiteSpace,\n width,\n renderFoldButton,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n onMouseEnter,\n onMouseLeave,\n onPointerEnter,\n onPointerLeave,\n onClick,\n onFocus,\n } = props;\n const finalContent = content || children;\n // 是否截断\n const [ellipsis, setEllipsis] = useState(false);\n const [getLineHeightFail, setGetLineHeightFail] = useState(false);\n // 折叠状态\n const [fold, setFold] = useSyncPropsState(props, 'fold', {defaultValue: true, onChange: onFoldChange});\n const [foldBtnWidth, setFoldBtnWidth] = useState(1);\n const [innerLineHeight, setInnerLineHeight] = useState(\n typeof lineHeight === \"string\" && lineHeight.endsWith(\"px\")\n ? parseFloat(lineHeight)\n : 0\n );\n const [innerLines = 0, setInnerLines] = useState(lines);\n // children提取的纯文本\n const [textContent, setTextContent] = useState('');\n\n const [runtime] = useRuntime({\n inited: false, // mounted\n contentOffsetHeight: 0, // 内容节点offsetHeight\n containerContentHeight: 0, // 容器内容高度 = 容器高 - 上下padding\n ellipsis,\n defaultFold: fold, // 记录一下默认的折叠状态,用于 reset fold\n fold,\n foldBtnWidth,\n textContent,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n }, ['fold', 'onEllipsisChange', 'onFoldChange', 'onStatusChange']);\n\n const contentRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const btnWrapperRef = useRef<HTMLDivElement>(null);\n\n const containerStyle = useMemo(() => {\n return {\n lineHeight: getLineHeightFail // 未传入且获取 lineHeight(px) 失败,则设置 default lineHeight: 1.4(em)\n ? \"1.4\" // more brower normal default lineHeight\n : lineHeight ? lineHeight : undefined,\n ...style,\n };\n }, [style, lineHeight, getLineHeightFail]);\n\n const commonWrapStyle = useMemo(() => {\n return {\n whiteSpace,\n width,\n };\n }, [whiteSpace, width]);\n // 容器样式\n const wrapStyle = useMemo(() => {\n const lines = innerLines;\n const isHeightMode = truncateMode === 'height';\n if (!ellipsis || !isHeightMode && (!lines || !innerLineHeight)) {\n return commonWrapStyle;\n }\n const paddingBottom = showFoldControl && (uiType === \"bottom\" && !fold) ? `${innerLineHeight}px` : undefined;\n return {\n ...commonWrapStyle,\n // HACK: 兼容safari 15+ 富文本折叠高度丢失问题\n minHeight: !isHeightMode && fold ? `${(lines - 0.2) * innerLineHeight}px` : undefined,\n // Note: safari 对WebkitLineClamp支持太差劲 判断浏览器优雅降级为高度截断方案?目前先交给用户去判断,自行选择truncateMode\n // WebkitLineClamp: isSafari ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n // maxHeight: isSafari && fold ? lines * innerLineHeight : undefined,\n WebkitLineClamp: isHeightMode ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n maxHeight: isHeightMode && fold ? (maxHeight || lines * innerLineHeight || runtime.containerContentHeight || 0) : undefined,\n paddingBottom,\n boxSizing: paddingBottom ? 'border-box' as const : undefined,\n };\n }, [innerLines, innerLineHeight, ellipsis, fold, showFoldControl, uiType, truncateMode, maxHeight, commonWrapStyle]);\n\n // 计算折叠按钮蒙层的渐变颜色\n const validMaskBgColor = useMemo(() => {\n if (!showFoldControl || !ellipsis) {\n return null;\n }\n const {r, g, b} = rgbaToObj(maskBgColor || '') || findEffectiveBgColor(containerRef.current);\n return {\n startColor: `rgba(${r}, ${g}, ${b}, 0.2)`,\n endColor: `rgba(${r}, ${g}, ${b}, 1)`,\n };\n }, [maskBgColor, ellipsis, showFoldControl]);\n\n // 展开|收起 按钮样式\n const btnStyle = useMemo(() => {\n if (!fold) {\n return;\n }\n // 按钮padding,取行高\n const padding = innerLineHeight;\n // 蒙层透明度所占比例\n const ratio = uiType === \"right\" ? Math.min((padding / foldBtnWidth) * 100, 80) : 60;\n const {startColor = 'rgba(255,255,255,0.2)', endColor = 'rgba(255,255,255,1)'} = validMaskBgColor || {};\n return {\n boxSizing: 'content-box' as const,\n height: `${innerLineHeight}px`,\n lineHeight: `${innerLineHeight}px`,\n paddingTop: uiType === \"bottom\" ? `${padding}px` : undefined,\n paddingLeft: uiType === \"right\" ? `${padding}px` : undefined,\n // 渐变蒙层\n background: `linear-gradient(to ${uiType}, ${startColor}, ${endColor} ${ratio}%, ${endColor} 100%)`,\n };\n }, [innerLineHeight, fold, uiType, foldBtnWidth, validMaskBgColor]);\n\n const reorganizeDom = useCallback(() => {\n // Note: safari 中仅改变 WebkitLineClamp 没触发重排,调整微小宽度以触发\n if (contentRef.current) {\n const orginStyleWidth = contentRef.current.style.width;\n const orginWidth = window.getComputedStyle(contentRef.current).width;\n // console.log('orginWidth, orginStyleWidth:', orginWidth, orginStyleWidth);\n contentRef.current.style.width = `${parseFloat(orginWidth) - 0.1}px`;\n window.requestAnimationFrame?.(() => {\n if (contentRef.current) {\n contentRef.current.style.width = orginStyleWidth;\n }\n });\n }\n }, []);\n\n const handleFoldChange = useCallback(\n (evt?: MouseEvent<HTMLDivElement>, fold = !runtime.fold) => {\n runtime.fold = fold;\n setFold(fold);\n }, []);\n\n const ButtonComp = useMemo(() => {\n return (\n <div\n className={cx(\n \"btn-fold-wrapper\",\n `btn-fold-wrapper-${uiType}`,\n uiType === \"bottom\" && `placement-${controlPlacement}`\n )}\n style={btnStyle}\n ref={btnWrapperRef}\n onClick={handleFoldChange}\n >\n {renderFoldButton ? (\n renderFoldButton(fold)\n ) : (\n <div className={\"btn-fold\"}>{fold ? unfoldText : foldText}</div>\n )}\n </div>\n );\n }, [\n btnStyle,\n fold,\n foldText,\n handleFoldChange,\n renderFoldButton,\n controlPlacement,\n uiType,\n unfoldText,\n ]);\n\n // 占位按钮\n const ButtonShadowDom = useMemo(() => {\n if (!showFoldControl || uiType !== 'right' || fold) {\n return null;\n }\n return <span style={btnStyle} className=\"btn-fold-right-shadow\">\n {renderFoldButton ? renderFoldButton(fold) : foldText}\n </span>;\n }, [uiType, showFoldControl, fold, btnStyle, foldText, renderFoldButton]);\n\n // 重置状态\n const resetState = useCallback((newEllipsis = runtime.ellipsis, {\n forceResetFold = false, // 强制重置fold 比如child变化时\n } = {}) => {\n const {ellipsis, fold: preFold, defaultFold} = runtime;\n if (newEllipsis !== ellipsis) {\n setEllipsis(newEllipsis);\n runtime.ellipsis = newEllipsis;\n runtime.onEllipsisChange?.(newEllipsis);\n }\n // 从未截断状态切换为截断状态时,自动折叠(即:出现展开按钮)\n if (\n resetFoldWhenChildrenOrEllipsisChange\n && (forceResetFold || !ellipsis && newEllipsis)\n && preFold !== defaultFold\n ) {\n handleFoldChange(undefined, defaultFold);\n }\n }, [handleFoldChange, finalContent, resetFoldWhenChildrenOrEllipsisChange]);\n\n const calcEllipsis = useCallback(() => {\n const wrapDom = wrapperRef.current;\n const containerDom = containerRef.current;\n if (!wrapDom || !containerDom) {\n return;\n }\n runtime.contentOffsetHeight = wrapDom.offsetHeight;\n const containerStyle = window.getComputedStyle(containerDom);\n const paddingTop = parseFloat(containerStyle.paddingTop);\n const paddingBottom = parseFloat(containerStyle.paddingBottom);\n const containerContentHeight = runtime.containerContentHeight = containerDom.clientHeight - paddingTop - paddingBottom;\n\n // 计算真实行高\n let realLineHeight = 0;\n // 若外部未传入, 尝试读取当前文本的行高。\n if (!realLineHeight && wrapDom) {\n const {lineHeight} = containerStyle || {};\n if (lineHeight) {\n // 未设置行高的为 normal\n realLineHeight = parseFloat(lineHeight);\n if (!realLineHeight) {\n setGetLineHeightFail(true);\n }\n }\n }\n // lineHeight同步到innerLineHeight\n if (innerLineHeight !== realLineHeight) {\n setInnerLineHeight(realLineHeight);\n if (!realLineHeight) {\n return;\n }\n }\n\n const isHeightMode = truncateMode === 'height';\n // 高度截断模式,比较简单 直接判断是否超出容器高度\n if (isHeightMode) {\n resetState(runtime.contentOffsetHeight > (maxHeight || containerContentHeight));\n return;\n }\n\n // 行数截断模式,需要利用行高计算是否超出容器高度\n if (!lines) {\n if (runtime.contentOffsetHeight > containerContentHeight) {\n const adjustLines = Math.floor(containerContentHeight / realLineHeight) || 1;\n if (innerLines !== adjustLines) {\n setInnerLines(adjustLines);\n }\n resetState(true);\n } else {\n resetState(false);\n }\n } else {\n if (innerLines !== lines) {\n setInnerLines(lines);\n }\n // console.log('contentOffsetHeight, realLineHeight', runtime.contentOffsetHeight, realLineHeight);\n // 允许误差1px(行高为小数时, safari计算行高*行数和实践总高有差异,故将行高向下取整兼容)\n resetState(runtime.contentOffsetHeight >= (lines + 1) * Math.floor(realLineHeight) - 1);\n }\n }, [lines, innerLineHeight, truncateMode, maxHeight, resetState]);\n\n // 监听内容高度,是否需要折叠\n // 用useLayoutEffect方式闪屏显示\n useCompatibleEffect(() => {\n resetState(runtime.ellipsis, {\n forceResetFold: true,\n });\n calcEllipsis();\n }, [calcEllipsis, resetState]);\n\n // 监听\"展开\"按钮宽度变化\n useEffect(() => {\n if (ellipsis && btnWrapperRef.current) {\n const {offsetWidth} = btnWrapperRef.current;\n if (offsetWidth !== runtime.foldBtnWidth) {\n runtime.foldBtnWidth = offsetWidth;\n setFoldBtnWidth(offsetWidth);\n }\n }\n }, [ellipsis, unfoldText, showFoldControl]);\n useEffect(() => {\n if (isSafari) {\n reorganizeDom();\n }\n }, [fold, reorganizeDom]);\n const updateTextContent = useCallback(() => {\n if (!wrapperRef.current) {\n return;\n }\n const newTextContent = wrapperRef.current.textContent || '';\n if (newTextContent !== runtime.textContent) {\n runtime.textContent = newTextContent;\n setTextContent(newTextContent);\n }\n }, []);\n const handleResize = useCallback<NonNullable<MeasureProps['onResize']>>((rect) => {\n // console.log('[handleResize] rect: ', rect, runtime.contentOffsetHeight);\n const {height} = rect.offset || {};\n if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n calcEllipsis();\n }\n }, [calcEllipsis]);\n const hoverTitle = useMemo(() => {\n return ellipsis && fold\n ? (typeof titleWhenFold === 'function'\n ? titleWhenFold(textContent)\n : titleWhenFold || textContent)\n : undefined;\n }, [titleWhenFold, ellipsis, fold, textContent]);\n useEffect(() => {\n if (runtime.inited) { \n runtime.onStatusChange?.({\n ellipsis,\n fold,\n title: hoverTitle\n });\n }\n }, [fold, ellipsis, hoverTitle]);\n useEffect(() => {\n runtime.inited = true;\n }, []);\n // 高度自适应,容器高度变化时重新计算高度(容器也需要包装Measure,TODO: 待开发 hooks -> useMeasure, 使得观测dom尺寸的方式更简洁)\n // if (!maxHeight && !lines) {\n // calcEllipsis();\n // }\n // console.log('[render TextEllipsis]: ellipsis fold wrapStyle: ', ellipsis, fold, wrapStyle);\n return (\n <div\n className={cx(c(\"container\"), className)}\n style={containerStyle}\n ref={(r) => {\n assignRef(containerRef, r);\n ref && assignRef(ref, r);\n }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onPointerEnter={onPointerEnter}\n onPointerLeave={onPointerLeave}\n onClick={onClick}\n onFocus={onFocus}\n >\n {/* 此dom仅用于计算高度 用.text-ellipsis-inner计算 在不重新初始化情况下切换文本时高度计算有问题 */}\n <Measure offset throttleMs={100} onResize={handleResize} triggerResizeInit={false}>\n {({measureRef, /* contentRect */}) => {\n // console.log('contentRect:', contentRect, contentRect.offset?.height, runtime.contentOffsetHeight);\n // const {height} = contentRect.offset || {};\n // if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n // calcEllipsis();\n // }\n return <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={(r) => {\n assignRef(measureRef, r);\n assignRef(wrapperRef, r);\n updateTextContent();\n }}>\n {finalContent}\n </div>\n }}\n </Measure>\n {/* <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={wrapperRef}>\n {finalContent}\n </div> */}\n {/* 主文本显示 */}\n <div\n className={\"text-ellipsis-inner\"}\n title={showTitleWhenFold ? hoverTitle : undefined}\n style={wrapStyle}\n ref={contentRef}\n >\n {/* {finalContent} */}\n {/* firefox >= 133 绝对定位的按钮放文本后面也会被截断隐藏!! , 放文本前面可解决 */}\n {ellipsis && showFoldControl && ButtonComp}\n {finalContent}\n {ButtonShadowDom}\n </div>\n </div>\n );\n});\n"],"names":["c","p","prefixClassname","TextEllipsis","forwardRef","props","ref","className","style","_props$lineHeight","lineHeight","lines","maskBgColor","_props$resetFoldWhenC","resetFoldWhenChildrenOrEllipsisChange","showTitleWhenFold","titleWhenFold","_props$showFoldContro","showFoldControl","_props$foldText","foldText","_props$unfoldText","unfoldText","_props$uiType","uiType","_props$truncateMode","truncateMode","maxHeight","_props$controlPlaceme","controlPlacement","whiteSpace","width","renderFoldButton","onEllipsisChange","onFoldChange","onStatusChange","onMouseEnter","onMouseLeave","onPointerEnter","onPointerLeave","onClick","onFocus","finalContent","content","children","_useState","useState","ellipsis","setEllipsis","_useState2","getLineHeightFail","setGetLineHeightFail","_useSyncPropsState","useSyncPropsState","defaultValue","onChange","fold","setFold","_useState3","foldBtnWidth","setFoldBtnWidth","_useState4","endsWith","parseFloat","innerLineHeight","setInnerLineHeight","_useState5","_useState5$","innerLines","setInnerLines","_useState6","textContent","setTextContent","runtime","useRuntime","inited","contentOffsetHeight","containerContentHeight","defaultFold","contentRef","useRef","wrapperRef","containerRef","btnWrapperRef","containerStyle","useMemo","_extends","undefined","commonWrapStyle","wrapStyle","isHeightMode","paddingBottom","minHeight","WebkitLineClamp","boxSizing","validMaskBgColor","_ref","rgbaToObj","findEffectiveBgColor","current","r","g","b","startColor","endColor","btnStyle","padding","ratio","Math","min","_ref2","_ref2$startColor","_ref2$endColor","height","paddingTop","paddingLeft","background","reorganizeDom","useCallback","orginStyleWidth","orginWidth","window","getComputedStyle","requestAnimationFrame","handleFoldChange","evt","ButtonComp","React","createElement","cx","ButtonShadowDom","resetState","newEllipsis","_temp","_ref3$forceResetFold","forceResetFold","preFold","calcEllipsis","wrapDom","containerDom","offsetHeight","clientHeight","realLineHeight","floor","adjustLines","useCompatibleEffect","useEffect","offsetWidth","isSafari","updateTextContent","newTextContent","handleResize","rect","offset","abs","hoverTitle","title","assignRef","Measure","throttleMs","onResize","triggerResizeInit","_ref6","measureRef"],"mappings":"u4BA+Ba,IAAAA,EAAIC,EAACC,gBAAC,yBA+HNC,EAAeC,EAAAA,WAA8C,SAACC,EAAOC,GAChF,IACEC,EA6BEF,EA7BFE,UACAC,EA4BEH,EA5BFG,MAAKC,EA4BHJ,EA3BFK,WAAAA,OAAU,IAAAD,EAAG,GAAEA,EACfE,EA0BEN,EA1BFM,MACAC,EAyBEP,EAzBFO,YAEQC,EAuBNR,EAtBFS,sCAAAA,OAAwC,IAAHD,GAAQA,EAC7CE,EAqBEV,EArBFU,kBACAC,EAoBEX,EApBFW,cAAaC,EAoBXZ,EAnBFa,gBAAAA,OAAkB,IAAHD,GAAOA,EAAAE,EAmBpBd,EAlBFe,SAAAA,OAAQ,IAAAD,EAAG,KAAIA,EAAAE,EAkBbhB,EAjBFiB,WAAAA,OAAa,IAAHD,EAAG,KAAIA,EAAAE,EAiBflB,EAhBFmB,OAAAA,OAAM,IAAAD,EAAG,QAAOA,EAAAE,EAgBdpB,EAfFqB,aAAAA,OAAe,IAAHD,EAAG,OAAMA,EACrBE,EAcEtB,EAdFsB,UAASC,EAcPvB,EAbFwB,iBAAAA,OAAgB,IAAAD,EAAG,SAAQA,EAC3BE,EAYEzB,EAZFyB,WACAC,EAWE1B,EAXF0B,MACAC,EAUE3B,EAVF2B,iBACAC,EASE5B,EATF4B,iBACAC,EAQE7B,EARF6B,aACAC,EAOE9B,EAPF8B,eACAC,EAME/B,EANF+B,aACAC,EAKEhC,EALFgC,aACAC,EAIEjC,EAJFiC,eACAC,EAGElC,EAHFkC,eACAC,EAEEnC,EAFFmC,QACAC,EACEpC,EADFoC,QAEIC,EADFrC,EAxBFsC,SAwBEtC,EAvBFuC,SA0BFC,EAAgCC,EAAQA,UAAC,GAAlCC,EAAQF,EAAA,GAAEG,EAAWH,EAAA,GAC5BI,EAAkDH,YAAS,GAApDI,EAAiBD,EAAEE,GAAAA,EAAoBF,EAE9C,GAAAG,EAAwBC,EAAiBA,kBAAChD,EAAO,OAAQ,CAACiD,cAAc,EAAMC,SAAUrB,IAAjFsB,GAAIJ,EAAA,GAAEK,GAAOL,EACpB,GAAAM,GAAwCZ,EAAAA,SAAS,GAA1Ca,GAAYD,GAAA,GAAEE,GAAeF,GAAA,GACpCG,GAA8Cf,EAAAA,SACtB,iBAAfpC,GAA2BA,EAAWoD,SAAS,MAClDC,WAAWrD,GACX,GAHCsD,GAAeH,GAAA,GAAEI,GAAkBJ,GAAA,GAK1CK,GAAwCpB,EAAQA,SAACnC,GAAMwD,GAAAD,GAAhDE,GAAAA,QAAa,IAAHD,GAAG,EAACA,GAAEE,GAAaH,GAAA,GAEpCI,GAAsCxB,WAAS,IAAxCyB,GAAWD,MAAEE,GAAcF,GAAA,GAE3BG,GAAWC,EAAAA,WAAW,CAC3BC,QAAQ,EACRC,oBAAqB,EACrBC,uBAAwB,EACxB9B,SAAAA,EACA+B,YAAatB,GACbA,KAAAA,GACAG,aAAAA,GACAY,YAAAA,GACAtC,iBAAAA,EACAC,aAAAA,EACAC,eAAAA,GACC,CAAC,OAAQ,mBAAoB,eAAgB,mBAEhD,GAAM4C,GAAaC,EAAAA,OAAuB,MACpCC,GAAaD,EAAMA,OAAiB,MACpCE,GAAeF,EAAMA,OAAiB,MACtCG,GAAgBH,SAAuB,MAEvCI,GAAiBC,EAAAA,QAAQ,WAC7B,OAAAC,EAAA,CACE5E,WAAYwC,EACR,MACAxC,QAA0B6E,GAC3B/E,EAEP,EAAG,CAACA,EAAOE,EAAYwC,IAEjBsC,GAAkBH,EAAOA,QAAC,WAC9B,MAAO,CACLvD,WAAAA,EACAC,MAAAA,EAEJ,EAAG,CAACD,EAAYC,IAEV0D,GAAYJ,EAAOA,QAAC,WACxB,IACMK,EAAgC,WAAjBhE,EACrB,IAAKqB,KAAa2C,GAFJtB,IAEgCJ,IAC5C,OAAOwB,GAET,IAAMG,EAAgBzE,GAA+B,WAAXM,IAAwBgC,GAAWQ,GAAsBuB,UAAAA,EACnG,OAAAD,EAAA,CAAA,EACKE,GAAe,CAElBI,WAAYF,GAAgBlC,IAThBY,GASmC,IAAOJ,GAAsBuB,UAAAA,EAI5EM,gBAAiBH,OAAeH,EAAY/B,GAbhCY,QAa+CmB,EAC3D5D,UAAW+D,GAAgBlC,GAAQ7B,GAdvByC,GAc4CJ,IAAmBS,GAAQI,wBAA0B,OAAKU,EAClHI,cAAAA,EACAG,UAAWH,EAAgB,kBAAwBJ,GAEvD,EAAG,CAACnB,GAAYJ,GAAiBjB,EAAUS,GAAMtC,EAAiBM,EAAQE,EAAcC,EAAW6D,KAG7FO,GAAmBV,UAAQ,WAC/B,IAAKnE,IAAoB6B,EACvB,OAAO,KAET,IAAAiD,EAAkBC,YAAUrF,GAAe,KAAOsF,EAAoBA,qBAAChB,GAAaiB,SAA7EC,EAACJ,EAADI,EAAGC,EAACL,EAADK,EAAGC,EAACN,EAADM,EACb,MAAO,CACLC,WAAoBH,QAAAA,EAAMC,KAAAA,EAAMC,KAAAA,WAChCE,SAAkBJ,QAAAA,EAAMC,KAAAA,EAAMC,KAAAA,SAElC,EAAG,CAAC1F,EAAamC,EAAU7B,IAGrBuF,GAAWpB,EAAOA,QAAC,WACvB,GAAK7B,GAAL,CAIA,IAAMkD,EAAU1C,GAEV2C,EAAmB,UAAXnF,EAAqBoF,KAAKC,IAAKH,EAAU/C,GAAgB,IAAK,IAAM,GAClFmD,EAAiFf,IAAoB,GAAEgB,EAAAD,EAAhGP,WAAoCS,EAAAF,EAAEN,SAAAA,OAAQ,IAAAQ,EAAG,sBAAqBA,EAC7E,MAAO,CACLlB,UAAW,cACXmB,OAAWjD,GAAmB,KAC9BtD,WAAesD,GAAe,KAC9BkD,WAAuB,WAAX1F,EAAyBkF,EAAO,UAAOnB,EACnD4B,YAAwB,UAAX3F,EAAwBkF,EAAO,UAAOnB,EAEnD6B,WAAkC5F,sBAAAA,EAAW+E,WAR9B,IAAAQ,EAAG,wBAAuBA,GAQmBP,KAAAA,EAAYG,IAAAA,EAAWH,MAAAA,WAbpF,CAeH,EAAG,CAACxC,GAAiBR,GAAMhC,EAAQmC,GAAcoC,KAE3CsB,GAAgBC,EAAAA,YAAY,WAEhC,GAAIvC,GAAWoB,QAAS,CACtB,IAAMoB,EAAkBxC,GAAWoB,QAAQ3F,MAAMuB,MAC3CyF,EAAaC,OAAOC,iBAAiB3C,GAAWoB,SAASpE,MAE/DgD,GAAWoB,QAAQ3F,MAAMuB,MAAWgC,WAAWyD,GAAc,GAAG,KACpC,MAA5BC,OAAOE,uBAAPF,OAAOE,sBAAwB,WACzB5C,GAAWoB,UACbpB,GAAWoB,QAAQ3F,MAAMuB,MAAQwF,EAErC,EACD,CACH,EAAG,IAEGK,GAAmBN,EAAWA,YAClC,SAACO,EAAkCrE,QAAAA,IAAAA,IAAAA,GAAQiB,GAAQjB,MACjDiB,GAAQjB,KAAOA,EACfC,GAAQD,EACZ,EAAG,IAEGsE,GAAazC,EAAOA,QAAC,wBACzB,OACE0C,EAAAA,QAAAC,cAAA,MAAA,CACEzH,UAAW0H,EAAAA,WACT,mBACoBzG,oBAAAA,EACT,WAAXA,GAAoCK,aAAAA,GAEtCrB,MAAOiG,GACPnG,IAAK6E,GACL3C,QAASoF,IAER5F,EACCA,EAAiBwB,iBAEjBuE,EAAA,QAAAC,cAAA,MAAA,CAAKzH,UAAW,YAAaiD,GAAOlC,EAAaF,GAIzD,EAAG,CACDqF,GACAjD,GACApC,EACAwG,GACA5F,EACAH,EACAL,EACAF,IAII4G,GAAkB7C,UAAQ,WAC9B,OAAKnE,GAA8B,UAAXM,GAAsBgC,qBAGvCuE,EAAA,QAAAC,cAAA,OAAA,CAAMxH,MAAOiG,GAAUlG,UAAU,yBACrCyB,EAAmBA,EAAiBwB,IAAQpC,EAEjD,EAAG,CAACI,EAAQN,EAAiBsC,GAAMiD,GAAUrF,EAAUY,IAGjDmG,GAAab,EAAWA,YAAC,SAACc,EAAWC,QAAA,IAAXD,IAAAA,EAAc3D,GAAQ1B,UAAQ,IAExDuF,QAFwD,IAAAD,EAE1D,CAAE,EAAAA,GADJE,eAAAA,OAAc,IAAAD,GAAQA,EAEfvF,EAAwC0B,GAAxC1B,SAAgByF,EAAwB/D,GAA9BjB,KAAesB,EAAeL,GAAfK,YAC5BsD,IAAgBrF,IAClBC,EAAYoF,GACZ3D,GAAQ1B,SAAWqF,EACnB3D,MAAAA,GAAQxC,kBAARwC,GAAQxC,iBAAmBmG,IAI3BtH,IACIyH,IAAoBxF,GAAYqF,IACjCI,IAAY1D,GAEf8C,QAAiBrC,EAAWT,EAEhC,EAAG,CAAC8C,GAAkBlF,EAAc5B,IAE9B2H,GAAenB,EAAAA,YAAY,WAC/B,IAAMoB,EAAUzD,GAAWkB,QACrBwC,EAAezD,GAAaiB,QAClC,GAAKuC,GAAYC,EAAjB,CAGAlE,GAAQG,oBAAsB8D,EAAQE,aACtC,IAAMxD,EAAiBqC,OAAOC,iBAAiBiB,GACzCzB,EAAanD,WAAWqB,EAAe8B,YACvCvB,EAAgB5B,WAAWqB,EAAeO,eAC1Cd,EAAyBJ,GAAQI,uBAAyB8D,EAAaE,aAAe3B,EAAavB,EAGrGmD,EAAiB,EAErB,IAAKA,GAAkBJ,EAAS,CAC9B,IAAOhI,GAAc0E,GAAkB,CAAE,GAAlC1E,WACHA,KAEFoI,EAAiB/E,WAAWrD,KAE1ByC,GAAqB,GAG1B,CAED,GAAIa,KAAoB8E,IACtB7E,GAAmB6E,GACdA,GAOP,GAFsC,WAAjBpH,EAGnByG,GAAW1D,GAAQG,qBAAuBjD,GAAakD,SAKzD,GAAKlE,EAWCyD,KAAezD,GACjB0D,GAAc1D,GAIdwH,GAAW1D,GAAQG,sBAAwBjE,EAAQ,GAAKiG,KAAKmC,MAAMD,GAAkB,QAfvF,GAAIrE,GAAQG,oBAAsBC,EAAwB,CACtD,IAAMmE,EAAcpC,KAAKmC,MAAMlE,EAAyBiE,IAAmB,EACvE1E,KAAe4E,GACjB3E,GAAc2E,GAEhBb,IAAW,EACd,MACCA,IAAW,EA5Cd,CAsDH,EAAG,CAACxH,EAAOqD,GAAiBtC,EAAcC,EAAWwG,KAIrDc,EAAmBA,oBAAC,WAClBd,GAAW1D,GAAQ1B,SAAU,CAC3BwF,gBAAgB,IAElBE,IACF,EAAG,CAACA,GAAcN,KAGlBe,EAASA,UAAC,WACR,GAAInG,GAAYoC,GAAcgB,QAAS,CACrC,IAAOgD,EAAehE,GAAcgB,QAA7BgD,YACHA,IAAgB1E,GAAQd,eAC1Bc,GAAQd,aAAewF,EACvBvF,GAAgBuF,GAEnB,CACH,EAAG,CAACpG,EAAUzB,EAAYJ,IAC1BgI,EAASA,UAAC,WACJE,EAAAA,UACF/B,IAEJ,EAAG,CAAC7D,GAAM6D,KACV,IAAMgC,GAAoB/B,EAAAA,YAAY,WACpC,GAAKrC,GAAWkB,QAAhB,CAGA,IAAMmD,EAAiBrE,GAAWkB,QAAQ5B,aAAe,GACrD+E,IAAmB7E,GAAQF,cAC7BE,GAAQF,YAAc+E,EACtB9E,GAAe8E,GAJhB,CAMH,EAAG,IACGC,GAAejC,EAAWA,YAAwC,SAACkC,GAEvE,IAAOvC,GAAUuC,EAAKC,QAAU,CAAE,GAA3BxC,YACQ1B,IAAX0B,GAAwBL,KAAK8C,IAAIzC,EAASxC,GAAQG,qBAAuB,GAC3E6D,IAEJ,EAAG,CAACA,KACEkB,GAAatE,UAAQ,WACvB,OAAOtC,GAAYS,GACW,mBAAlBxC,EACNA,EAAcuD,IACdvD,GAAiBuD,QACnBgB,CACR,EAAG,CAACvE,EAAe+B,EAAUS,GAAMe,KAkBnC,OAjBA2E,EAAAA,UAAU,WACJzE,GAAQE,SACY,MAAtBF,GAAQtC,gBAARsC,GAAQtC,eAAiB,CACrBY,SAAAA,EACAS,KAAAA,GACAoG,MAAOD,KAGf,EAAG,CAACnG,GAAMT,EAAU4G,KACpBT,EAAAA,UAAU,WACRzE,GAAQE,QAAS,CACnB,EAAG,iBAODoD,EAAAA,QAAAC,cACEzH,MAAAA,CAAAA,UAAW0H,EAAAA,WAAGjI,EAAE,aAAcO,GAC9BC,MAAO4E,GACP9E,IAAK,SAAC8F,GACJyD,EAAAA,UAAU3E,GAAckB,GACxB9F,GAAOuJ,EAAAA,UAAUvJ,EAAK8F,EACxB,EACAhE,aAAcA,EACdC,aAAcA,EACdC,eAAgBA,EAChBC,eAAgBA,EAChBC,QAASA,EACTC,QAASA,gBAGTsF,EAAAA,QAAAC,cAAC8B,EAAAA,QAAO,CAACL,QAAM,EAACM,WAAY,IAAKC,SAAUT,GAAcU,mBAAmB,GACzE,SAAAC,GAAE,IAAAC,EAAUD,EAAVC,wBAMD,OAAOpC,EAAAA,QAAAC,cAAKxH,MAAAA,CAAAA,MAAOgF,GAAiBjF,UAAW,qBAAsBD,IAAK,SAAC8F,GACzEyD,EAASA,UAACM,EAAY/D,GACtByD,EAAAA,UAAU5E,GAAYmB,GACtBiD,IACF,GACG3G,EAEL,gBAMFqF,EAAA,QAAAC,cACEzH,MAAAA,CAAAA,UAAW,sBACXqJ,MAAO7I,EAAoB4I,QAAapE,EACxC/E,MAAOiF,GACPnF,IAAKyE,IAIJhC,GAAY7B,GAAmB4G,GAC/BpF,EACAwF,IAIT"}
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/index.tsx"],"sourcesContent":["/**\n * @file 文本截断显示组件\n * @description 基于React封装一个文本截断显示组件,富文本(仅文字样式,图片和表格效果不一定好)同普通文本处理一致\n * @author <wuqiuyang305@126.com>\n */\n\nimport React, {\n forwardRef,\n useState,\n useMemo,\n useEffect,\n useCallback,\n useRef,\n PropsWithChildren,\n MouseEvent,\n} from \"react\";\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {\n assignRef,\n useRuntime,\n useCompatibleEffect,\n useSyncPropsState,\n} from \"@ohkit/react-helper\";\nimport {isSafari} from \"@ohkit/platform\";\nimport {rgbaToObj, findEffectiveBgColor} from \"@ohkit/dom-helper\";\nimport {Measure, MeasureProps} from \"@ohkit/measure\";\nimport \"./style.scss\";\n\nexport const c = p(\"ohkit-text-ellipsis__\");\n\ninterface ITextEllipsis\n extends Pick<\n React.DOMAttributes<HTMLDivElement>,\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onFocus\"\n | \"onClick\"\n > {\n /**\n * 自定义样式类名,会附加到根元素上\n */\n className?: string;\n /**\n * 自定义样式\n */\n style?: React.CSSProperties;\n /**\n * right | bottom 展开按钮在右下侧还是底部\n * @default right\n */\n uiType?: \"right\" | \"bottom\";\n /**\n * 截断模式 (若某些浏览器不支持 webkitLineClamp,可降级切换为 height 模式)\n * @default line\n */\n truncateMode?: \"line\" | \"height\";\n /**\n * truncateMode === \"height\" 时生效\n * 最大高度(number > 0),没传或者传入无效值不限制,尝试取 lines * lineHeight,若仍无效 自动截断到容器的最大高度\n * 单位: px\n */\n maxHeight?: number;\n /**\n * (单位:px)未传入或无效(0也视为无效)则自动取当前文本的行高\n */\n lineHeight?: React.CSSProperties[\"lineHeight\"];\n /**\n * truncateMode === \"line\" 时生效\n * 超过几行折叠(number > 0), 没传或者传入无效值不限制,自动截断到容器的最大高度\n */\n lines?: number;\n /**\n * 展开按钮蒙层背景色(仅支持16进制表示)\n * @default #fff\n */\n maskBgColor?: string;\n /**\n * text|ReactNode 与children任传一个\n */\n content?: React.ReactNode;\n /**\n * 当 content or children or ellipsis 变化时,重置 fold 状态 \n * @default false\n */\n resetFoldWhenChildrenOrEllipsisChange?: boolean;\n /**\n * 折叠状态\n * @default true\n */\n fold?: boolean;\n /**\n * 显示展开控制按钮\n * @default true\n */\n showFoldControl?: boolean;\n /**\n * 展开按钮位置 uiType='bottom'时有效\n * @default center\n */\n controlPlacement?: 'left' | 'center' | 'right';\n /**\n * 折叠按钮文字\n * @default 收起\n */\n foldText?: string;\n /**\n * 展开按钮文字\n * @default 展开\n */\n unfoldText?: string;\n /**\n * 折叠状态下是否显示title属性\n * @default false\n */\n showTitleWhenFold?: boolean;\n /**\n * 折叠状态自定义title属性内容\n */\n titleWhenFold?: string | ((title: string) => string);\n /**\n * 是否保留换行\n */\n whiteSpace?: React.CSSProperties['whiteSpace'];\n /**\n * 容器宽度(默认自适应内容)\n * 应用场景:whiteSpace='pre*' 时,支持展示换行符,自适应内容可能导致控制按钮位置不确定\n */\n width?: React.CSSProperties['width'];\n /**\n * 自定义渲染展开按钮\n */\n renderFoldButton?: (fold: boolean) => React.ReactNode;\n /**\n * @param fold 折叠状态,true 折叠,false 展开\n */\n onFoldChange?: (fold: boolean) => void;\n /**\n * @param ellipsis 是否截断,true 截断,false 未截断\n */\n onEllipsisChange?: (ellipsis: boolean) => void;\n /**\n * 关键状态变更触发\n * @param status\n */\n onStatusChange?: (status: {\n fold: boolean;\n ellipsis: boolean;\n title?: string;\n }) => void;\n}\n\nexport type TextEllipsisProps = PropsWithChildren<ITextEllipsis>;\n\nexport const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>(function TextEllipsis(props, ref) {\n const {\n className,\n style,\n lineHeight = \"\",\n lines,\n maskBgColor,\n content,\n children,\n resetFoldWhenChildrenOrEllipsisChange = false,\n showTitleWhenFold,\n titleWhenFold,\n showFoldControl = true,\n foldText = \"收起\",\n unfoldText = \"展开\",\n uiType = \"right\",\n truncateMode = \"line\",\n maxHeight,\n controlPlacement = 'center',\n whiteSpace,\n width,\n renderFoldButton,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n onMouseEnter,\n onMouseLeave,\n onPointerEnter,\n onPointerLeave,\n onClick,\n onFocus,\n } = props;\n const finalContent = content || children;\n // 是否截断\n const [ellipsis, setEllipsis] = useState(false);\n const [getLineHeightFail, setGetLineHeightFail] = useState(false);\n // 折叠状态\n const [fold, setFold] = useSyncPropsState(props, 'fold', {defaultValue: true, onChange: onFoldChange});\n const [foldBtnWidth, setFoldBtnWidth] = useState(1);\n const [innerLineHeight, setInnerLineHeight] = useState(\n typeof lineHeight === \"string\" && lineHeight.endsWith(\"px\")\n ? parseFloat(lineHeight)\n : 0\n );\n const [innerLines = 0, setInnerLines] = useState(lines);\n // children提取的纯文本\n const [textContent, setTextContent] = useState('');\n\n const [runtime] = useRuntime({\n inited: false, // mounted\n contentOffsetHeight: 0, // 内容节点offsetHeight\n containerContentHeight: 0, // 容器内容高度 = 容器高 - 上下padding\n ellipsis,\n defaultFold: fold, // 记录一下默认的折叠状态,用于 reset fold\n fold,\n foldBtnWidth,\n textContent,\n onEllipsisChange,\n onFoldChange,\n onStatusChange,\n }, ['fold', 'onEllipsisChange', 'onFoldChange', 'onStatusChange']);\n\n const contentRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const btnWrapperRef = useRef<HTMLDivElement>(null);\n\n const containerStyle = useMemo(() => {\n return {\n lineHeight: getLineHeightFail // 未传入且获取 lineHeight(px) 失败,则设置 default lineHeight: 1.4(em)\n ? \"1.4\" // more brower normal default lineHeight\n : lineHeight ? lineHeight : undefined,\n ...style,\n };\n }, [style, lineHeight, getLineHeightFail]);\n\n const commonWrapStyle = useMemo(() => {\n return {\n whiteSpace,\n width,\n };\n }, [whiteSpace, width]);\n // 容器样式\n const wrapStyle = useMemo(() => {\n const lines = innerLines;\n const isHeightMode = truncateMode === 'height';\n if (!ellipsis || !isHeightMode && (!lines || !innerLineHeight)) {\n return commonWrapStyle;\n }\n const paddingBottom = showFoldControl && (uiType === \"bottom\" && !fold) ? `${innerLineHeight}px` : undefined;\n return {\n ...commonWrapStyle,\n // HACK: 兼容safari 15+ 富文本折叠高度丢失问题\n minHeight: !isHeightMode && fold ? `${(lines - 0.2) * innerLineHeight}px` : undefined,\n // Note: safari 对WebkitLineClamp支持太差劲 判断浏览器优雅降级为高度截断方案?目前先交给用户去判断,自行选择truncateMode\n // WebkitLineClamp: isSafari ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n // maxHeight: isSafari && fold ? lines * innerLineHeight : undefined,\n WebkitLineClamp: isHeightMode ? undefined : fold ? lines : undefined, // 利用-webkit-line-clamp截断方案\n maxHeight: isHeightMode && fold ? (maxHeight || lines * innerLineHeight || runtime.containerContentHeight || 0) : undefined,\n paddingBottom,\n boxSizing: paddingBottom ? 'border-box' as const : undefined,\n };\n }, [innerLines, innerLineHeight, ellipsis, fold, showFoldControl, uiType, truncateMode, maxHeight, commonWrapStyle]);\n\n // 计算折叠按钮蒙层的渐变颜色\n const validMaskBgColor = useMemo(() => {\n if (!showFoldControl || !ellipsis) {\n return null;\n }\n const {r, g, b} = rgbaToObj(maskBgColor || '') || findEffectiveBgColor(containerRef.current);\n return {\n startColor: `rgba(${r}, ${g}, ${b}, 0.2)`,\n endColor: `rgba(${r}, ${g}, ${b}, 1)`,\n };\n }, [maskBgColor, ellipsis, showFoldControl]);\n\n // 展开|收起 按钮样式\n const btnStyle = useMemo(() => {\n if (!fold) {\n return;\n }\n // 按钮padding,取行高\n const padding = innerLineHeight;\n // 蒙层透明度所占比例\n const ratio = uiType === \"right\" ? Math.min((padding / foldBtnWidth) * 100, 80) : 60;\n const {startColor = 'rgba(255,255,255,0.2)', endColor = 'rgba(255,255,255,1)'} = validMaskBgColor || {};\n return {\n boxSizing: 'content-box' as const,\n height: `${innerLineHeight}px`,\n lineHeight: `${innerLineHeight}px`,\n paddingTop: uiType === \"bottom\" ? `${padding}px` : undefined,\n paddingLeft: uiType === \"right\" ? `${padding}px` : undefined,\n // 渐变蒙层\n background: `linear-gradient(to ${uiType}, ${startColor}, ${endColor} ${ratio}%, ${endColor} 100%)`,\n };\n }, [innerLineHeight, fold, uiType, foldBtnWidth, validMaskBgColor]);\n\n const reorganizeDom = useCallback(() => {\n // Note: safari 中仅改变 WebkitLineClamp 没触发重排,调整微小宽度以触发\n if (contentRef.current) {\n const orginStyleWidth = contentRef.current.style.width;\n const orginWidth = window.getComputedStyle(contentRef.current).width;\n // console.log('orginWidth, orginStyleWidth:', orginWidth, orginStyleWidth);\n contentRef.current.style.width = `${parseFloat(orginWidth) - 0.1}px`;\n window.requestAnimationFrame?.(() => {\n if (contentRef.current) {\n contentRef.current.style.width = orginStyleWidth;\n }\n });\n }\n }, []);\n\n const handleFoldChange = useCallback(\n (evt?: MouseEvent<HTMLDivElement>, fold = !runtime.fold) => {\n runtime.fold = fold;\n setFold(fold);\n }, []);\n\n const ButtonComp = useMemo(() => {\n return (\n <div\n className={cx(\n \"btn-fold-wrapper\",\n `btn-fold-wrapper-${uiType}`,\n uiType === \"bottom\" && `placement-${controlPlacement}`\n )}\n style={btnStyle}\n ref={btnWrapperRef}\n onClick={handleFoldChange}\n >\n {renderFoldButton ? (\n renderFoldButton(fold)\n ) : (\n <div className={\"btn-fold\"}>{fold ? unfoldText : foldText}</div>\n )}\n </div>\n );\n }, [\n btnStyle,\n fold,\n foldText,\n handleFoldChange,\n renderFoldButton,\n controlPlacement,\n uiType,\n unfoldText,\n ]);\n\n // 占位按钮\n const ButtonShadowDom = useMemo(() => {\n if (!ellipsis || !showFoldControl || uiType !== 'right' || fold) {\n return null;\n }\n return <span style={btnStyle} className=\"btn-fold-right-shadow\">\n {renderFoldButton ? renderFoldButton(fold) : foldText}\n </span>;\n }, [ellipsis, uiType, showFoldControl, fold, btnStyle, foldText, renderFoldButton]);\n\n // 重置状态\n const resetState = useCallback((newEllipsis = runtime.ellipsis, {\n forceResetFold = false, // 强制重置fold 比如child变化时\n } = {}) => {\n const {ellipsis, fold: preFold, defaultFold} = runtime;\n if (newEllipsis !== ellipsis) {\n setEllipsis(newEllipsis);\n runtime.ellipsis = newEllipsis;\n runtime.onEllipsisChange?.(newEllipsis);\n }\n // 从未截断状态切换为截断状态时,自动折叠(即:出现展开按钮)\n if (\n resetFoldWhenChildrenOrEllipsisChange\n && (forceResetFold || !ellipsis && newEllipsis)\n && preFold !== defaultFold\n ) {\n handleFoldChange(undefined, defaultFold);\n }\n }, [handleFoldChange, finalContent, resetFoldWhenChildrenOrEllipsisChange]);\n\n const calcEllipsis = useCallback(() => {\n const wrapDom = wrapperRef.current;\n const containerDom = containerRef.current;\n if (!wrapDom || !containerDom) {\n return;\n }\n runtime.contentOffsetHeight = wrapDom.offsetHeight;\n const containerStyle = window.getComputedStyle(containerDom);\n const paddingTop = parseFloat(containerStyle.paddingTop);\n const paddingBottom = parseFloat(containerStyle.paddingBottom);\n const containerContentHeight = runtime.containerContentHeight = containerDom.clientHeight - paddingTop - paddingBottom;\n\n // 计算真实行高\n let realLineHeight = 0;\n // 若外部未传入, 尝试读取当前文本的行高。\n if (!realLineHeight && wrapDom) {\n const {lineHeight} = containerStyle || {};\n if (lineHeight) {\n // 未设置行高的为 normal\n realLineHeight = parseFloat(lineHeight);\n if (!realLineHeight) {\n setGetLineHeightFail(true);\n }\n }\n }\n // lineHeight同步到innerLineHeight\n if (innerLineHeight !== realLineHeight) {\n setInnerLineHeight(realLineHeight);\n if (!realLineHeight) {\n return;\n }\n }\n\n const isHeightMode = truncateMode === 'height';\n // 高度截断模式,比较简单 直接判断是否超出容器高度\n if (isHeightMode) {\n resetState(runtime.contentOffsetHeight > (maxHeight || containerContentHeight));\n return;\n }\n\n // 行数截断模式,需要利用行高计算是否超出容器高度\n if (!lines) {\n if (runtime.contentOffsetHeight > containerContentHeight) {\n const adjustLines = Math.floor(containerContentHeight / realLineHeight) || 1;\n if (innerLines !== adjustLines) {\n setInnerLines(adjustLines);\n }\n resetState(true);\n } else {\n resetState(false);\n }\n } else {\n if (innerLines !== lines) {\n setInnerLines(lines);\n }\n // console.log('contentOffsetHeight, realLineHeight', runtime.contentOffsetHeight, realLineHeight);\n // 允许误差1px(行高为小数时, safari计算行高*行数和实践总高有差异,故将行高向下取整兼容)\n resetState(runtime.contentOffsetHeight >= (lines + 1) * Math.floor(realLineHeight) - 1);\n }\n }, [lines, innerLineHeight, truncateMode, maxHeight, resetState]);\n\n // 监听内容高度,是否需要折叠\n // 用useLayoutEffect方式闪屏显示\n useCompatibleEffect(() => {\n resetState(runtime.ellipsis, {\n forceResetFold: true,\n });\n calcEllipsis();\n }, [calcEllipsis, resetState]);\n\n // 监听\"展开\"按钮宽度变化\n useEffect(() => {\n if (ellipsis && btnWrapperRef.current) {\n const {offsetWidth} = btnWrapperRef.current;\n if (offsetWidth !== runtime.foldBtnWidth) {\n runtime.foldBtnWidth = offsetWidth;\n setFoldBtnWidth(offsetWidth);\n }\n }\n }, [ellipsis, unfoldText, showFoldControl]);\n useEffect(() => {\n if (isSafari) {\n reorganizeDom();\n }\n }, [fold, reorganizeDom]);\n const updateTextContent = useCallback(() => {\n if (!wrapperRef.current) {\n return;\n }\n const newTextContent = wrapperRef.current.textContent || '';\n if (newTextContent !== runtime.textContent) {\n runtime.textContent = newTextContent;\n setTextContent(newTextContent);\n }\n }, []);\n const handleResize = useCallback<NonNullable<MeasureProps['onResize']>>((rect) => {\n // console.log('[handleResize] rect: ', rect, runtime.contentOffsetHeight);\n const {height} = rect.offset || {};\n if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n calcEllipsis();\n }\n }, [calcEllipsis]);\n const hoverTitle = useMemo(() => {\n return ellipsis && fold\n ? (typeof titleWhenFold === 'function'\n ? titleWhenFold(textContent)\n : titleWhenFold || textContent)\n : undefined;\n }, [titleWhenFold, ellipsis, fold, textContent]);\n useEffect(() => {\n if (runtime.inited) { \n runtime.onStatusChange?.({\n ellipsis,\n fold,\n title: hoverTitle\n });\n }\n }, [fold, ellipsis, hoverTitle]);\n useEffect(() => {\n runtime.inited = true;\n }, []);\n // 高度自适应,容器高度变化时重新计算高度(容器也需要包装Measure,TODO: 待开发 hooks -> useMeasure, 使得观测dom尺寸的方式更简洁)\n // if (!maxHeight && !lines) {\n // calcEllipsis();\n // }\n // console.log('[render TextEllipsis]: ellipsis fold wrapStyle: ', ellipsis, fold, wrapStyle);\n return (\n <div\n className={cx(c(\"container\"), className)}\n style={containerStyle}\n ref={(r) => {\n assignRef(containerRef, r);\n if (ref) {\n assignRef(ref, r);\n }\n }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onPointerEnter={onPointerEnter}\n onPointerLeave={onPointerLeave}\n onClick={onClick}\n onFocus={onFocus}\n >\n {/* 此dom仅用于计算高度 用.text-ellipsis-inner计算 在不重新初始化情况下切换文本时高度计算有问题 */}\n <Measure offset throttleMs={100} onResize={handleResize} triggerResizeInit={false}>\n {({measureRef, /* contentRect */}) => {\n // console.log('contentRect:', contentRect, contentRect.offset?.height, runtime.contentOffsetHeight);\n // const {height} = contentRect.offset || {};\n // if (height !== undefined && Math.abs(height - runtime.contentOffsetHeight) > 1) {\n // calcEllipsis();\n // }\n return <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={(r) => {\n assignRef(measureRef, r);\n assignRef(wrapperRef, r);\n updateTextContent();\n }}>\n {finalContent}\n </div>\n }}\n </Measure>\n {/* <div style={commonWrapStyle} className={\"content-shadow-dom\"} ref={wrapperRef}>\n {finalContent}\n </div> */}\n {/* 主文本显示 */}\n <div\n className={\"text-ellipsis-inner\"}\n title={showTitleWhenFold ? hoverTitle : undefined}\n style={wrapStyle}\n ref={contentRef}\n >\n {/* {finalContent} */}\n {/* firefox >= 133 绝对定位的按钮放文本后面也会被截断隐藏!! , 放文本前面可解决 */}\n {ellipsis && showFoldControl && ButtonComp}\n {finalContent}\n {ButtonShadowDom}\n </div>\n </div>\n );\n});\n"],"names":["c","p","prefixClassname","TextEllipsis","forwardRef","props","ref","className","style","_props$lineHeight","lineHeight","lines","maskBgColor","_props$resetFoldWhenC","resetFoldWhenChildrenOrEllipsisChange","showTitleWhenFold","titleWhenFold","_props$showFoldContro","showFoldControl","_props$foldText","foldText","_props$unfoldText","unfoldText","_props$uiType","uiType","_props$truncateMode","truncateMode","maxHeight","_props$controlPlaceme","controlPlacement","whiteSpace","width","renderFoldButton","onEllipsisChange","onFoldChange","onStatusChange","onMouseEnter","onMouseLeave","onPointerEnter","onPointerLeave","onClick","onFocus","finalContent","content","children","_useState","useState","ellipsis","setEllipsis","_useState2","getLineHeightFail","setGetLineHeightFail","_useSyncPropsState","useSyncPropsState","defaultValue","onChange","fold","setFold","_useState3","foldBtnWidth","setFoldBtnWidth","_useState4","endsWith","parseFloat","innerLineHeight","setInnerLineHeight","_useState5","_useState5$","innerLines","setInnerLines","_useState6","textContent","setTextContent","runtime","useRuntime","inited","contentOffsetHeight","containerContentHeight","defaultFold","contentRef","useRef","wrapperRef","containerRef","btnWrapperRef","containerStyle","useMemo","_extends","undefined","commonWrapStyle","wrapStyle","isHeightMode","paddingBottom","minHeight","WebkitLineClamp","boxSizing","validMaskBgColor","_ref","rgbaToObj","findEffectiveBgColor","current","r","g","b","startColor","endColor","btnStyle","padding","ratio","Math","min","_ref2","_ref2$startColor","_ref2$endColor","height","paddingTop","paddingLeft","background","reorganizeDom","useCallback","orginStyleWidth","orginWidth","window","getComputedStyle","requestAnimationFrame","handleFoldChange","evt","ButtonComp","React","createElement","cx","classNames","ButtonShadowDom","resetState","newEllipsis","_temp","_ref3$forceResetFold","forceResetFold","preFold","calcEllipsis","wrapDom","containerDom","offsetHeight","clientHeight","realLineHeight","floor","adjustLines","useCompatibleEffect","useEffect","offsetWidth","isSafari","updateTextContent","newTextContent","handleResize","rect","offset","abs","hoverTitle","title","assignRef","Measure","throttleMs","onResize","triggerResizeInit","_ref6","measureRef"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ohkit/text-ellipsis",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "text ellipsis for react",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"text ellipsis"
|
|
7
7
|
],
|
|
8
8
|
"author": "wuqiuyang <wuqiuyang305@126.com>",
|
|
9
|
-
"homepage": "",
|
|
9
|
+
"homepage": "https://wuqiuyang.github.io/ohkit/storybook-static",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"source": "src/index.@(js|jsx|mjs|ts|tsx)",
|
|
12
12
|
"main": "dist/index.js",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"react": ">=16.8.0",
|
|
47
47
|
"react-dom": ">=16.8.0"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "7d81004d7d8851f4910a44a0210719c26f8c2064"
|
|
50
50
|
}
|
package/src/index.tsx
CHANGED
|
@@ -156,7 +156,7 @@ interface ITextEllipsis
|
|
|
156
156
|
|
|
157
157
|
export type TextEllipsisProps = PropsWithChildren<ITextEllipsis>;
|
|
158
158
|
|
|
159
|
-
export const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>((props, ref)
|
|
159
|
+
export const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>(function TextEllipsis(props, ref) {
|
|
160
160
|
const {
|
|
161
161
|
className,
|
|
162
162
|
style,
|
|
@@ -346,13 +346,13 @@ export const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>((props
|
|
|
346
346
|
|
|
347
347
|
// 占位按钮
|
|
348
348
|
const ButtonShadowDom = useMemo(() => {
|
|
349
|
-
if (!showFoldControl || uiType !== 'right' || fold) {
|
|
349
|
+
if (!ellipsis || !showFoldControl || uiType !== 'right' || fold) {
|
|
350
350
|
return null;
|
|
351
351
|
}
|
|
352
352
|
return <span style={btnStyle} className="btn-fold-right-shadow">
|
|
353
353
|
{renderFoldButton ? renderFoldButton(fold) : foldText}
|
|
354
354
|
</span>;
|
|
355
|
-
}, [uiType, showFoldControl, fold, btnStyle, foldText, renderFoldButton]);
|
|
355
|
+
}, [ellipsis, uiType, showFoldControl, fold, btnStyle, foldText, renderFoldButton]);
|
|
356
356
|
|
|
357
357
|
// 重置状态
|
|
358
358
|
const resetState = useCallback((newEllipsis = runtime.ellipsis, {
|
|
@@ -506,7 +506,9 @@ export const TextEllipsis = forwardRef<HTMLDivElement, TextEllipsisProps>((props
|
|
|
506
506
|
style={containerStyle}
|
|
507
507
|
ref={(r) => {
|
|
508
508
|
assignRef(containerRef, r);
|
|
509
|
-
|
|
509
|
+
if (ref) {
|
|
510
|
+
assignRef(ref, r);
|
|
511
|
+
}
|
|
510
512
|
}}
|
|
511
513
|
onMouseEnter={onMouseEnter}
|
|
512
514
|
onMouseLeave={onMouseLeave}
|