@vrixton/pixel-pet 0.1.0 → 0.2.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 +5 -2
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,7 +62,9 @@ The message shows right away, without hovering, and screen readers announce it.
|
|
|
62
62
|
| Option | Type | Default | Description |
|
|
63
63
|
| --- | --- | --- | --- |
|
|
64
64
|
| `emotion` | `'happy' \| 'angry' \| 'curious'` | none | Plays that emotion's animation and colors the bubble to match. Without it, the bubble is neutral. |
|
|
65
|
-
| `duration` | `number` | `5000` | How long the message stays, in milliseconds. |
|
|
65
|
+
| `duration` | `number` | `5000` | How long the message stays, in milliseconds. Pass `Infinity` to keep it until a new message replaces it, the user taps the pet, or the pet falls asleep. |
|
|
66
|
+
|
|
67
|
+
Call `pet.current?.hush()` to close the current message right away, for example when the user dismisses it.
|
|
66
68
|
|
|
67
69
|
## Props
|
|
68
70
|
|
|
@@ -77,7 +79,8 @@ The message shows right away, without hovering, and screen readers announce it.
|
|
|
77
79
|
| `messages` | `PetMessages` | English messages | Replaces the text shown for each emotion. |
|
|
78
80
|
| `dialogStyle` | `DialogStyleProps` | none | Styles for every bubble. |
|
|
79
81
|
| `emotionDialogStyles` | `Partial<Record<PetEmotion, DialogStyleProps>>` | none | Styles for the bubble of a single emotion. |
|
|
80
|
-
| `
|
|
82
|
+
| `onClick` | `(event) => void` | none | Called when the user clicks or taps the pet. Call `event.preventDefault()` inside it to skip the pet's own reaction. |
|
|
83
|
+
| `ref` | `Ref<PixelPetHandle>` | none | Gives you the `say()` and `hush()` methods. |
|
|
81
84
|
|
|
82
85
|
## Reusing a configuration
|
|
83
86
|
|
package/dist/index.d.mts
CHANGED
|
@@ -18,6 +18,7 @@ interface PetSayOptions {
|
|
|
18
18
|
}
|
|
19
19
|
interface PixelPetHandle {
|
|
20
20
|
say: (message: React.ReactNode, options?: PetSayOptions) => void;
|
|
21
|
+
hush: () => void;
|
|
21
22
|
}
|
|
22
23
|
interface PixelPetProps {
|
|
23
24
|
petName?: string;
|
|
@@ -29,6 +30,7 @@ interface PixelPetProps {
|
|
|
29
30
|
messages?: PetMessages;
|
|
30
31
|
dialogStyle?: DialogStyleProps;
|
|
31
32
|
emotionDialogStyles?: Partial<Record<PetEmotion, DialogStyleProps>>;
|
|
33
|
+
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
32
34
|
ref?: React.Ref<PixelPetHandle>;
|
|
33
35
|
}
|
|
34
36
|
declare const PixelPet: React.FC<PixelPetProps>;
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ interface PetSayOptions {
|
|
|
18
18
|
}
|
|
19
19
|
interface PixelPetHandle {
|
|
20
20
|
say: (message: React.ReactNode, options?: PetSayOptions) => void;
|
|
21
|
+
hush: () => void;
|
|
21
22
|
}
|
|
22
23
|
interface PixelPetProps {
|
|
23
24
|
petName?: string;
|
|
@@ -29,6 +30,7 @@ interface PixelPetProps {
|
|
|
29
30
|
messages?: PetMessages;
|
|
30
31
|
dialogStyle?: DialogStyleProps;
|
|
31
32
|
emotionDialogStyles?: Partial<Record<PetEmotion, DialogStyleProps>>;
|
|
33
|
+
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
32
34
|
ref?: React.Ref<PixelPetHandle>;
|
|
33
35
|
}
|
|
34
36
|
declare const PixelPet: React.FC<PixelPetProps>;
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
"use strict";var G=Object.defineProperty;var
|
|
2
|
+
"use strict";var G=Object.defineProperty;var ve=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames;var Me=Object.prototype.hasOwnProperty;var Ce=(s,a)=>{for(var u in a)G(s,u,{get:a[u],enumerable:!0})},Se=(s,a,u,b)=>{if(a&&typeof a=="object"||typeof a=="function")for(let d of we(a))!Me.call(s,d)&&d!==u&&G(s,d,{get:()=>a[d],enumerable:!(b=ve(a,d))||b.enumerable});return s};var De=s=>Se(G({},"__esModule",{value:!0}),s);var $e={};Ce($e,{PixelPet:()=>Oe});module.exports=De($e);var t=require("react");var r=require("react/jsx-runtime"),Z=["pointermove","pointerdown","keydown","wheel"],ne="(prefers-reduced-motion: reduce)",V=4,Ie=240,ee=5e3,te=65,oe=100,Ae=.04,Le=100,Ne=s=>{if(typeof window.matchMedia!="function")return()=>{};let a=window.matchMedia(ne);return a.addEventListener("change",s),()=>a.removeEventListener("change",s)},Fe=()=>typeof window.matchMedia=="function"&&window.matchMedia(ne).matches,We=()=>(0,t.useSyncExternalStore)(Ne,Fe,()=>!1),_e={happy:{backgroundColor:"#1e1c063d",borderColor:"#ffeb3b"},angry:{backgroundColor:"#21090833",borderColor:"#F04037"},curious:{backgroundColor:"#1f341d3a",borderColor:"#8BE383"}},He={backgroundColor:"#05080cd9",borderColor:"var(--pixel-pet-color, #FDDBA0)"},Oe=({petName:s="Static",variant:a="cat",spriteSrc:u,color:b,label:d,walk:re=!0,messages:A,dialogStyle:g={},emotionDialogStyles:ie={},onClick:se,ref:ae})=>{let[l,c]=(0,t.useState)("idle"),le=We(),y=re&&!le,L=(0,t.useRef)(null),M=(0,t.useRef)(null),Y=(0,t.useRef)(null),[N,pe]=(0,t.useState)(null),[E,C]=(0,t.useState)(null),[ce,q]=(0,t.useState)(!1),[ue,Q]=(0,t.useState)(!1),[de,fe]=(0,t.useState)(!1),[x,me]=(0,t.useState)(null),k=(0,t.useRef)(oe),[F,ge]=(0,t.useState)(0),[W,xe]=(0,t.useState)("right"),he={happy:A?.happy??(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("span",{className:"pixel-pet-highlight-pet",children:s})," is feeling"," ",(0,r.jsx)("span",{className:"pixel-pet-highlight-happy",children:"happy"}),"!"]}),angry:A?.angry??(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("span",{className:"pixel-pet-highlight-pet",children:s})," is feeling"," ",(0,r.jsx)("span",{className:"pixel-pet-highlight-angry",children:"overwhelmed"}),"!"]}),curious:A?.curious??(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("span",{className:"pixel-pet-highlight-pet",children:s})," is very"," ",(0,r.jsx)("span",{className:"pixel-pet-highlight-curious",children:"curious"})]})},K=(0,t.useRef)(l),S=(0,t.useRef)(null),P=(0,t.useRef)(!1),_=(0,t.useRef)(!1),p=(0,t.useRef)(null),j=(0,t.useRef)("happy"),H=(0,t.useRef)([]),T=(0,t.useRef)(!1),R=(0,t.useRef)(null),O=(0,t.useRef)(ee),$=(e,n=!1)=>{l==="sleep"&&c("idle"),j.current=e,C(e),fe(n),p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{_.current||C(null)},5e3)},v=e=>{T.current=e!==null,me(e)},D=()=>{R.current&&clearTimeout(R.current)},J=e=>{D(),e!==1/0&&(R.current=setTimeout(()=>v(null),e))};(0,t.useImperativeHandle)(ae,()=>({say:(e,n={})=>{c(o=>o==="sleep"?"idle":o),v({message:e,emotion:n.emotion??null}),O.current=n.duration??ee,J(O.current)},hush:()=>{D(),v(null)}}),[]),(0,t.useEffect)(()=>{let e,n=()=>{c(o=>o==="sleep"?"idle":o),clearTimeout(e),e=setTimeout(()=>{C(null),v(null),c("sleep")},12e4)};return Z.forEach(o=>{window.addEventListener(o,n,{passive:!0})}),n(),()=>{clearTimeout(e),Z.forEach(o=>{window.removeEventListener(o,n)})}},[]),(0,t.useEffect)(()=>{K.current=l},[l]),(0,t.useEffect)(()=>{let e=setInterval(()=>{if(K.current==="sleep"||T.current)return;let n=["happy","angry","curious"],o=n[Math.floor(Math.random()*n.length)];$(o)},3e4);return()=>{clearInterval(e)}},[]),(0,t.useEffect)(()=>()=>{p.current&&clearTimeout(p.current),R.current&&clearTimeout(R.current)},[]),(0,t.useEffect)(()=>{if(!(l==="sleep"||!y)){if(l==="walk"){let e=Math.floor(Math.random()*175001)+5e3;S.current=setTimeout(()=>{c("idle"),P.current=!0,setTimeout(()=>{P.current=!1},3e4)},e)}else{let e=()=>{if(!P.current&&Math.random()>.4){c("walk");return}S.current=setTimeout(e,5e3)};e()}return()=>{S.current&&clearTimeout(S.current)}}},[l,y]);let B=e=>{k.current=e,M.current&&(M.current.style.transform=`translateX(${e}px)`)};(0,t.useEffect)(()=>{if(l!=="walk"||E!==null||x!==null||!y)return;let e=0,n=F-te;if(n<=e)return;let o=0,i=null,m=w=>{let X=i===null?0:Math.min(w-i,Le);i=w;let h=k.current+(W==="right"?1:-1)*Ae*X;if(h<=e||h>=n){if(Math.random()>.5){c("idle"),P.current=!0,setTimeout(()=>{P.current=!1},3e4);return}B(h<=e?e+2:n-2),xe(z=>z==="right"?"left":"right");return}B(h),o=requestAnimationFrame(m)};return o=requestAnimationFrame(m),()=>cancelAnimationFrame(o)},[l,E,x,W,y,F]),(0,t.useEffect)(()=>{let e=L.current;if(!e)return;let n=i=>{ge(i),B(Math.max(Math.min(k.current,i-te),0))};if(n(e.clientWidth),typeof ResizeObserver>"u")return;let o=new ResizeObserver(([i])=>{i&&n(i.contentRect.width)});return o.observe(e),()=>o.disconnect()},[]);let be=e=>{if(se?.(e),e.defaultPrevented)return;let n=Date.now();l==="sleep"&&c("idle"),T.current&&(D(),v(null));let o=[...H.current,n].filter(i=>n-i<=1e4);H.current=o,o.length>5?(H.current=[],$("angry",!0)):$(j.current,!0)},ye=()=>{q(!0),T.current&&D(),E&&(_.current=!0,p.current&&clearTimeout(p.current))},Ee=()=>{q(!1),T.current&&J(O.current),E&&(_.current=!1,p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{C(null)},5e3))},I=x!==null&&l!=="sleep",f=l==="sleep"?null:I?x.emotion:E,U=I||f!==null&&(ce||ue||de);(0,t.useLayoutEffect)(()=>{let e=L.current,n=M.current,o=Y.current;if(!U||!e||!n||!o)return;let i=e.clientWidth,m=Math.max(Math.min(Ie,i-V*2),0),w=Math.min(o.offsetWidth,m),X=k.current+n.offsetWidth/2,h=V,z=i-V-w,Te=X-w/2,Re=Math.max(Math.min(Te,z),h);pe({left:Re-k.current,maxWidth:m})},[U,f,x,F]);let ke=()=>f?`pixel-pet-state-${f}`:(!y||I)&&l==="walk"?"pixel-pet-state-idle":`pixel-pet-state-${l}`,Pe=e=>{let n=e?_e[e]:He,o=e&&ie[e]||{},i=o.backgroundColor||g.backgroundColor||n.backgroundColor,m=o.borderColor||g.borderColor||n.borderColor;return{backgroundColor:i,color:o.textColor||g.textColor||"#ffffff",border:`${o.borderWidth||g.borderWidth||"1px"} solid ${m}`,borderRadius:o.borderRadius||g.borderRadius||"5px",fontFamily:o.fontFamily||g.fontFamily||"monospace"}};return(0,r.jsx)("div",{className:"pixel-pet",ref:L,style:b?{"--pixel-pet-color":b}:void 0,children:(0,r.jsxs)("div",{ref:M,className:"pixel-pet-container",style:{transform:`translateX(${oe}px)`},onMouseEnter:ye,onMouseLeave:Ee,children:[(0,r.jsx)("div",{className:"pixel-pet-status",role:"status",children:U&&(0,r.jsx)("div",{ref:Y,className:"pixel-pet-dialog",style:{...Pe(f),...N&&{left:N.left,maxWidth:N.maxWidth}},children:I?x.message:f&&he[f]})}),(0,r.jsx)("button",{type:"button","aria-label":d??s,className:`pixel-pet-sprite pixel-pet-${a} ${ke()} ${W==="left"?"pixel-pet-flip-x":""}`,style:u?{backgroundImage:`url("${u}")`}:void 0,onClick:be,onFocus:()=>Q(!0),onBlur:()=>Q(!1)})]})})};0&&(module.exports={PixelPet});
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import{useState as l,useEffect as f,useImperativeHandle as Ce,useLayoutEffect as
|
|
2
|
+
import{useState as l,useEffect as f,useImperativeHandle as Ce,useLayoutEffect as Se,useRef as i,useSyncExternalStore as De}from"react";import{Fragment as V,jsx as a,jsxs as I}from"react/jsx-runtime";var te=["pointermove","pointerdown","keydown","wheel"],ie="(prefers-reduced-motion: reduce)",G=4,Ie=240,oe=5e3,ne=65,re=100,Ae=.04,Le=100,Ne=c=>{if(typeof window.matchMedia!="function")return()=>{};let v=window.matchMedia(ie);return v.addEventListener("change",c),()=>v.removeEventListener("change",c)},Fe=()=>typeof window.matchMedia=="function"&&window.matchMedia(ie).matches,We=()=>De(Ne,Fe,()=>!1),_e={happy:{backgroundColor:"#1e1c063d",borderColor:"#ffeb3b"},angry:{backgroundColor:"#21090833",borderColor:"#F04037"},curious:{backgroundColor:"#1f341d3a",borderColor:"#8BE383"}},He={backgroundColor:"#05080cd9",borderColor:"var(--pixel-pet-color, #FDDBA0)"},Ge=({petName:c="Static",variant:v="cat",spriteSrc:Y,color:q,label:se,walk:ae=!0,messages:A,dialogStyle:m={},emotionDialogStyles:le={},onClick:pe,ref:ce})=>{let[r,p]=l("idle"),ue=We(),h=ae&&!ue,L=i(null),w=i(null),Q=i(null),[N,de]=l(null),[b,M]=l(null),[fe,K]=l(!1),[me,j]=l(!1),[ge,xe]=l(!1),[g,he]=l(null),y=i(re),[F,be]=l(0),[W,ye]=l("right"),Ee={happy:A?.happy??I(V,{children:[a("span",{className:"pixel-pet-highlight-pet",children:c})," is feeling"," ",a("span",{className:"pixel-pet-highlight-happy",children:"happy"}),"!"]}),angry:A?.angry??I(V,{children:[a("span",{className:"pixel-pet-highlight-pet",children:c})," is feeling"," ",a("span",{className:"pixel-pet-highlight-angry",children:"overwhelmed"}),"!"]}),curious:A?.curious??I(V,{children:[a("span",{className:"pixel-pet-highlight-pet",children:c})," is very"," ",a("span",{className:"pixel-pet-highlight-curious",children:"curious"})]})},J=i(r),C=i(null),E=i(!1),_=i(!1),s=i(null),Z=i("happy"),H=i([]),k=i(!1),P=i(null),O=i(oe),$=(e,o=!1)=>{r==="sleep"&&p("idle"),Z.current=e,M(e),xe(o),s.current&&clearTimeout(s.current),s.current=setTimeout(()=>{_.current||M(null)},5e3)},T=e=>{k.current=e!==null,he(e)},S=()=>{P.current&&clearTimeout(P.current)},ee=e=>{S(),e!==1/0&&(P.current=setTimeout(()=>T(null),e))};Ce(ce,()=>({say:(e,o={})=>{p(t=>t==="sleep"?"idle":t),T({message:e,emotion:o.emotion??null}),O.current=o.duration??oe,ee(O.current)},hush:()=>{S(),T(null)}}),[]),f(()=>{let e,o=()=>{p(t=>t==="sleep"?"idle":t),clearTimeout(e),e=setTimeout(()=>{M(null),T(null),p("sleep")},12e4)};return te.forEach(t=>{window.addEventListener(t,o,{passive:!0})}),o(),()=>{clearTimeout(e),te.forEach(t=>{window.removeEventListener(t,o)})}},[]),f(()=>{J.current=r},[r]),f(()=>{let e=setInterval(()=>{if(J.current==="sleep"||k.current)return;let o=["happy","angry","curious"],t=o[Math.floor(Math.random()*o.length)];$(t)},3e4);return()=>{clearInterval(e)}},[]),f(()=>()=>{s.current&&clearTimeout(s.current),P.current&&clearTimeout(P.current)},[]),f(()=>{if(!(r==="sleep"||!h)){if(r==="walk"){let e=Math.floor(Math.random()*175001)+5e3;C.current=setTimeout(()=>{p("idle"),E.current=!0,setTimeout(()=>{E.current=!1},3e4)},e)}else{let e=()=>{if(!E.current&&Math.random()>.4){p("walk");return}C.current=setTimeout(e,5e3)};e()}return()=>{C.current&&clearTimeout(C.current)}}},[r,h]);let B=e=>{y.current=e,w.current&&(w.current.style.transform=`translateX(${e}px)`)};f(()=>{if(r!=="walk"||b!==null||g!==null||!h)return;let e=0,o=F-ne;if(o<=e)return;let t=0,n=null,d=R=>{let X=n===null?0:Math.min(R-n,Le);n=R;let x=y.current+(W==="right"?1:-1)*Ae*X;if(x<=e||x>=o){if(Math.random()>.5){p("idle"),E.current=!0,setTimeout(()=>{E.current=!1},3e4);return}B(x<=e?e+2:o-2),ye(z=>z==="right"?"left":"right");return}B(x),t=requestAnimationFrame(d)};return t=requestAnimationFrame(d),()=>cancelAnimationFrame(t)},[r,b,g,W,h,F]),f(()=>{let e=L.current;if(!e)return;let o=n=>{be(n),B(Math.max(Math.min(y.current,n-ne),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 ke=e=>{if(pe?.(e),e.defaultPrevented)return;let o=Date.now();r==="sleep"&&p("idle"),k.current&&(S(),T(null));let t=[...H.current,o].filter(n=>o-n<=1e4);H.current=t,t.length>5?(H.current=[],$("angry",!0)):$(Z.current,!0)},Pe=()=>{K(!0),k.current&&S(),b&&(_.current=!0,s.current&&clearTimeout(s.current))},Te=()=>{K(!1),k.current&&ee(O.current),b&&(_.current=!1,s.current&&clearTimeout(s.current),s.current=setTimeout(()=>{M(null)},5e3))},D=g!==null&&r!=="sleep",u=r==="sleep"?null:D?g.emotion:b,U=D||u!==null&&(fe||me||ge);Se(()=>{let e=L.current,o=w.current,t=Q.current;if(!U||!e||!o||!t)return;let n=e.clientWidth,d=Math.max(Math.min(Ie,n-G*2),0),R=Math.min(t.offsetWidth,d),X=y.current+o.offsetWidth/2,x=G,z=n-G-R,we=X-R/2,Me=Math.max(Math.min(we,z),x);de({left:Me-y.current,maxWidth:d})},[U,u,g,F]);let Re=()=>u?`pixel-pet-state-${u}`:(!h||D)&&r==="walk"?"pixel-pet-state-idle":`pixel-pet-state-${r}`,ve=e=>{let o=e?_e[e]:He,t=e&&le[e]||{},n=t.backgroundColor||m.backgroundColor||o.backgroundColor,d=t.borderColor||m.borderColor||o.borderColor;return{backgroundColor:n,color:t.textColor||m.textColor||"#ffffff",border:`${t.borderWidth||m.borderWidth||"1px"} solid ${d}`,borderRadius:t.borderRadius||m.borderRadius||"5px",fontFamily:t.fontFamily||m.fontFamily||"monospace"}};return a("div",{className:"pixel-pet",ref:L,style:q?{"--pixel-pet-color":q}:void 0,children:I("div",{ref:w,className:"pixel-pet-container",style:{transform:`translateX(${re}px)`},onMouseEnter:Pe,onMouseLeave:Te,children:[a("div",{className:"pixel-pet-status",role:"status",children:U&&a("div",{ref:Q,className:"pixel-pet-dialog",style:{...ve(u),...N&&{left:N.left,maxWidth:N.maxWidth}},children:D?g.message:u&&Ee[u]})}),a("button",{type:"button","aria-label":se??c,className:`pixel-pet-sprite pixel-pet-${v} ${Re()} ${W==="left"?"pixel-pet-flip-x":""}`,style:Y?{backgroundImage:`url("${Y}")`}:void 0,onClick:ke,onFocus:()=>j(!0),onBlur:()=>j(!1)})]})})};export{Ge as PixelPet};
|
package/package.json
CHANGED