react-link-textarea
Version:
Enhancing UX by breaking the limitations of original textarea tag, supports link integration and offers flexible styling options.
16 lines (13 loc) • 4.23 kB
JavaScript
'use client';
import{jsxs as k,jsx as x}from"react/jsx-runtime";import{useMemo as O,useCallback as E,forwardRef as _,useRef as C,useEffect as b}from"react";import L from"linkify-string";function j(t,e){var c={};for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&e.indexOf(n)<0&&(c[n]=t[n]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var i=0,n=Object.getOwnPropertySymbols(t);i<n.length;i++)e.indexOf(n[i])<0&&Object.prototype.propertyIsEnumerable.call(t,n[i])&&(c[n[i]]=t[n[i]]);return c}typeof SuppressedError=="function"&&SuppressedError;function w(t,e){e===void 0&&(e={});var c=e.insertAt;if(!(typeof document>"u")){var n=document.head||document.getElementsByTagName("head")[0],i=document.createElement("style");i.type="text/css",c==="top"&&n.firstChild?n.insertBefore(i,n.firstChild):n.appendChild(i),i.styleSheet?i.styleSheet.cssText=t:i.appendChild(document.createTextNode(t))}}var N=`.link-textarea-container__mirror a:link {
color: #0000ee !important;
}
.link-textarea-container__mirror a:visited {
color: #551a8b !important;
}
.link-textarea-container__mirror a {
pointer-events: auto !important;
text-decoration: underline;
}
`;w(N);const M=t=>t.split("-").map((e,c)=>c===0?e:e.charAt(0).toUpperCase()+e.slice(1)).join(""),p=t=>t.endsWith("px")?parseInt(t.slice(0,-2),10):0,z=(t,e)=>{const c=o=>{if(!t?.current)throw new Error("Textarea ref is not defined");const a=p(o.paddingLeft)+p(o.paddingRight),u=p(o.paddingTop)+p(o.paddingBottom),{clientWidth:r,clientHeight:l}=t.current;return{width:r-a+"px",height:l-u+"px"}},n=O(()=>new ResizeObserver(()=>{if(!e.current||!t.current)return;const{width:o,height:a}=c(getComputedStyle(t.current));e.current.style.width=o,e.current.style.height=a}),[t,e,c]),i=E(o=>{if(!e?.current||!t?.current)return;const a=["border","borderLeft","borderRight","borderTop","borderBottom","boxSizing","fontFamily","fontSize","fontWeight","letterSpacing","lineHeight","padding","paddingLeft","paddingRight","paddingTop","margin","marginLeft","marginRight","marginTop","marginBottom","paddingBottom","textDecoration","textIndent","textTransform","whiteSpace","wordSpacing","wordWrap","textAlign","borderRadius"],u=getComputedStyle(t.current);a.forEach(r=>{const l=M(r);e.current.style[l]=u[l]}),e.current.style.borderColor="transparent",o?.color&&(e.current.style.color=o.color),o?.backgroundColor&&(e.current.style.backgroundColor=o.backgroundColor)},[e,t]);return{resizeObserver:n,applyStyleToMirroredRef:i,setLinkifyText:o=>{!e?.current||!t.current||(e.current.innerHTML=L(t.current.value,{target:o}))},copyTextToMirroredRef:()=>{!t?.current||!e?.current||(e.current.textContent=t.current.value)}}},B=_((t,e)=>{var{containerStyle:c={},textareaStyle:n={},containerClassName:i="",textareaClassName:m="",linkTarget:d="_blank",fontColor:o="black",caretColor:a="black"}=t,u=j(t,["containerStyle","textareaStyle","containerClassName","textareaClassName","linkTarget","fontColor","caretColor"]);const r=C(null),l=C(null),{resizeObserver:v,applyStyleToMirroredRef:S,setLinkifyText:g,copyTextToMirroredRef:T}=z(r,l);return b(()=>{T(),S(n),g(d)},[n,T]),b(()=>{if(r?.current)return v.observe(r.current),()=>{v.disconnect()}},[r,v]),b(()=>{if(!r?.current||!l?.current)return;const s=()=>{!r.current||!l.current||(l.current.scrollTop=r.current.scrollTop)},f=()=>{g(d)};return r.current.addEventListener("scroll",s),r.current.addEventListener("input",f),()=>{var h,y;(h=r.current)===null||h===void 0||h.removeEventListener("scroll",s),(y=r.current)===null||y===void 0||y.removeEventListener("input",f)}},[r,l,d,g]),k("div",{className:`link-textarea-container ${i}`,style:Object.assign(Object.assign({},c),{position:"relative"}),children:[x("textarea",Object.assign({ref:s=>{r.current=s,typeof e=="function"?e(s):e&&(e.current=s)},className:`link-textarea-container__textarea ${m}`,style:Object.assign(Object.assign({width:"100%",height:"100%",caretColor:a},n),{color:"transparent",position:"relative"})},u)),x("div",{ref:l,className:"link-textarea-container__mirror",style:{color:o,width:"100%",height:"100%",position:"absolute",top:0,left:0,right:0,userSelect:"none",overflow:"hidden",pointerEvents:"none"}})]})});export{B as default};
//# sourceMappingURL=bundle.js.map