@vrixton/pixel-pet 0.2.1 → 0.3.0

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/README.md CHANGED
@@ -115,7 +115,7 @@ Messages can be plain strings with two markers, so they fit in translation files
115
115
  />
116
116
  ```
117
117
 
118
- `{name}` becomes the pet's name in its color, and `**word**` shows that word in the color of the emotion. The markers also work in `say()`: there, `**word**` takes the color of the requested emotion, or the pet's color when there is none. In `label`, which screen readers read aloud, only `{name}` is replaced. Any emotion you leave out keeps its English message.
118
+ `{name}` becomes the pet's name in its color, `__word__` shows any word in the pet's color, and `**word**` shows that word in the color of the emotion. If your translation system already fills in `{name}` itself, wrap it as `__{name}__`, so the pet receives `__Bit__` and still paints the name. The markers also work in `say()`: there, `**word**` takes the color of the requested emotion, or the pet's color when there is none. In `label`, which screen readers read aloud, only `{name}` is replaced. Any emotion you leave out keeps its English message.
119
119
 
120
120
  Messages can also be any React node when you need more control. The highlight classes are `pixel-pet-highlight-pet`, `pixel-pet-highlight-happy`, `pixel-pet-highlight-angry`, and `pixel-pet-highlight-curious`.
121
121
 
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  'use client';
2
- "use strict";var Y=Object.defineProperty;var De=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var Ie=Object.prototype.hasOwnProperty;var Le=(i,s)=>{for(var u in s)Y(i,u,{get:s[u],enumerable:!0})},_e=(i,s,u,b)=>{if(s&&typeof s=="object"||typeof s=="function")for(let d of Ae(s))!Ie.call(i,d)&&d!==u&&Y(i,d,{get:()=>s[d],enumerable:!(b=De(s,d))||b.enumerable});return i};var Fe=i=>_e(Y({},"__esModule",{value:!0}),i);var Ye={};Le(Ye,{PixelPet:()=>Ve});module.exports=Fe(Ye);var t=require("react");var c=require("react/jsx-runtime"),re=["pointermove","pointerdown","keydown","wheel"],le="(prefers-reduced-motion: reduce)",K=4,Ne=240,ie=5e3,We=3e3,He=/(\{name\}|\*\*[^*]+\*\*)/,q={happy:"{name} is feeling **happy**!",angry:"{name} is feeling **overwhelmed**!",curious:"{name} is very **curious**"},se=65,ae=100,Oe=.04,Be=100,Ue=i=>{if(typeof window.matchMedia!="function")return()=>{};let s=window.matchMedia(le);return s.addEventListener("change",i),()=>s.removeEventListener("change",i)},$e=()=>typeof window.matchMedia=="function"&&window.matchMedia(le).matches,Xe=()=>(0,t.useSyncExternalStore)(Ue,$e,()=>!1),Ge={happy:{backgroundColor:"#1e1c06eb",borderColor:"#ffeb3b"},angry:{backgroundColor:"#210908eb",borderColor:"#F04037"},curious:{backgroundColor:"#1f341deb",borderColor:"#8BE383"}},ze={backgroundColor:"#05080ceb",borderColor:"var(--pixel-pet-color, #FDDBA0)"},Ve=({petName:i="Static",variant:s="cat",spriteSrc:u,color:b,label:d,walk:ce=!0,messages:F,dialogStyle:x={},emotionDialogStyles:pe={},onClick:ue,ref:de})=>{let[a,p]=(0,t.useState)("idle"),fe=Xe(),y=ce&&!fe,N=(0,t.useRef)(null),C=(0,t.useRef)(null),Q=(0,t.useRef)(null),[W,me]=(0,t.useState)(null),[E,S]=(0,t.useState)(null),[ge,j]=(0,t.useState)(!1),[xe,J]=(0,t.useState)(!1),[he,Z]=(0,t.useState)(!1),[be,ee]=(0,t.useState)(!1),[f,ye]=(0,t.useState)(null),R=(0,t.useRef)(ae),[H,Ee]=(0,t.useState)(0),[O,Re]=(0,t.useState)("right"),D=(e,n)=>typeof e!="string"?e:e.split(He).map((o,r)=>r%2===0?o:o==="{name}"?(0,c.jsx)("span",{className:"pixel-pet-highlight-pet",children:i},r):(0,c.jsx)("span",{className:`pixel-pet-highlight-${n??"pet"}`,children:o.slice(2,-2)},r)),Te={happy:D(F?.happy??q.happy,"happy"),angry:D(F?.angry??q.angry,"angry"),curious:D(F?.curious??q.curious,"curious")},te=(0,t.useRef)(a),A=(0,t.useRef)(null),T=(0,t.useRef)(!1),I=(0,t.useRef)(!1),l=(0,t.useRef)(null),oe=(0,t.useRef)("happy"),B=(0,t.useRef)([]),k=(0,t.useRef)(null),P=(0,t.useRef)(!1),v=(0,t.useRef)(null),U=(0,t.useRef)(ie),$=(e,n=!1)=>{a==="sleep"&&p("idle"),oe.current=e,S(e),Z(n),l.current&&clearTimeout(l.current),l.current=setTimeout(()=>{I.current||S(null)},5e3)},M=e=>{P.current=e!==null,ye(e)},L=()=>{v.current&&clearTimeout(v.current)},ne=e=>{L(),e!==1/0&&(v.current=setTimeout(()=>M(null),e))};(0,t.useImperativeHandle)(de,()=>({say:(e,n={})=>{p(o=>o==="sleep"?"idle":o),M({message:e,emotion:n.emotion??null}),U.current=n.duration??ie,ne(U.current)},hush:()=>{L(),M(null)}}),[]),(0,t.useEffect)(()=>{let e,n=()=>{p(o=>o==="sleep"?"idle":o),clearTimeout(e),e=setTimeout(()=>{S(null),M(null),p("sleep")},12e4)};return re.forEach(o=>{window.addEventListener(o,n,{passive:!0})}),n(),()=>{clearTimeout(e),re.forEach(o=>{window.removeEventListener(o,n)})}},[]),(0,t.useEffect)(()=>{te.current=a},[a]),(0,t.useEffect)(()=>{let e=setInterval(()=>{if(te.current==="sleep"||P.current)return;let n=["happy","angry","curious"],o=n[Math.floor(Math.random()*n.length)];$(o)},3e4);return()=>{clearInterval(e)}},[]),(0,t.useEffect)(()=>()=>{l.current&&clearTimeout(l.current),v.current&&clearTimeout(v.current),k.current&&clearTimeout(k.current)},[]),(0,t.useEffect)(()=>{if(!(a==="sleep"||!y)){if(a==="walk"){let e=Math.floor(Math.random()*175001)+5e3;A.current=setTimeout(()=>{p("idle"),T.current=!0,setTimeout(()=>{T.current=!1},3e4)},e)}else{let e=()=>{if(!T.current&&Math.random()>.4){p("walk");return}A.current=setTimeout(e,5e3)};e()}return()=>{A.current&&clearTimeout(A.current)}}},[a,y]);let X=e=>{R.current=e,C.current&&(C.current.style.transform=`translateX(${e}px)`)};(0,t.useEffect)(()=>{if(a!=="walk"||E!==null||f!==null||!y)return;let e=0,n=H-se;if(n<=e)return;let o=0,r=null,g=w=>{let z=r===null?0:Math.min(w-r,Be);r=w;let h=R.current+(O==="right"?1:-1)*Oe*z;if(h<=e||h>=n){if(Math.random()>.5){p("idle"),T.current=!0,setTimeout(()=>{T.current=!1},3e4);return}X(h<=e?e+2:n-2),Re(V=>V==="right"?"left":"right");return}X(h),o=requestAnimationFrame(g)};return o=requestAnimationFrame(g),()=>cancelAnimationFrame(o)},[a,E,f,O,y,H]),(0,t.useEffect)(()=>{let e=N.current;if(!e)return;let n=r=>{Ee(r),X(Math.max(Math.min(R.current,r-se),0))};if(n(e.clientWidth),typeof ResizeObserver>"u")return;let o=new ResizeObserver(([r])=>{r&&n(r.contentRect.width)});return o.observe(e),()=>o.disconnect()},[]);let ke=e=>{if(ue?.(e),e.defaultPrevented)return;let n=Date.now();a==="sleep"&&p("idle"),P.current&&(L(),M(null)),I.current=!1,ee(!0),k.current&&clearTimeout(k.current),k.current=setTimeout(()=>Z(!1),We);let o=[...B.current,n].filter(r=>n-r<=1e4);B.current=o,o.length>5?(B.current=[],$("angry",!0)):$(oe.current,!0)},Pe=()=>{j(!0),P.current&&L(),E&&(I.current=!0,l.current&&clearTimeout(l.current))},ve=()=>{j(!1),ee(!1),P.current&&ne(U.current),E&&(I.current=!1,l.current&&clearTimeout(l.current),l.current=setTimeout(()=>{S(null)},5e3))},_=f!==null&&a!=="sleep",m=a==="sleep"?null:_?f.emotion:E,G=_||m!==null&&(ge&&!be||xe||he);(0,t.useLayoutEffect)(()=>{let e=N.current,n=C.current,o=Q.current;if(!G||!e||!n||!o)return;let r=e.clientWidth,g=Math.max(Math.min(Ne,r-K*2),0),w=Math.min(o.offsetWidth,g),z=R.current+n.offsetWidth/2,h=K,V=r-K-w,Ce=z-w/2,Se=Math.max(Math.min(Ce,V),h);me({left:Se-R.current,maxWidth:g})},[G,m,f,H]);let Me=()=>m?`pixel-pet-state-${m}`:(!y||_)&&a==="walk"?"pixel-pet-state-idle":`pixel-pet-state-${a}`,we=e=>{let n=e?Ge[e]:ze,o=e&&pe[e]||{},r=o.backgroundColor||x.backgroundColor||n.backgroundColor,g=o.borderColor||x.borderColor||n.borderColor;return{backgroundColor:r,color:o.textColor||x.textColor||"#ffffff",border:`${o.borderWidth||x.borderWidth||"1px"} solid ${g}`,borderRadius:o.borderRadius||x.borderRadius||"0",fontFamily:o.fontFamily||x.fontFamily||"monospace"}};return(0,c.jsx)("div",{className:"pixel-pet",ref:N,style:b?{"--pixel-pet-color":b}:void 0,children:(0,c.jsxs)("div",{ref:C,className:"pixel-pet-container",style:{transform:`translateX(${ae}px)`},onMouseEnter:Pe,onMouseLeave:ve,children:[(0,c.jsx)("div",{className:"pixel-pet-status",role:"status",children:G&&(0,c.jsx)("div",{ref:Q,className:"pixel-pet-dialog",style:{...we(m),...W&&{left:W.left,maxWidth:W.maxWidth}},children:_?D(f.message,f.emotion):m&&Te[m]})}),(0,c.jsx)("button",{type:"button","aria-label":(d??i).split("{name}").join(i),className:`pixel-pet-sprite pixel-pet-${s} ${Me()} ${O==="left"?"pixel-pet-flip-x":""}`,style:u?{backgroundImage:`url("${u}")`}:void 0,onClick:ke,onFocus:e=>J(e.currentTarget.matches(":focus-visible")),onBlur:()=>J(!1)})]})})};0&&(module.exports={PixelPet});
2
+ "use strict";var Y=Object.defineProperty;var De=Object.getOwnPropertyDescriptor;var _e=Object.getOwnPropertyNames;var Ae=Object.prototype.hasOwnProperty;var Ie=(i,s)=>{for(var u in s)Y(i,u,{get:s[u],enumerable:!0})},Le=(i,s,u,b)=>{if(s&&typeof s=="object"||typeof s=="function")for(let d of _e(s))!Ae.call(i,d)&&d!==u&&Y(i,d,{get:()=>s[d],enumerable:!(b=De(s,d))||b.enumerable});return i};var Fe=i=>Le(Y({},"__esModule",{value:!0}),i);var Ye={};Ie(Ye,{PixelPet:()=>Ve});module.exports=Fe(Ye);var t=require("react");var c=require("react/jsx-runtime"),re=["pointermove","pointerdown","keydown","wheel"],le="(prefers-reduced-motion: reduce)",K=4,Ne=240,ie=5e3,We=3e3,He=/(\{name\}|\*\*[^*]+\*\*|__[^_]+__)/,q={happy:"{name} is feeling **happy**!",angry:"{name} is feeling **overwhelmed**!",curious:"{name} is very **curious**"},se=65,ae=100,Oe=.04,Be=100,Ue=i=>{if(typeof window.matchMedia!="function")return()=>{};let s=window.matchMedia(le);return s.addEventListener("change",i),()=>s.removeEventListener("change",i)},$e=()=>typeof window.matchMedia=="function"&&window.matchMedia(le).matches,Xe=()=>(0,t.useSyncExternalStore)(Ue,$e,()=>!1),Ge={happy:{backgroundColor:"#1e1c06eb",borderColor:"#ffeb3b"},angry:{backgroundColor:"#210908eb",borderColor:"#F04037"},curious:{backgroundColor:"#1f341deb",borderColor:"#8BE383"}},ze={backgroundColor:"#05080ceb",borderColor:"var(--pixel-pet-color, #FDDBA0)"},Ve=({petName:i="Static",variant:s="cat",spriteSrc:u,color:b,label:d,walk:ce=!0,messages:F,dialogStyle:x={},emotionDialogStyles:pe={},onClick:ue,ref:de})=>{let[a,p]=(0,t.useState)("idle"),fe=Xe(),y=ce&&!fe,N=(0,t.useRef)(null),C=(0,t.useRef)(null),Q=(0,t.useRef)(null),[W,me]=(0,t.useState)(null),[E,S]=(0,t.useState)(null),[ge,j]=(0,t.useState)(!1),[xe,J]=(0,t.useState)(!1),[he,Z]=(0,t.useState)(!1),[be,ee]=(0,t.useState)(!1),[f,ye]=(0,t.useState)(null),R=(0,t.useRef)(ae),[H,Ee]=(0,t.useState)(0),[O,Re]=(0,t.useState)("right"),D=(e,n)=>typeof e!="string"?e:e.split(He).map((o,r)=>r%2===0?o:o==="{name}"||o.startsWith("__")?(0,c.jsx)("span",{className:"pixel-pet-highlight-pet",children:o==="{name}"?i:o.slice(2,-2)},r):(0,c.jsx)("span",{className:`pixel-pet-highlight-${n??"pet"}`,children:o.slice(2,-2)},r)),Te={happy:D(F?.happy??q.happy,"happy"),angry:D(F?.angry??q.angry,"angry"),curious:D(F?.curious??q.curious,"curious")},te=(0,t.useRef)(a),_=(0,t.useRef)(null),T=(0,t.useRef)(!1),A=(0,t.useRef)(!1),l=(0,t.useRef)(null),oe=(0,t.useRef)("happy"),B=(0,t.useRef)([]),k=(0,t.useRef)(null),P=(0,t.useRef)(!1),v=(0,t.useRef)(null),U=(0,t.useRef)(ie),$=(e,n=!1)=>{a==="sleep"&&p("idle"),oe.current=e,S(e),Z(n),l.current&&clearTimeout(l.current),l.current=setTimeout(()=>{A.current||S(null)},5e3)},M=e=>{P.current=e!==null,ye(e)},I=()=>{v.current&&clearTimeout(v.current)},ne=e=>{I(),e!==1/0&&(v.current=setTimeout(()=>M(null),e))};(0,t.useImperativeHandle)(de,()=>({say:(e,n={})=>{p(o=>o==="sleep"?"idle":o),M({message:e,emotion:n.emotion??null}),U.current=n.duration??ie,ne(U.current)},hush:()=>{I(),M(null)}}),[]),(0,t.useEffect)(()=>{let e,n=()=>{p(o=>o==="sleep"?"idle":o),clearTimeout(e),e=setTimeout(()=>{S(null),M(null),p("sleep")},12e4)};return re.forEach(o=>{window.addEventListener(o,n,{passive:!0})}),n(),()=>{clearTimeout(e),re.forEach(o=>{window.removeEventListener(o,n)})}},[]),(0,t.useEffect)(()=>{te.current=a},[a]),(0,t.useEffect)(()=>{let e=setInterval(()=>{if(te.current==="sleep"||P.current)return;let n=["happy","angry","curious"],o=n[Math.floor(Math.random()*n.length)];$(o)},3e4);return()=>{clearInterval(e)}},[]),(0,t.useEffect)(()=>()=>{l.current&&clearTimeout(l.current),v.current&&clearTimeout(v.current),k.current&&clearTimeout(k.current)},[]),(0,t.useEffect)(()=>{if(!(a==="sleep"||!y)){if(a==="walk"){let e=Math.floor(Math.random()*175001)+5e3;_.current=setTimeout(()=>{p("idle"),T.current=!0,setTimeout(()=>{T.current=!1},3e4)},e)}else{let e=()=>{if(!T.current&&Math.random()>.4){p("walk");return}_.current=setTimeout(e,5e3)};e()}return()=>{_.current&&clearTimeout(_.current)}}},[a,y]);let X=e=>{R.current=e,C.current&&(C.current.style.transform=`translateX(${e}px)`)};(0,t.useEffect)(()=>{if(a!=="walk"||E!==null||f!==null||!y)return;let e=0,n=H-se;if(n<=e)return;let o=0,r=null,g=w=>{let z=r===null?0:Math.min(w-r,Be);r=w;let h=R.current+(O==="right"?1:-1)*Oe*z;if(h<=e||h>=n){if(Math.random()>.5){p("idle"),T.current=!0,setTimeout(()=>{T.current=!1},3e4);return}X(h<=e?e+2:n-2),Re(V=>V==="right"?"left":"right");return}X(h),o=requestAnimationFrame(g)};return o=requestAnimationFrame(g),()=>cancelAnimationFrame(o)},[a,E,f,O,y,H]),(0,t.useEffect)(()=>{let e=N.current;if(!e)return;let n=r=>{Ee(r),X(Math.max(Math.min(R.current,r-se),0))};if(n(e.clientWidth),typeof ResizeObserver>"u")return;let o=new ResizeObserver(([r])=>{r&&n(r.contentRect.width)});return o.observe(e),()=>o.disconnect()},[]);let ke=e=>{if(ue?.(e),e.defaultPrevented)return;let n=Date.now();a==="sleep"&&p("idle"),P.current&&(I(),M(null)),A.current=!1,ee(!0),k.current&&clearTimeout(k.current),k.current=setTimeout(()=>Z(!1),We);let o=[...B.current,n].filter(r=>n-r<=1e4);B.current=o,o.length>5?(B.current=[],$("angry",!0)):$(oe.current,!0)},Pe=()=>{j(!0),P.current&&I(),E&&(A.current=!0,l.current&&clearTimeout(l.current))},ve=()=>{j(!1),ee(!1),P.current&&ne(U.current),E&&(A.current=!1,l.current&&clearTimeout(l.current),l.current=setTimeout(()=>{S(null)},5e3))},L=f!==null&&a!=="sleep",m=a==="sleep"?null:L?f.emotion:E,G=L||m!==null&&(ge&&!be||xe||he);(0,t.useLayoutEffect)(()=>{let e=N.current,n=C.current,o=Q.current;if(!G||!e||!n||!o)return;let r=e.clientWidth,g=Math.max(Math.min(Ne,r-K*2),0),w=Math.min(o.offsetWidth,g),z=R.current+n.offsetWidth/2,h=K,V=r-K-w,Ce=z-w/2,Se=Math.max(Math.min(Ce,V),h);me({left:Se-R.current,maxWidth:g})},[G,m,f,H]);let Me=()=>m?`pixel-pet-state-${m}`:(!y||L)&&a==="walk"?"pixel-pet-state-idle":`pixel-pet-state-${a}`,we=e=>{let n=e?Ge[e]:ze,o=e&&pe[e]||{},r=o.backgroundColor||x.backgroundColor||n.backgroundColor,g=o.borderColor||x.borderColor||n.borderColor;return{backgroundColor:r,color:o.textColor||x.textColor||"#ffffff",border:`${o.borderWidth||x.borderWidth||"1px"} solid ${g}`,borderRadius:o.borderRadius||x.borderRadius||"0",fontFamily:o.fontFamily||x.fontFamily||"monospace"}};return(0,c.jsx)("div",{className:"pixel-pet",ref:N,style:b?{"--pixel-pet-color":b}:void 0,children:(0,c.jsxs)("div",{ref:C,className:"pixel-pet-container",style:{transform:`translateX(${ae}px)`},onMouseEnter:Pe,onMouseLeave:ve,children:[(0,c.jsx)("div",{className:"pixel-pet-status",role:"status",children:G&&(0,c.jsx)("div",{ref:Q,className:"pixel-pet-dialog",style:{...we(m),...W&&{left:W.left,maxWidth:W.maxWidth}},children:L?D(f.message,f.emotion):m&&Te[m]})}),(0,c.jsx)("button",{type:"button","aria-label":(d??i).split("{name}").join(i),className:`pixel-pet-sprite pixel-pet-${s} ${Me()} ${O==="left"?"pixel-pet-flip-x":""}`,style:u?{backgroundImage:`url("${u}")`}:void 0,onClick:ke,onFocus:e=>J(e.currentTarget.matches(":focus-visible")),onBlur:()=>J(!1)})]})})};0&&(module.exports={PixelPet});
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
1
  'use client';
2
- import{useState as a,useEffect as d,useImperativeHandle as Ae,useLayoutEffect as Ie,useRef as r,useSyncExternalStore as Le}from"react";import{jsx as x,jsxs as Ge}from"react/jsx-runtime";var re=["pointermove","pointerdown","keydown","wheel"],le="(prefers-reduced-motion: reduce)",V=4,_e=240,ie=5e3,Fe=3e3,Ne=/(\{name\}|\*\*[^*]+\*\*)/,Y={happy:"{name} is feeling **happy**!",angry:"{name} is feeling **overwhelmed**!",curious:"{name} is very **curious**"},se=65,ae=100,We=.04,He=100,Oe=f=>{if(typeof window.matchMedia!="function")return()=>{};let M=window.matchMedia(le);return M.addEventListener("change",f),()=>M.removeEventListener("change",f)},Be=()=>typeof window.matchMedia=="function"&&window.matchMedia(le).matches,Ue=()=>Le(Oe,Be,()=>!1),$e={happy:{backgroundColor:"#1e1c06eb",borderColor:"#ffeb3b"},angry:{backgroundColor:"#210908eb",borderColor:"#F04037"},curious:{backgroundColor:"#1f341deb",borderColor:"#8BE383"}},Xe={backgroundColor:"#05080ceb",borderColor:"var(--pixel-pet-color, #FDDBA0)"},je=({petName:f="Static",variant:M="cat",spriteSrc:K,color:q,label:ce,walk:pe=!0,messages:_,dialogStyle:m={},emotionDialogStyles:ue={},onClick:de,ref:fe})=>{let[i,l]=a("idle"),me=Ue(),h=pe&&!me,F=r(null),w=r(null),Q=r(null),[N,ge]=a(null),[b,C]=a(null),[xe,j]=a(!1),[he,J]=a(!1),[be,Z]=a(!1),[ye,ee]=a(!1),[c,Ee]=a(null),y=r(ae),[W,Re]=a(0),[H,Te]=a("right"),S=(e,o)=>typeof e!="string"?e:e.split(Ne).map((t,n)=>n%2===0?t:t==="{name}"?x("span",{className:"pixel-pet-highlight-pet",children:f},n):x("span",{className:`pixel-pet-highlight-${o??"pet"}`,children:t.slice(2,-2)},n)),ke={happy:S(_?.happy??Y.happy,"happy"),angry:S(_?.angry??Y.angry,"angry"),curious:S(_?.curious??Y.curious,"curious")},te=r(i),D=r(null),E=r(!1),A=r(!1),s=r(null),oe=r("happy"),O=r([]),R=r(null),T=r(!1),k=r(null),B=r(ie),U=(e,o=!1)=>{i==="sleep"&&l("idle"),oe.current=e,C(e),Z(o),s.current&&clearTimeout(s.current),s.current=setTimeout(()=>{A.current||C(null)},5e3)},P=e=>{T.current=e!==null,Ee(e)},I=()=>{k.current&&clearTimeout(k.current)},ne=e=>{I(),e!==1/0&&(k.current=setTimeout(()=>P(null),e))};Ae(fe,()=>({say:(e,o={})=>{l(t=>t==="sleep"?"idle":t),P({message:e,emotion:o.emotion??null}),B.current=o.duration??ie,ne(B.current)},hush:()=>{I(),P(null)}}),[]),d(()=>{let e,o=()=>{l(t=>t==="sleep"?"idle":t),clearTimeout(e),e=setTimeout(()=>{C(null),P(null),l("sleep")},12e4)};return re.forEach(t=>{window.addEventListener(t,o,{passive:!0})}),o(),()=>{clearTimeout(e),re.forEach(t=>{window.removeEventListener(t,o)})}},[]),d(()=>{te.current=i},[i]),d(()=>{let e=setInterval(()=>{if(te.current==="sleep"||T.current)return;let o=["happy","angry","curious"],t=o[Math.floor(Math.random()*o.length)];U(t)},3e4);return()=>{clearInterval(e)}},[]),d(()=>()=>{s.current&&clearTimeout(s.current),k.current&&clearTimeout(k.current),R.current&&clearTimeout(R.current)},[]),d(()=>{if(!(i==="sleep"||!h)){if(i==="walk"){let e=Math.floor(Math.random()*175001)+5e3;D.current=setTimeout(()=>{l("idle"),E.current=!0,setTimeout(()=>{E.current=!1},3e4)},e)}else{let e=()=>{if(!E.current&&Math.random()>.4){l("walk");return}D.current=setTimeout(e,5e3)};e()}return()=>{D.current&&clearTimeout(D.current)}}},[i,h]);let $=e=>{y.current=e,w.current&&(w.current.style.transform=`translateX(${e}px)`)};d(()=>{if(i!=="walk"||b!==null||c!==null||!h)return;let e=0,o=W-se;if(o<=e)return;let t=0,n=null,u=v=>{let G=n===null?0:Math.min(v-n,He);n=v;let g=y.current+(H==="right"?1:-1)*We*G;if(g<=e||g>=o){if(Math.random()>.5){l("idle"),E.current=!0,setTimeout(()=>{E.current=!1},3e4);return}$(g<=e?e+2:o-2),Te(z=>z==="right"?"left":"right");return}$(g),t=requestAnimationFrame(u)};return t=requestAnimationFrame(u),()=>cancelAnimationFrame(t)},[i,b,c,H,h,W]),d(()=>{let e=F.current;if(!e)return;let o=n=>{Re(n),$(Math.max(Math.min(y.current,n-se),0))};if(o(e.clientWidth),typeof ResizeObserver>"u")return;let t=new ResizeObserver(([n])=>{n&&o(n.contentRect.width)});return t.observe(e),()=>t.disconnect()},[]);let Pe=e=>{if(de?.(e),e.defaultPrevented)return;let o=Date.now();i==="sleep"&&l("idle"),T.current&&(I(),P(null)),A.current=!1,ee(!0),R.current&&clearTimeout(R.current),R.current=setTimeout(()=>Z(!1),Fe);let t=[...O.current,o].filter(n=>o-n<=1e4);O.current=t,t.length>5?(O.current=[],U("angry",!0)):U(oe.current,!0)},ve=()=>{j(!0),T.current&&I(),b&&(A.current=!0,s.current&&clearTimeout(s.current))},Me=()=>{j(!1),ee(!1),T.current&&ne(B.current),b&&(A.current=!1,s.current&&clearTimeout(s.current),s.current=setTimeout(()=>{C(null)},5e3))},L=c!==null&&i!=="sleep",p=i==="sleep"?null:L?c.emotion:b,X=L||p!==null&&(xe&&!ye||he||be);Ie(()=>{let e=F.current,o=w.current,t=Q.current;if(!X||!e||!o||!t)return;let n=e.clientWidth,u=Math.max(Math.min(_e,n-V*2),0),v=Math.min(t.offsetWidth,u),G=y.current+o.offsetWidth/2,g=V,z=n-V-v,Se=G-v/2,De=Math.max(Math.min(Se,z),g);ge({left:De-y.current,maxWidth:u})},[X,p,c,W]);let we=()=>p?`pixel-pet-state-${p}`:(!h||L)&&i==="walk"?"pixel-pet-state-idle":`pixel-pet-state-${i}`,Ce=e=>{let o=e?$e[e]:Xe,t=e&&ue[e]||{},n=t.backgroundColor||m.backgroundColor||o.backgroundColor,u=t.borderColor||m.borderColor||o.borderColor;return{backgroundColor:n,color:t.textColor||m.textColor||"#ffffff",border:`${t.borderWidth||m.borderWidth||"1px"} solid ${u}`,borderRadius:t.borderRadius||m.borderRadius||"0",fontFamily:t.fontFamily||m.fontFamily||"monospace"}};return x("div",{className:"pixel-pet",ref:F,style:q?{"--pixel-pet-color":q}:void 0,children:Ge("div",{ref:w,className:"pixel-pet-container",style:{transform:`translateX(${ae}px)`},onMouseEnter:ve,onMouseLeave:Me,children:[x("div",{className:"pixel-pet-status",role:"status",children:X&&x("div",{ref:Q,className:"pixel-pet-dialog",style:{...Ce(p),...N&&{left:N.left,maxWidth:N.maxWidth}},children:L?S(c.message,c.emotion):p&&ke[p]})}),x("button",{type:"button","aria-label":(ce??f).split("{name}").join(f),className:`pixel-pet-sprite pixel-pet-${M} ${we()} ${H==="left"?"pixel-pet-flip-x":""}`,style:K?{backgroundImage:`url("${K}")`}:void 0,onClick:Pe,onFocus:e=>J(e.currentTarget.matches(":focus-visible")),onBlur:()=>J(!1)})]})})};export{je as PixelPet};
2
+ import{useState as a,useEffect as d,useImperativeHandle as _e,useLayoutEffect as Ae,useRef as r,useSyncExternalStore as Ie}from"react";import{jsx as x,jsxs as Ge}from"react/jsx-runtime";var re=["pointermove","pointerdown","keydown","wheel"],le="(prefers-reduced-motion: reduce)",V=4,Le=240,ie=5e3,Fe=3e3,Ne=/(\{name\}|\*\*[^*]+\*\*|__[^_]+__)/,Y={happy:"{name} is feeling **happy**!",angry:"{name} is feeling **overwhelmed**!",curious:"{name} is very **curious**"},se=65,ae=100,We=.04,He=100,Oe=f=>{if(typeof window.matchMedia!="function")return()=>{};let M=window.matchMedia(le);return M.addEventListener("change",f),()=>M.removeEventListener("change",f)},Be=()=>typeof window.matchMedia=="function"&&window.matchMedia(le).matches,Ue=()=>Ie(Oe,Be,()=>!1),$e={happy:{backgroundColor:"#1e1c06eb",borderColor:"#ffeb3b"},angry:{backgroundColor:"#210908eb",borderColor:"#F04037"},curious:{backgroundColor:"#1f341deb",borderColor:"#8BE383"}},Xe={backgroundColor:"#05080ceb",borderColor:"var(--pixel-pet-color, #FDDBA0)"},je=({petName:f="Static",variant:M="cat",spriteSrc:K,color:q,label:ce,walk:pe=!0,messages:L,dialogStyle:m={},emotionDialogStyles:ue={},onClick:de,ref:fe})=>{let[i,l]=a("idle"),me=Ue(),h=pe&&!me,F=r(null),w=r(null),Q=r(null),[N,ge]=a(null),[b,C]=a(null),[xe,j]=a(!1),[he,J]=a(!1),[be,Z]=a(!1),[ye,ee]=a(!1),[c,Ee]=a(null),y=r(ae),[W,Re]=a(0),[H,Te]=a("right"),S=(e,o)=>typeof e!="string"?e:e.split(Ne).map((t,n)=>n%2===0?t:t==="{name}"||t.startsWith("__")?x("span",{className:"pixel-pet-highlight-pet",children:t==="{name}"?f:t.slice(2,-2)},n):x("span",{className:`pixel-pet-highlight-${o??"pet"}`,children:t.slice(2,-2)},n)),ke={happy:S(L?.happy??Y.happy,"happy"),angry:S(L?.angry??Y.angry,"angry"),curious:S(L?.curious??Y.curious,"curious")},te=r(i),D=r(null),E=r(!1),_=r(!1),s=r(null),oe=r("happy"),O=r([]),R=r(null),T=r(!1),k=r(null),B=r(ie),U=(e,o=!1)=>{i==="sleep"&&l("idle"),oe.current=e,C(e),Z(o),s.current&&clearTimeout(s.current),s.current=setTimeout(()=>{_.current||C(null)},5e3)},P=e=>{T.current=e!==null,Ee(e)},A=()=>{k.current&&clearTimeout(k.current)},ne=e=>{A(),e!==1/0&&(k.current=setTimeout(()=>P(null),e))};_e(fe,()=>({say:(e,o={})=>{l(t=>t==="sleep"?"idle":t),P({message:e,emotion:o.emotion??null}),B.current=o.duration??ie,ne(B.current)},hush:()=>{A(),P(null)}}),[]),d(()=>{let e,o=()=>{l(t=>t==="sleep"?"idle":t),clearTimeout(e),e=setTimeout(()=>{C(null),P(null),l("sleep")},12e4)};return re.forEach(t=>{window.addEventListener(t,o,{passive:!0})}),o(),()=>{clearTimeout(e),re.forEach(t=>{window.removeEventListener(t,o)})}},[]),d(()=>{te.current=i},[i]),d(()=>{let e=setInterval(()=>{if(te.current==="sleep"||T.current)return;let o=["happy","angry","curious"],t=o[Math.floor(Math.random()*o.length)];U(t)},3e4);return()=>{clearInterval(e)}},[]),d(()=>()=>{s.current&&clearTimeout(s.current),k.current&&clearTimeout(k.current),R.current&&clearTimeout(R.current)},[]),d(()=>{if(!(i==="sleep"||!h)){if(i==="walk"){let e=Math.floor(Math.random()*175001)+5e3;D.current=setTimeout(()=>{l("idle"),E.current=!0,setTimeout(()=>{E.current=!1},3e4)},e)}else{let e=()=>{if(!E.current&&Math.random()>.4){l("walk");return}D.current=setTimeout(e,5e3)};e()}return()=>{D.current&&clearTimeout(D.current)}}},[i,h]);let $=e=>{y.current=e,w.current&&(w.current.style.transform=`translateX(${e}px)`)};d(()=>{if(i!=="walk"||b!==null||c!==null||!h)return;let e=0,o=W-se;if(o<=e)return;let t=0,n=null,u=v=>{let G=n===null?0:Math.min(v-n,He);n=v;let g=y.current+(H==="right"?1:-1)*We*G;if(g<=e||g>=o){if(Math.random()>.5){l("idle"),E.current=!0,setTimeout(()=>{E.current=!1},3e4);return}$(g<=e?e+2:o-2),Te(z=>z==="right"?"left":"right");return}$(g),t=requestAnimationFrame(u)};return t=requestAnimationFrame(u),()=>cancelAnimationFrame(t)},[i,b,c,H,h,W]),d(()=>{let e=F.current;if(!e)return;let o=n=>{Re(n),$(Math.max(Math.min(y.current,n-se),0))};if(o(e.clientWidth),typeof ResizeObserver>"u")return;let t=new ResizeObserver(([n])=>{n&&o(n.contentRect.width)});return t.observe(e),()=>t.disconnect()},[]);let Pe=e=>{if(de?.(e),e.defaultPrevented)return;let o=Date.now();i==="sleep"&&l("idle"),T.current&&(A(),P(null)),_.current=!1,ee(!0),R.current&&clearTimeout(R.current),R.current=setTimeout(()=>Z(!1),Fe);let t=[...O.current,o].filter(n=>o-n<=1e4);O.current=t,t.length>5?(O.current=[],U("angry",!0)):U(oe.current,!0)},ve=()=>{j(!0),T.current&&A(),b&&(_.current=!0,s.current&&clearTimeout(s.current))},Me=()=>{j(!1),ee(!1),T.current&&ne(B.current),b&&(_.current=!1,s.current&&clearTimeout(s.current),s.current=setTimeout(()=>{C(null)},5e3))},I=c!==null&&i!=="sleep",p=i==="sleep"?null:I?c.emotion:b,X=I||p!==null&&(xe&&!ye||he||be);Ae(()=>{let e=F.current,o=w.current,t=Q.current;if(!X||!e||!o||!t)return;let n=e.clientWidth,u=Math.max(Math.min(Le,n-V*2),0),v=Math.min(t.offsetWidth,u),G=y.current+o.offsetWidth/2,g=V,z=n-V-v,Se=G-v/2,De=Math.max(Math.min(Se,z),g);ge({left:De-y.current,maxWidth:u})},[X,p,c,W]);let we=()=>p?`pixel-pet-state-${p}`:(!h||I)&&i==="walk"?"pixel-pet-state-idle":`pixel-pet-state-${i}`,Ce=e=>{let o=e?$e[e]:Xe,t=e&&ue[e]||{},n=t.backgroundColor||m.backgroundColor||o.backgroundColor,u=t.borderColor||m.borderColor||o.borderColor;return{backgroundColor:n,color:t.textColor||m.textColor||"#ffffff",border:`${t.borderWidth||m.borderWidth||"1px"} solid ${u}`,borderRadius:t.borderRadius||m.borderRadius||"0",fontFamily:t.fontFamily||m.fontFamily||"monospace"}};return x("div",{className:"pixel-pet",ref:F,style:q?{"--pixel-pet-color":q}:void 0,children:Ge("div",{ref:w,className:"pixel-pet-container",style:{transform:`translateX(${ae}px)`},onMouseEnter:ve,onMouseLeave:Me,children:[x("div",{className:"pixel-pet-status",role:"status",children:X&&x("div",{ref:Q,className:"pixel-pet-dialog",style:{...Ce(p),...N&&{left:N.left,maxWidth:N.maxWidth}},children:I?S(c.message,c.emotion):p&&ke[p]})}),x("button",{type:"button","aria-label":(ce??f).split("{name}").join(f),className:`pixel-pet-sprite pixel-pet-${M} ${we()} ${H==="left"?"pixel-pet-flip-x":""}`,style:K?{backgroundImage:`url("${K}")`}:void 0,onClick:Pe,onFocus:e=>J(e.currentTarget.matches(":focus-visible")),onBlur:()=>J(!1)})]})})};export{je as PixelPet};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vrixton/pixel-pet",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "A pixel art pet for React that walks, sleeps, reacts to clicks, and speaks on demand.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",