@strg/react-snip
Version:
React component to clamp text to a specified number of lines.
2 lines (1 loc) • 3.19 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ReactSnip={},e.React)}(this,function(e,c){"use strict";function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function d(e,t){(t=t.current.element).observer&&(t.observer.disconnect(),t.prevWidth=null,t.prevHeight=null,t.observer=null)}function p(e){var t=window.getComputedStyle(e),e=parseInt(t.height),t="normal"===t.lineHeight?1.2*parseInt(t.fontSize):parseInt(t.lineHeight);return 0===e&&0===t?0:Math.ceil(e/t)}function n(e){var t;return{method:"undefined"!=typeof CSS&&CSS.supports("display","-webkit-box")&&CSS.supports("-webkit-line-clamp","3")&&CSS.supports("-webkit-box-orient","vertical")?null!==(t=null==e?void 0:e.method)&&void 0!==t?t:r:"js",lines:null!==(t=null==e?void 0:e.lines)&&void 0!==t?t:i,midWord:null!==(t=null==e?void 0:e.midWord)&&void 0!==t?t:l,ellipsis:null!==(e=null==e?void 0:e.ellipsis)&&void 0!==e?e:o}}function u(u,e){var s=c.useRef({});c.useLayoutEffect(function(){s.current.options=n(e)},[e]),c.useLayoutEffect(function(){s.current.element={fullText:u.current.textContent}},[u]),c.useLayoutEffect(function(){var e,t,n,r="undefined"!=typeof ResizeObserver,i="js"===s.current.options.method,l=!!s.current.element.observer,o=r&&i&&!l,r=r&&!i&&l;return o&&(e=u,n=(t=s).current.element,(i=n.observer||new ResizeObserver(function(){e.current.clientWidth===n.prevWidth&&e.current.clientHeight===n.prevHeight||f(e,t)})).observe(e.current),n.observer=i),r&&d(0,s),o||f(u,s),function(){return l&&d(0,s)}},[u,s.current.options])}var s=t(c),r="css",i=3,l=!0,o=". . .",f=function(e,t){var n,r,i,l,o,u=t.current,s=u.options,c=u.element;if("css"===s.method)return n=e,r=(u=(r=t).current).options,u=u.element,n.current.textContent=u.fullText,n.current.style.display="-webkit-box",n.current.style.webkitLineClamp=""+r.lines,n.current.style.webkitBoxOrient="vertical",void(n.current.style.overflow="hidden");"js"===s.method&&(i=e,t=(t=t).current,o=t.options,t=t.element,i.current.style.display=null,i.current.style.webkitLineClamp=null,i.current.style.webkitBoxOrient=null,i.current.style.overflow=null,i.current.textContent=t.fullText,o.lines<=0||p(i.current)<=o.lines||(l={unprocessed:t.fullText,processed:""},(o.midWord?[". ",", "," ",""]:[". ",", "," "]).forEach(function(e){for(var t=0,n=l.unprocessed.split(e);t<n.length;t++){var r=n[t];if(i.current.textContent=""+l.processed+r+e+o.ellipsis,p(i.current)>o.lines){l.unprocessed=r;break}l.processed=""+l.processed+r+e}}),i.current.textContent=""+l.processed.trim()+o.ellipsis),c.prevWidth=e.current.clientWidth,c.prevHeight=e.current.clientHeight)};e.ReactSnip=function(e){var t=e.children,n=e.method,r=e.lines,i=e.midWord,e=e.ellipsis,l=c.useRef(null);u(l,{method:n,lines:r,midWord:i,ellipsis:e});var o=function(e){return 1<c.Children.count(e)||!c.isValidElement(e)?s.default.createElement("div",{ref:l},e):c.isValidElement(e.props.children)?c.cloneElement(e,{children:o(e.props.children)}):c.cloneElement(e,{ref:l})};return o(t)},Object.defineProperty(e,"__esModule",{value:!0})});