UNPKG

react-magical-typewriter

Version:

A customizable typewriter effect component for React with GSAP animations

23 lines (22 loc) 16.1 kB
(function(x,R){typeof exports=="object"&&typeof module<"u"?R(exports,require("react"),require("gsap")):typeof define=="function"&&define.amd?define(["exports","react","gsap"],R):(x=typeof globalThis<"u"?globalThis:x||self,R(x.ReactMagicalTypewriter={},x.React,x.gsap))})(this,function(x,R,c){"use strict";var D={exports:{}},X={};/** * @license React * react-jsx-runtime.production.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */var ee;function ne(){if(ee)return X;ee=1;var m=Symbol.for("react.transitional.element"),C=Symbol.for("react.fragment");function _(O,b,r){var p=null;if(r!==void 0&&(p=""+r),b.key!==void 0&&(p=""+b.key),"key"in b){r={};for(var j in b)j!=="key"&&(r[j]=b[j])}else r=b;return b=r.ref,{$$typeof:m,type:O,key:p,ref:b!==void 0?b:null,props:r}}return X.Fragment=C,X.jsx=_,X.jsxs=_,X}var $={};/** * @license React * react-jsx-runtime.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */var te;function se(){return te||(te=1,process.env.NODE_ENV!=="production"&&function(){function m(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===t?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case N:return"Fragment";case v:return"Profiler";case U:return"StrictMode";case J:return"Suspense";case q:return"SuspenseList";case a:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case B:return"Portal";case V:return(e.displayName||"Context")+".Provider";case I:return(e._context.displayName||"Context")+".Consumer";case M:var s=e.render;return e=e.displayName,e||(e=s.displayName||s.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case H:return s=e.displayName||null,s!==null?s:m(e.type)||"Memo";case G:s=e._payload,e=e._init;try{return m(e(s))}catch{}}return null}function C(e){return""+e}function _(e){try{C(e);var s=!1}catch{s=!0}if(s){s=console;var l=s.error,w=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return l.call(s,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",w),C(e)}}function O(e){if(e===N)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===G)return"<...>";try{var s=m(e);return s?"<"+s+">":"<...>"}catch{return"<...>"}}function b(){var e=g.A;return e===null?null:e.getOwner()}function r(){return Error("react-stack-top-frame")}function p(e){if(k.call(e,"key")){var s=Object.getOwnPropertyDescriptor(e,"key").get;if(s&&s.isReactWarning)return!1}return e.key!==void 0}function j(e,s){function l(){o||(o=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",s))}l.isReactWarning=!0,Object.defineProperty(e,"key",{get:l,configurable:!0})}function S(){var e=m(this.type);return i[e]||(i[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function W(e,s,l,w,P,T,Z,Q){return l=T.ref,e={$$typeof:A,type:e,key:s,props:T,_owner:P},(l!==void 0?l:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:S}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:Z}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:Q}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function z(e,s,l,w,P,T,Z,Q){var y=s.children;if(y!==void 0)if(w)if(u(y)){for(w=0;w<y.length;w++)E(y[w]);Object.freeze&&Object.freeze(y)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else E(y);if(k.call(s,"key")){y=m(e);var F=Object.keys(s).filter(function(ie){return ie!=="key"});w=0<F.length?"{key: someKey, "+F.join(": ..., ")+": ...}":"{key: someKey}",h[y+w]||(F=0<F.length?"{"+F.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX: let props = %s; <%s {...props} /> React keys must be passed directly to JSX without using spread: let props = %s; <%s key={someKey} {...props} />`,w,y,F,y),h[y+w]=!0)}if(y=null,l!==void 0&&(_(l),y=""+l),p(s)&&(_(s.key),y=""+s.key),"key"in s){l={};for(var K in s)K!=="key"&&(l[K]=s[K])}else l=s;return y&&j(l,typeof e=="function"?e.displayName||e.name||"Unknown":e),W(e,y,T,P,b(),l,Z,Q)}function E(e){typeof e=="object"&&e!==null&&e.$$typeof===A&&e._store&&(e._store.validated=1)}var Y=R,A=Symbol.for("react.transitional.element"),B=Symbol.for("react.portal"),N=Symbol.for("react.fragment"),U=Symbol.for("react.strict_mode"),v=Symbol.for("react.profiler"),I=Symbol.for("react.consumer"),V=Symbol.for("react.context"),M=Symbol.for("react.forward_ref"),J=Symbol.for("react.suspense"),q=Symbol.for("react.suspense_list"),H=Symbol.for("react.memo"),G=Symbol.for("react.lazy"),a=Symbol.for("react.activity"),t=Symbol.for("react.client.reference"),g=Y.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,k=Object.prototype.hasOwnProperty,u=Array.isArray,n=console.createTask?console.createTask:function(){return null};Y={"react-stack-bottom-frame":function(e){return e()}};var o,i={},d=Y["react-stack-bottom-frame"].bind(Y,r)(),f=n(O(r)),h={};$.Fragment=N,$.jsx=function(e,s,l,w,P){var T=1e4>g.recentlyCreatedOwnerStacks++;return z(e,s,l,!1,w,P,T?Error("react-stack-top-frame"):d,T?n(O(e)):f)},$.jsxs=function(e,s,l,w,P){var T=1e4>g.recentlyCreatedOwnerStacks++;return z(e,s,l,!0,w,P,T?Error("react-stack-top-frame"):d,T?n(O(e)):f)}}()),$}var re;function ae(){return re||(re=1,process.env.NODE_ENV==="production"?D.exports=ne():D.exports=se()),D.exports}var L=ae();const oe=({text:m,typingSpeed:C=500,delayAfterTyping:_=1500,cursorCharacter:O="|",cursorBlinkSpeed:b=500,charAnimationSpeed:r=.7,animationStyle:p="Elegant",ghostTrailColor:j="rgba(100, 149, 237, 0.7)",cursorInvert:S="none",onComplete:W=()=>{},className:z=""})=>{const[E,Y]=R.useState([]),[A,B]=R.useState(!0),[N,U]=R.useState(!1),v=R.useRef(null),I=R.useRef([]),V=R.useMemo(()=>m.split(/(\s+)/).filter(Boolean),[m]);let M=0;const J=a=>{a.querySelectorAll(".ray").forEach(u=>u.remove());const g=[],k=16;for(let u=0;u<k;u++){const n=document.createElement("div");n.className="ray",a.appendChild(n),g.push(n)}return g},q=(a,t,g)=>{document.querySelectorAll(`.ghost-char-${g}`).forEach(d=>d.remove());const u=[];if(!v.current)return u;const n=5,o=a.getBoundingClientRect(),i=v.current.getBoundingClientRect();for(let d=0;d<n;d++){const f=document.createElement("span");f.textContent=t===" "?" ":t,f.className=`react-magical-typewriter-ghost ghost-char-${g}`,v.current.appendChild(f),c.gsap.set(f,{position:"absolute",top:`${o.top-i.top}px`,left:`${o.left-i.left}px`,width:`${o.width}px`,height:`${o.height}px`,fontSize:window.getComputedStyle(a).fontSize,fontFamily:window.getComputedStyle(a).fontFamily,fontWeight:window.getComputedStyle(a).fontWeight,lineHeight:window.getComputedStyle(a).lineHeight,color:j,opacity:.7-d*.15,zIndex:1,pointerEvents:"none"}),u.push(f)}return u},H=(a,t,g)=>{document.querySelectorAll(`.fragment-char-${g}`).forEach(f=>f.remove());const u=[];if(!v.current)return u;const n=6+Math.floor(Math.random()*3),o=a.getBoundingClientRect(),i=v.current.getBoundingClientRect(),d=()=>{const f=3+Math.floor(Math.random()*3);let h="polygon(";for(let e=0;e<f;e++)h+=`${Math.random()*100}% ${Math.random()*100}%`,e<f-1&&(h+=", ");return h+=")",h};for(let f=0;f<n;f++){const h=document.createElement("span");h.textContent=t===" "?" ":t,h.className=`react-magical-typewriter-fragment fragment-char-${g}`,v.current.appendChild(h);const e=(Math.random()-.5)*(o.width*2),s=(Math.random()-.5)*(o.height*2),l=(Math.random()-.5)*360;c.gsap.set(h,{position:"absolute",top:`${o.top-i.top+s}px`,left:`${o.left-i.left+e}px`,width:`${o.width*(.4+Math.random()*.4)}px`,height:`${o.height*(.4+Math.random()*.4)}px`,fontSize:window.getComputedStyle(a).fontSize,fontFamily:window.getComputedStyle(a).fontFamily,fontWeight:window.getComputedStyle(a).fontWeight,lineHeight:window.getComputedStyle(a).lineHeight,color:window.getComputedStyle(a).color,opacity:0,rotation:l,scale:.3+Math.random()*.4,clipPath:d(),overflow:"hidden",pointerEvents:"none"}),u.push(h)}return u};R.useEffect(()=>{let a;return E.length<m.length&&(a=setTimeout(()=>{Y(t=>[...t,{char:m[t.length],id:`${t.length}-${Date.now()}`}])},C)),()=>clearTimeout(a)},[E,m,C]),R.useEffect(()=>{if(E.length===m.length&&!N){U(!0);const a=setTimeout(()=>W(),_);return()=>clearTimeout(a)}},[E,m,N,_,W]),R.useEffect(()=>{const a=setInterval(()=>B(t=>!t),b);return()=>clearInterval(a)},[b]);const G=(a,t)=>{a&&(I.current[t]=a)};return R.useEffect(()=>{var u;const a=E.length-1;if(a<0||!I.current[a])return;const t=I.current[a],g=E[a];c.gsap.killTweensOf(t);const k=typeof p=="object"&&!Array.isArray(p);if(k)c.gsap.set(t,{display:"inline-block"}),p.from||c.gsap.set(t,{opacity:0});else{const n=p,o=n==="Elegant"||n==="LiquidDrip"?0:1;c.gsap.set(t,{display:"inline-block",opacity:o,x:0,y:0,scale:1,rotation:0,skewX:0,skewY:0,clipPath:"none",filter:"none",transformOrigin:"center center"})}if(k){const n=p;n.from&&n.to?c.gsap.fromTo(t,{...n.from},{...n.to,duration:n.duration||r,ease:n.ease||"power2.out"}):n.to&&c.gsap.to(t,{...n.to,duration:n.duration||r,ease:n.ease||"power2.out"})}else{const n=p;if(n==="Elegant")c.gsap.to(t,{opacity:1,duration:r,ease:"power2.out"});else if(n==="Whimsical"){const i=[{x:-10,y:-10},{x:10,y:-10},{x:10,y:10},{x:-10,y:10}][a%4];c.gsap.fromTo(t,{opacity:0,x:i.x,y:i.y,rotation:a%20-10},{opacity:1,x:0,y:0,rotation:0,duration:r,ease:"back.out(1.7)"})}else if(n==="Landing")c.gsap.fromTo(t,{y:"-200%",rotation:-3},{y:"0%",rotation:0,duration:r,ease:"elastic.out(1, 0.7)"});else if(n==="Arise")c.gsap.fromTo(t,{y:"200%",rotation:3},{y:"0%",rotation:0,duration:r,ease:"power4.out"});else if(n==="Rift")c.gsap.fromTo(t,{scale:0,rotation:720},{scale:1,rotation:0,duration:r,ease:"elastic.out(1, 0.6)"});else if(n==="Warp")c.gsap.fromTo(t,{scaleX:3,scaleY:.1,x:"50%",opacity:0},{scale:1,x:"0%",opacity:1,duration:r,ease:"elastic.out(1.1, 0.7)"});else if(n==="RadialBurst"){const o=J(t);c.gsap.set(t,{scale:.5,opacity:0,transformOrigin:"center center"}),c.gsap.set(o,{position:"absolute",width:"3px",height:"1px",backgroundColor:"rgba(255, 223, 0, 0.9)",top:"50%",left:"50%",yPercent:-100,transformOrigin:"bottom center",scale:0,opacity:0,zIndex:-1});const i=c.gsap.timeline();o.forEach((d,f)=>{const h=f/o.length*360,e=20+Math.random()*15;i.to(d,{rotation:h,height:`${e}px`,scale:1,opacity:.4,duration:r*.5,ease:"power3.out"},0)}),i.to(t,{scale:1,opacity:1,duration:r*.7,ease:"elastic.out(1.2, 0.5)"},r*.1),i.to(o,{opacity:0,scale:0,duration:r*.6,ease:"power2.in",onComplete:()=>o.forEach(d=>d.remove())},`-=${r*.2}`)}else if(n==="LiquidDrip")c.gsap.set(t,{opacity:0,scaleY:.2,y:"-100%",transformOrigin:"center bottom"}),c.gsap.timeline().to(t,{y:"-15%",opacity:1,scaleY:1.3,duration:r*.4,ease:"power2.in"}).to(t,{y:"5%",scaleY:.85,scaleX:1.15,duration:r*.25,ease:"power1.out"}).to(t,{y:"0%",scaleY:1,scaleX:1,duration:r*.35,ease:"elastic.out(1, 0.5)"});else if(n==="LaserSketch"){c.gsap.set(t,{opacity:1,display:"inline-block",verticalAlign:"middle"});const o=c.gsap.timeline();o.to(t,{clipPath:"polygon(0% 0%, 100% 0%, 0% 0%, 0% 100%)",duration:r*.1,ease:"power1.inOut"}),o.to(t,{clipPath:"polygon(0 0%, 100% 0%, 100% 100%, 0% 100%)",duration:r*.7,ease:"power1.inOut"}),o.to(t,{opacity:.5,duration:r*.9,ease:"power2.in"}),o.to(t,{opacity:1,duration:r*.9,ease:"power2.out"})}else if(n==="FlipReveal")t.parentElement&&c.gsap.set(t.parentElement,{perspective:800}),c.gsap.set(t,{opacity:0,rotationY:-90,transformOrigin:"center center"}),c.gsap.timeline().to(t,{rotationY:0,opacity:1,duration:r*.8,ease:"back.out(1.5)"}).to(t,{rotationY:15,duration:r*.2,ease:"power1.inOut"}).to(t,{rotationY:0,duration:r*.3,ease:"elastic.out(1, 0.7)"});else if(n==="PixelGlitch")c.gsap.set(t,{opacity:1,filter:"blur(6px) contrast(0.1) brightness(3)",skewX:"8deg",scale:1.1}),c.gsap.timeline().to(t,{filter:"blur(3px) contrast(2) brightness(0.8)",skewX:"-6deg",x:5,duration:r*.25,ease:"steps(4)"}).to(t,{filter:"blur(1px) contrast(0.5) brightness(1.5)",skewX:"4deg",x:-3,duration:r*.2,ease:"steps(3)"}).to(t,{filter:"blur(0px) contrast(1) brightness(1)",skewX:"0deg",x:0,scale:1,duration:r*.3,ease:"power2.out"});else if(n==="GhostTrail"){c.gsap.fromTo(t,{opacity:0,x:-10},{opacity:1,x:0,duration:r*.4,ease:"power2.out"});const o=q(t,g.char,a);o.length>0&&c.gsap.to(o,{x:i=>`-=${10+i*4}`,y:i=>`+=${4+i*2}`,opacity:0,duration:r*1.8,stagger:.08,ease:"power1.out",onComplete:()=>{o.forEach(i=>i.remove())}})}else if(n==="ShatterIn"){const o=H(t,g.char,a);if(c.gsap.set(t,{opacity:0}),o.length>0){const i=t.getBoundingClientRect(),d=((u=v.current)==null?void 0:u.getBoundingClientRect())||{top:0,left:0};c.gsap.to(o,{top:i.top-d.top,left:i.left-d.left,width:i.width,height:i.height,rotation:0,scale:1,opacity:.7,clipPath:"polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)",duration:r,stagger:{amount:r*.3,from:"random"},ease:"quad.out",onComplete:()=>{c.gsap.set(t,{opacity:1}),o.forEach(f=>f.remove())}})}else c.gsap.set(t,{opacity:1})}else if(n==="OrigamiReveal"){const o=[{origin:"bottom center",scaleProp:"scaleY",skewSign:1},{origin:"top center",scaleProp:"scaleY",skewSign:-1},{origin:"center left",scaleProp:"scaleX",skewSign:1},{origin:"center right",scaleProp:"scaleX",skewSign:-1},{origin:"top left",scaleProp:"scaleY",skewSign:-1},{origin:"top left",scaleProp:"scaleX",skewSign:1},{origin:"top right",scaleProp:"scaleY",skewSign:-1},{origin:"top right",scaleProp:"scaleX",skewSign:-1},{origin:"bottom left",scaleProp:"scaleY",skewSign:1},{origin:"bottom left",scaleProp:"scaleX",skewSign:1},{origin:"bottom right",scaleProp:"scaleY",skewSign:1},{origin:"bottom right",scaleProp:"scaleX",skewSign:-1}],i=o[Math.floor(Math.random()*o.length)],d=i.skewSign*35,f=i.skewSign*-15,h=i.skewSign*5,e={opacity:1,transformOrigin:i.origin,skewX:`${d}deg`,[i.scaleProp]:0};c.gsap.set(t,e);const s=c.gsap.timeline(),l={skewX:`${f}deg`,duration:r*.5,ease:"power3.out",[i.scaleProp]:1};s.to(t,l).to(t,{skewX:`${h}deg`,duration:r*.25,ease:"power1.inOut"}).to(t,{skewX:"0deg",duration:r*.25,ease:"elastic.out(1, 0.6)"})}}},[E,p,r,m.length]),L.jsxs("span",{ref:v,className:`react-magical-typewriter-container ${p==="Arise"||p==="Landing"||p==="PixelGlitch"||p==="LiquidDrip"?"clip-path-overflow":""} ${z}`,children:[V.map((a,t)=>{const g=[],k=M;for(let u=0;u<a.length&&M<E.length;u++)g.push(E[M]),M++;return g.length===0?null:L.jsx("span",{className:"typewriter-word-or-space-segment",children:g.map((u,n)=>{const o=k+n;return L.jsx("span",{ref:i=>G(i,o),className:`react-magical-typewriter-char ${typeof p=="string"&&["RadialBurst","LaserSketch","ShatterIn"].includes(p)?`char-${p.toLowerCase()}`:""} ${p==="GhostTrail"?"char-ghosttrail-active":""}`,children:u.char===" "?" ":u.char},u.id)})},`segment-${t}`)}),L.jsx("span",{className:`react-magical-typewriter-cursor ${S==="horizontal"?"cursor-invert-horizontal":S==="vertical"?"cursor-invert-vertical":S==="both"?"cursor-invert-both":S==="none"?"":S}`,style:{opacity:A?1:0},children:O})]})};x.ReactMagicalTypewriter=oe,x.default=oe,Object.defineProperties(x,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});