@supermousejs/labs 2.1.1 → 2.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/dist/index.umd.js CHANGED
@@ -1 +1,9 @@
1
- (function(C,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("@supermousejs/utils"),require("@supermousejs/zoetrope")):typeof define=="function"&&define.amd?define(["exports","@supermousejs/utils","@supermousejs/zoetrope"],e):(C=typeof globalThis<"u"?globalThis:C||self,e(C.SupermouseLabs={},C.SupermouseUtils,C.SupermouseZoetrope))})(this,(function(C,e,P){"use strict";function N(t,a){const c=t.tagName.toLowerCase();if(c==="input"||c==="textarea"||t.isContentEditable){const i=t.type;if(["button","submit","checkbox","radio","range","color"].includes(i)){if(a.pointer)return"pointer"}else if(a.text)return"text"}else if((c==="a"||c==="button"||t.closest("a")||t.closest("button"))&&a.pointer)return"pointer";return null}const k=t=>{let a,c=t.defaultState||"default",i=t.defaultState||"default",f=null,w=null,p=!1,S,g=0,z=0;const R=e.normalize(t.size,24),o=e.normalize(t.followStrategy,"smooth"),x=e.normalize(t.anchor,"center"),v=e.normalize(t.rotateWithVelocity,!1),h=t.useSemanticTags??!0,l=t.transitionDuration??200,n=t.offset?t.offset[0]:0,T=t.offset?t.offset[1]:0;return e.definePlugin({name:t.name||"smart-icon",selector:"[data-supermouse-icon]",create:()=>{const s=e.dom.createActor("div");return s.style.zIndex=e.Layers.CURSOR,a=e.dom.createActor("div"),e.dom.applyStyles(a,{width:"100%",height:"100%",display:"flex",alignItems:"center",justifyContent:"center",transformOrigin:"center center",transform:"scale(1)",transition:`transform ${l/2}ms cubic-bezier(0.16, 1, 0.3, 1)`}),a.innerHTML=t.icons[c]||"",s.appendChild(a),s},styles:{color:"color"},update:(s,y)=>{const r=t.icons,u=s.state.hoverTarget;let d=t.defaultState||"default";if(u){u!==f&&(f=u,w=h?N(u,r):null);const M=s.state.interaction?.icon;M&&r[M]?d=M:w&&(d=w)}else f=null,w=null;d!==c&&!p&&(r[d]||d===(t.defaultState||"default"))&&(i=d,p=!0,clearTimeout(S),a.style.transform="scale(0)",S=setTimeout(()=>{c=i,a.innerHTML=r[c]||"",a.style.transform="scale(1)",S=setTimeout(()=>{p=!1},l/2)},l/2));const b=R(s.state);e.dom.setStyle(y,"width",`${b}px`),e.dom.setStyle(y,"height",`${b}px`);let m=0,A=0;const L=b/2,$=x(s.state);$!=="center"&&($.includes("left")&&(m=L),$.includes("right")&&(m=-L),$.includes("top")&&(A=L),$.includes("bottom")&&(A=-L));const I=c==="pointer"||c==="text";if(v(s.state)&&!I&&!s.state.reducedMotion){const{x:M,y:O}=s.state.velocity;e.math.dist(M,O)>1&&(z=e.math.angle(M,O)),g=e.math.lerpAngle(g,z,.15)}else g=e.math.lerpAngle(g,0,.15);const E=o(s.state)==="raw"?s.state.pointer:s.state.smooth;e.dom.setTransform(y,E.x+n+m,E.y+T+A,g)},cleanup(){clearTimeout(S)}},t)},W=(t={})=>{const a=e.normalize(t.size,20),c=e.normalize(t.hoverSize,40),i=e.normalize(t.color,"#ffffff"),f=e.normalize(t.borderWidth,2),w=e.normalize(t.fill,"transparent");let p=20,S=20,g=0,z=1,R=1;return e.definePlugin({name:t.name||"smart-ring",selector:"[data-supermouse-color]",create:o=>{const x=e.dom.createCircle(a(o.state),w(o.state));return e.dom.applyStyles(x,{zIndex:e.Layers.FOLLOWER,mixBlendMode:t.mixBlendMode||"difference",transition:"opacity 0.2s ease, border-radius 0.2s ease",borderStyle:"solid"}),x},update:(o,x)=>{const v=a(o.state),h=o.state.shape;let l=v,n=v,T="50%",s=i(o.state);h?(l=h.width,n=h.height,T=`${h.borderRadius}px`):(o.state.isHover&&(l=c(o.state),n=c(o.state)),o.state.isDown&&(l*=.9,n*=.9)),o.state.interaction.color&&(s=o.state.interaction.color),p=e.math.lerp(p,l,.2),S=e.math.lerp(S,n,.2),e.dom.setStyle(x,"width",`${p}px`),e.dom.setStyle(x,"height",`${S}px`),e.dom.setStyle(x,"borderRadius",T),e.dom.setStyle(x,"borderColor",s),e.dom.setStyle(x,"backgroundColor",w(o.state)),e.dom.setStyle(x,"borderWidth",`${f(o.state)}px`);let y=0,r=1,u=1;if(!h&&t.enableSkew&&!o.state.reducedMotion){const{velocity:m}=o.state,A=e.effects.getVelocityDistortion(m.x,m.y);y=A.rotation,r=A.scaleX,u=A.scaleY,g=e.math.lerpAngle(g,y,.15)}else g=0;z=e.math.lerp(z,r,.15),R=e.math.lerp(R,u,.15);const{x:d,y:b}=o.state.smooth;e.dom.setTransform(x,d,b,g,z,R)}},t)},F=(t={})=>{const a=t.count||30,c=t.decay||.05,i=t.frequency||10,f=t.scatter||5,p=e.normalize(t.color,"#ff00ff"),S=[];let g=0,z=0,R=!1,o=0;const x=(v,h,l)=>{const n=S.find(r=>!r.isActive);if(!n)return;n.isActive=!0,n.life=1,n.x=v+e.math.random(-f,f),n.y=h+e.math.random(-f,f);const T=e.math.random(0,Math.PI*2),s=e.math.random(.5,1.5);n.vx=Math.cos(T)*s,n.vy=Math.sin(T)*s,n.scale=e.math.random(.5,1.2),n.color=l;const y=e.math.random(2,5);e.dom.setStyle(n.el,"width",`${y}px`),e.dom.setStyle(n.el,"height",`${y}px`),e.dom.setStyle(n.el,"backgroundColor",l),e.dom.setStyle(n.el,"opacity","1"),e.dom.setTransform(n.el,n.x,n.y,0,n.scale,n.scale)};return e.definePlugin({name:t.name||"sparkles",install(v){for(let h=0;h<a;h++){const l=e.dom.createCircle(0,"transparent");e.dom.applyStyles(l,{zIndex:e.Layers.TRACE,opacity:"0",willChange:"transform, opacity",transition:"none"}),v.container.appendChild(l),S.push({el:l,isActive:!1,x:0,y:0,vx:0,vy:0,life:0,scale:1,color:""})}},update(v){const{x:h,y:l}=v.state.pointer;R||(g=h,z=l,R=!0);const n=h-g,T=l-z,s=Math.hypot(n,T);if(o+=s,o>i){const y=p(v.state),r=Math.floor(o/i);for(let u=0;u<r;u++){const d=u/r,b=g+n*d,m=z+T*d;x(b,m,y)}o=o%i}g=h,z=l;for(let y=0;y<a;y++){const r=S[y];if(r.isActive)if(r.x+=r.vx,r.y+=r.vy,r.life-=c,r.life<=0)r.isActive=!1,r.el.style.opacity="0";else{r.el.style.opacity=String(r.life);const u=r.scale*r.life;e.dom.setTransform(r.el,r.x,r.y,0,u,u)}}},destroy(){S.forEach(v=>v.el.remove()),S.length=0}},t)};let H=0;const U=(t={})=>{let a,c,i,f,w;const p=`supermouse-text-ring-path-${H++}`,S="SUPERMOUSE • SUPERMOUSE • ",g=60,z=12,R=.5,o=t.className||"",x=t.spread??!1,v=e.normalize(t.text,S),h=e.normalize(t.radius,g),l=e.normalize(t.fontSize,z),n=e.normalize(t.speed,R),T=e.normalize(t.opacity,1);let s=0,y="",r=0,u=0;return e.definePlugin({name:"text-ring",selector:"[data-supermouse-text-ring]",create:d=>{const b=e.dom.createActor("div");e.dom.applyStyles(b,{zIndex:e.Layers.FOLLOWER,transition:"opacity 0.2s ease",opacity:"1",width:"0px",height:"0px",overflow:"visible",display:"flex",alignItems:"center",justifyContent:"center"}),o&&b.classList.add(...o.split(" ").filter(Boolean)),a=document.createElementNS("http://www.w3.org/2000/svg","svg"),a.style.overflow="visible",a.style.position="absolute",a.style.left="0",a.style.top="0",c=document.createElementNS("http://www.w3.org/2000/svg","path"),c.setAttribute("id",p),c.setAttribute("fill","none"),f=document.createElementNS("http://www.w3.org/2000/svg","text");const m=l(d.state);return f.setAttribute("font-size",`${m}px`),u=m,f.setAttribute("fill","currentColor"),f.style.textTransform="uppercase",f.style.letterSpacing="2px",i=document.createElementNS("http://www.w3.org/2000/svg","textPath"),i.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",`#${p}`),i.setAttribute("href",`#${p}`),i.setAttribute("startOffset","0%"),w=document.createTextNode(""),i.appendChild(w),f.appendChild(i),a.appendChild(c),a.appendChild(f),b.appendChild(a),b},styles:{color:"color"},update:(d,b)=>{let m=v(d.state);const A=h(d.state),L=l(d.state),$=n(d.state),I=T(d.state);e.dom.setStyle(b,"opacity",String(I));const E=d.state.interaction;if(E.textRing&&typeof E.textRing=="string"?m=E.textRing:E.text&&typeof E.text=="string"&&(m=E.text),A!==r&&(c.setAttribute("d",P.getCirclePath(A)),r=A),x){const j=P.getCircumference(A);i.setAttribute("textLength",String(j)),i.setAttribute("lengthAdjust","spacing"),m=P.formatLoopText(m,!0)}else i.removeAttribute("textLength"),i.removeAttribute("lengthAdjust");L!==u&&(f.setAttribute("font-size",`${L}px`),u=L),m!==y&&(w.textContent=m,y=m),s+=$;const{x:M,y:O}=d.state.smooth;e.dom.setTransform(b,M,O,s)}},t)};C.SmartIcon=k,C.SmartRing=W,C.Sparkles=F,C.TextRing=U,Object.defineProperty(C,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(C,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("@supermousejs/utils"),require("@supermousejs/zoetrope")):typeof define=="function"&&define.amd?define(["exports","@supermousejs/utils","@supermousejs/zoetrope"],e):(C=typeof globalThis<"u"?globalThis:C||self,e(C.SupermouseLabs={},C.SupermouseUtils,C.SupermouseZoetrope))})(this,(function(C,e,P){"use strict";function k(t,a){const c=t.tagName.toLowerCase();if(c==="input"||c==="textarea"||t.isContentEditable){const i=t.type;if(["button","submit","checkbox","radio","range","color"].includes(i)){if(a.pointer)return"pointer"}else if(a.text)return"text"}else if((c==="a"||c==="button"||t.closest("a")||t.closest("button"))&&a.pointer)return"pointer";return null}const N=t=>{let a,c=t.defaultState||"default",i=t.defaultState||"default",f=null,w=null,b=!1,S,g=0,z=0;const R=e.normalize(t.size,24),o=e.normalize(t.followStrategy,"smooth"),x=e.normalize(t.anchor,"center"),p=e.normalize(t.rotateWithVelocity,!1),y=t.useSemanticTags??!0,l=t.transitionDuration??200,n=t.offset?t.offset[0]:0,T=t.offset?t.offset[1]:0;return e.definePlugin({name:t.name||"smart-icon",selector:"[data-supermouse-icon]",create:()=>{const s=e.dom.createActor("div");return s.style.zIndex=e.Layers.CURSOR,a=e.dom.createActor("div"),e.dom.applyStyles(a,{width:"100%",height:"100%",display:"flex",alignItems:"center",justifyContent:"center",transformOrigin:"center center",transform:"scale(1)",transition:`transform ${l/2}ms cubic-bezier(0.16, 1, 0.3, 1)`}),a.innerHTML=t.icons[c]||"",e.dom.injectStyles("supermouse-smart-icon-styles",`
2
+ @keyframes sm {
3
+ 0% { transform: rotate(0deg); }
4
+ 100% { transform: rotate(360deg); }
5
+ }
6
+ .supermouse-spin {
7
+ animation: sm 1s linear infinite;
8
+ }
9
+ `),s.appendChild(a),s},styles:{color:"color"},update:(s,h)=>{const r=t.icons,u=s.state.hoverTarget;let d=t.defaultState||"default";if(u){u!==f&&(f=u,w=y?k(u,r):null);const M=s.state.interaction?.icon;M&&r[M]?d=M:w&&(d=w)}else f=null,w=null;d!==c&&!b&&(r[d]||d===(t.defaultState||"default"))&&(i=d,b=!0,clearTimeout(S),a.style.transform="scale(0)",S=setTimeout(()=>{c=i,a.innerHTML=r[c]||"",a.style.transform="scale(1)",S=setTimeout(()=>{b=!1},l/2)},l/2));const v=R(s.state);e.dom.setStyle(h,"width",`${v}px`),e.dom.setStyle(h,"height",`${v}px`);let m=0,A=0;const L=v/2,$=x(s.state);$!=="center"&&($.includes("left")&&(m=L),$.includes("right")&&(m=-L),$.includes("top")&&(A=L),$.includes("bottom")&&(A=-L));const j=c==="pointer"||c==="text";if(p(s.state)&&!j&&!s.state.reducedMotion){const{x:M,y:O}=s.state.velocity;e.math.dist(M,O)>1&&(z=e.math.angle(M,O)),g=e.math.lerpAngle(g,z,.15)}else g=e.math.lerpAngle(g,0,.15);const E=o(s.state)==="raw"?s.state.pointer:s.state.smooth;e.dom.setTransform(h,E.x+n+m,E.y+T+A,g)},cleanup(){clearTimeout(S)}},t)},W=(t={})=>{const a=e.normalize(t.size,20),c=e.normalize(t.hoverSize,40),i=e.normalize(t.color,"#ffffff"),f=e.normalize(t.borderWidth,2),w=e.normalize(t.fill,"transparent");let b=20,S=20,g=0,z=1,R=1;return e.definePlugin({name:t.name||"smart-ring",selector:"[data-supermouse-color]",create:o=>{const x=e.dom.createCircle(a(o.state),w(o.state));return e.dom.applyStyles(x,{zIndex:e.Layers.FOLLOWER,mixBlendMode:t.mixBlendMode||"difference",transition:"opacity 0.2s ease, border-radius 0.2s ease",borderStyle:"solid"}),x},update:(o,x)=>{const p=a(o.state),y=o.state.shape;let l=p,n=p,T="50%",s=i(o.state);y?(l=y.width,n=y.height,T=`${y.borderRadius}px`):(o.state.isHover&&(l=c(o.state),n=c(o.state)),o.state.isDown&&(l*=.9,n*=.9)),o.state.interaction.color&&(s=o.state.interaction.color),b=e.math.lerp(b,l,.2),S=e.math.lerp(S,n,.2),e.dom.setStyle(x,"width",`${b}px`),e.dom.setStyle(x,"height",`${S}px`),e.dom.setStyle(x,"borderRadius",T),e.dom.setStyle(x,"borderColor",s),e.dom.setStyle(x,"backgroundColor",w(o.state)),e.dom.setStyle(x,"borderWidth",`${f(o.state)}px`);let h=0,r=1,u=1;if(!y&&t.enableSkew&&!o.state.reducedMotion){const{velocity:m}=o.state,A=e.effects.getVelocityDistortion(m.x,m.y);h=A.rotation,r=A.scaleX,u=A.scaleY,g=e.math.lerpAngle(g,h,.15)}else g=0;z=e.math.lerp(z,r,.15),R=e.math.lerp(R,u,.15);const{x:d,y:v}=o.state.smooth;e.dom.setTransform(x,d,v,g,z,R)}},t)},F=(t={})=>{const a=t.count||30,c=t.decay||.05,i=t.frequency||10,f=t.scatter||5,b=e.normalize(t.color,"#ff00ff"),S=[];let g=0,z=0,R=!1,o=0;const x=(p,y,l)=>{const n=S.find(r=>!r.isActive);if(!n)return;n.isActive=!0,n.life=1,n.x=p+e.math.random(-f,f),n.y=y+e.math.random(-f,f);const T=e.math.random(0,Math.PI*2),s=e.math.random(.5,1.5);n.vx=Math.cos(T)*s,n.vy=Math.sin(T)*s,n.scale=e.math.random(.5,1.2),n.color=l;const h=e.math.random(2,5);e.dom.setStyle(n.el,"width",`${h}px`),e.dom.setStyle(n.el,"height",`${h}px`),e.dom.setStyle(n.el,"backgroundColor",l),e.dom.setStyle(n.el,"opacity","1"),e.dom.setTransform(n.el,n.x,n.y,0,n.scale,n.scale)};return e.definePlugin({name:t.name||"sparkles",install(p){for(let y=0;y<a;y++){const l=e.dom.createCircle(0,"transparent");e.dom.applyStyles(l,{zIndex:e.Layers.TRACE,opacity:"0",willChange:"transform, opacity",transition:"none"}),p.container.appendChild(l),S.push({el:l,isActive:!1,x:0,y:0,vx:0,vy:0,life:0,scale:1,color:""})}},update(p){const{x:y,y:l}=p.state.pointer;R||(g=y,z=l,R=!0);const n=y-g,T=l-z,s=Math.hypot(n,T);if(o+=s,o>i){const h=b(p.state),r=Math.floor(o/i);for(let u=0;u<r;u++){const d=u/r,v=g+n*d,m=z+T*d;x(v,m,h)}o=o%i}g=y,z=l;for(let h=0;h<a;h++){const r=S[h];if(r.isActive)if(r.x+=r.vx,r.y+=r.vy,r.life-=c,r.life<=0)r.isActive=!1,r.el.style.opacity="0";else{r.el.style.opacity=String(r.life);const u=r.scale*r.life;e.dom.setTransform(r.el,r.x,r.y,0,u,u)}}},destroy(){S.forEach(p=>p.el.remove()),S.length=0}},t)};let H=0;const U=(t={})=>{let a,c,i,f,w;const b=`supermouse-text-ring-path-${H++}`,S="SUPERMOUSE • SUPERMOUSE • ",g=60,z=12,R=.5,o=t.className||"",x=t.spread??!1,p=e.normalize(t.text,S),y=e.normalize(t.radius,g),l=e.normalize(t.fontSize,z),n=e.normalize(t.speed,R),T=e.normalize(t.opacity,1);let s=0,h="",r=0,u=0;return e.definePlugin({name:"text-ring",selector:"[data-supermouse-text-ring]",create:d=>{const v=e.dom.createActor("div");e.dom.applyStyles(v,{zIndex:e.Layers.FOLLOWER,transition:"opacity 0.2s ease",opacity:"1",width:"0px",height:"0px",overflow:"visible",display:"flex",alignItems:"center",justifyContent:"center"}),o&&v.classList.add(...o.split(" ").filter(Boolean)),a=document.createElementNS("http://www.w3.org/2000/svg","svg"),a.style.overflow="visible",a.style.position="absolute",a.style.left="0",a.style.top="0",c=document.createElementNS("http://www.w3.org/2000/svg","path"),c.setAttribute("id",b),c.setAttribute("fill","none"),f=document.createElementNS("http://www.w3.org/2000/svg","text");const m=l(d.state);return f.setAttribute("font-size",`${m}px`),u=m,f.setAttribute("fill","currentColor"),f.style.textTransform="uppercase",f.style.letterSpacing="2px",i=document.createElementNS("http://www.w3.org/2000/svg","textPath"),i.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",`#${b}`),i.setAttribute("href",`#${b}`),i.setAttribute("startOffset","0%"),w=document.createTextNode(""),i.appendChild(w),f.appendChild(i),a.appendChild(c),a.appendChild(f),v.appendChild(a),v},styles:{color:"color"},update:(d,v)=>{let m=p(d.state);const A=y(d.state),L=l(d.state),$=n(d.state),j=T(d.state);e.dom.setStyle(v,"opacity",String(j));const E=d.state.interaction;if(E.textRing&&typeof E.textRing=="string"?m=E.textRing:E.text&&typeof E.text=="string"&&(m=E.text),A!==r&&(c.setAttribute("d",P.getCirclePath(A)),r=A),x){const I=P.getCircumference(A);i.setAttribute("textLength",String(I)),i.setAttribute("lengthAdjust","spacing"),m=P.formatLoopText(m,!0)}else i.removeAttribute("textLength"),i.removeAttribute("lengthAdjust");L!==u&&(f.setAttribute("font-size",`${L}px`),u=L),m!==h&&(w.textContent=m,h=m),s+=$;const{x:M,y:O}=d.state.smooth;e.dom.setTransform(v,M,O,s)}},t)};C.SmartIcon=N,C.SmartRing=W,C.Sparkles=F,C.TextRing=U,Object.defineProperty(C,Symbol.toStringTag,{value:"Module"})}));
package/meta.json CHANGED
@@ -1,59 +1,148 @@
1
-
2
- [
3
- {
4
- "id": "smart-icon",
5
- "name": "SmartIcon",
6
- "package": "@supermousejs/labs",
7
- "description": "Advanced state machine that morphs SVGs based on semantic context.",
8
- "code": "import { SmartIcon } from '@supermousejs/labs';\n\napp.use(SmartIcon({ icons: { ... } }));",
9
- "recipeId": "context-icon",
10
- "icon": "labs",
11
- "options": [
12
- { "name": "icons", "type": "Record<string, string>", "default": "{}", "description": "Map of state names to SVG strings.", "reactive": false },
13
- { "name": "size", "type": "number", "default": "24", "description": "Size of the icon container.", "reactive": true },
14
- { "name": "color", "type": "string", "default": "'black'", "description": "Icon fill color (currentColor).", "reactive": true },
15
- { "name": "anchor", "type": "string", "default": "'center'", "description": "Alignment (center, top-left, etc).", "reactive": true },
16
- { "name": "offset", "type": "[number, number]", "default": "[0, 0]", "description": "Fixed offset.", "reactive": false },
17
- { "name": "transitionDuration", "type": "number", "default": "200", "description": "Morph transition time in ms.", "reactive": false }
18
- ]
19
- },
20
- {
21
- "id": "smart-ring",
22
- "name": "SmartRing",
23
- "package": "@supermousejs/labs",
24
- "description": "A reactive ring that distorts with velocity and adapts to stuck elements.",
25
- "code": "import { SmartRing } from '@supermousejs/labs';\n\napp.use(SmartRing({ size: 24, color: '#f59e0b', enableSkew: true }));",
26
- "icon": "ring",
27
- "options": [
28
- { "name": "size", "type": "number", "default": "20", "description": "Base diameter.", "reactive": true },
29
- { "name": "hoverSize", "type": "number", "default": "40", "description": "Diameter on hover.", "reactive": true },
30
- { "name": "enableSkew", "type": "boolean", "default": "false", "description": "Distort shape based on velocity.", "reactive": false }
31
- ]
32
- },
33
- {
34
- "id": "sparkles",
35
- "name": "Sparkles",
36
- "package": "@supermousejs/labs",
37
- "description": "Emits particle trails based on movement velocity.",
38
- "code": "import { Sparkles } from '@supermousejs/labs';\n\napp.use(Sparkles({ color: '#f59e0b', frequency: 10 }));",
39
- "icon": "trail",
40
- "options": [
41
- { "name": "color", "type": "string", "default": "'#ff00ff'", "description": "Particle color.", "reactive": true },
42
- { "name": "frequency", "type": "number", "default": "10", "description": "Pixels per spawn.", "reactive": false },
43
- { "name": "decay", "type": "number", "default": "0.05", "description": "Fade rate.", "reactive": false }
44
- ]
45
- },
46
- {
47
- "id": "text-ring",
48
- "name": "TextRing",
49
- "package": "@supermousejs/labs",
50
- "description": "Rotates text around the cursor position.",
51
- "code": "import { TextRing } from '@supermousejs/labs';\n\napp.use(TextRing({ text: 'LOADING • ', radius: 40 }));",
52
- "icon": "text",
53
- "options": [
54
- { "name": "text", "type": "string", "default": "'SUPERMOUSE • '", "description": "Text content.", "reactive": true },
55
- { "name": "radius", "type": "number", "default": "60", "description": "Ring radius.", "reactive": true },
56
- { "name": "speed", "type": "number", "default": "0.5", "description": "Rotation speed deg/frame.", "reactive": true }
57
- ]
58
- }
59
- ]
1
+ [
2
+ {
3
+ "id": "smart-icon",
4
+ "name": "SmartIcon",
5
+ "package": "@supermousejs/labs",
6
+ "description": "Advanced state machine that morphs SVGs based on semantic context.",
7
+ "code": "import { SmartIcon } from '@supermousejs/labs';\n\napp.use(SmartIcon({ icons: { ... } }));",
8
+ "recipeId": "context-icon",
9
+ "icon": "labs",
10
+ "options": [
11
+ {
12
+ "name": "icons",
13
+ "type": "Record<string, string>",
14
+ "default": "{}",
15
+ "description": "Map of state names to SVG strings.",
16
+ "reactive": false
17
+ },
18
+ {
19
+ "name": "size",
20
+ "type": "number",
21
+ "default": "24",
22
+ "description": "Size of the icon container.",
23
+ "reactive": true
24
+ },
25
+ {
26
+ "name": "color",
27
+ "type": "string",
28
+ "default": "'black'",
29
+ "description": "Icon fill color (currentColor).",
30
+ "reactive": true
31
+ },
32
+ {
33
+ "name": "anchor",
34
+ "type": "string",
35
+ "default": "'center'",
36
+ "description": "Alignment (center, top-left, etc).",
37
+ "reactive": true
38
+ },
39
+ {
40
+ "name": "offset",
41
+ "type": "[number, number]",
42
+ "default": "[0, 0]",
43
+ "description": "Fixed offset.",
44
+ "reactive": false
45
+ },
46
+ {
47
+ "name": "transitionDuration",
48
+ "type": "number",
49
+ "default": "200",
50
+ "description": "Morph transition time in ms.",
51
+ "reactive": false
52
+ }
53
+ ]
54
+ },
55
+ {
56
+ "id": "smart-ring",
57
+ "name": "SmartRing",
58
+ "package": "@supermousejs/labs",
59
+ "description": "A reactive ring that distorts with velocity and adapts to stuck elements.",
60
+ "code": "import { SmartRing } from '@supermousejs/labs';\n\napp.use(SmartRing({ size: 24, color: '#f59e0b', enableSkew: true }));",
61
+ "icon": "ring",
62
+ "options": [
63
+ {
64
+ "name": "size",
65
+ "type": "number",
66
+ "default": "20",
67
+ "description": "Base diameter.",
68
+ "reactive": true
69
+ },
70
+ {
71
+ "name": "hoverSize",
72
+ "type": "number",
73
+ "default": "40",
74
+ "description": "Diameter on hover.",
75
+ "reactive": true
76
+ },
77
+ {
78
+ "name": "enableSkew",
79
+ "type": "boolean",
80
+ "default": "false",
81
+ "description": "Distort shape based on velocity.",
82
+ "reactive": false
83
+ }
84
+ ]
85
+ },
86
+ {
87
+ "id": "sparkles",
88
+ "name": "Sparkles",
89
+ "package": "@supermousejs/labs",
90
+ "description": "Emits particle trails based on movement velocity.",
91
+ "code": "import { Sparkles } from '@supermousejs/labs';\n\napp.use(Sparkles({ color: '#f59e0b', frequency: 10 }));",
92
+ "icon": "trail",
93
+ "options": [
94
+ {
95
+ "name": "color",
96
+ "type": "string",
97
+ "default": "'#ff00ff'",
98
+ "description": "Particle color.",
99
+ "reactive": true
100
+ },
101
+ {
102
+ "name": "frequency",
103
+ "type": "number",
104
+ "default": "10",
105
+ "description": "Pixels per spawn.",
106
+ "reactive": false
107
+ },
108
+ {
109
+ "name": "decay",
110
+ "type": "number",
111
+ "default": "0.05",
112
+ "description": "Fade rate.",
113
+ "reactive": false
114
+ }
115
+ ]
116
+ },
117
+ {
118
+ "id": "text-ring",
119
+ "name": "TextRing",
120
+ "package": "@supermousejs/labs",
121
+ "description": "Rotates text around the cursor position.",
122
+ "code": "import { TextRing } from '@supermousejs/labs';\n\napp.use(TextRing({ text: 'LOADING • ', radius: 40 }));",
123
+ "icon": "text",
124
+ "options": [
125
+ {
126
+ "name": "text",
127
+ "type": "string",
128
+ "default": "'SUPERMOUSE • '",
129
+ "description": "Text content.",
130
+ "reactive": true
131
+ },
132
+ {
133
+ "name": "radius",
134
+ "type": "number",
135
+ "default": "60",
136
+ "description": "Ring radius.",
137
+ "reactive": true
138
+ },
139
+ {
140
+ "name": "speed",
141
+ "type": "number",
142
+ "default": "0.5",
143
+ "description": "Rotation speed deg/frame.",
144
+ "reactive": true
145
+ }
146
+ ]
147
+ }
148
+ ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supermousejs/labs",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "main": "dist/index.umd.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -8,14 +8,14 @@
8
8
  "url": "https://github.com/Whitestar14/supermouse-js",
9
9
  "license": "MIT",
10
10
  "dependencies": {
11
- "@supermousejs/utils": "2.1.1",
12
- "@supermousejs/zoetrope": "2.1.1"
11
+ "@supermousejs/zoetrope": "2.2.0",
12
+ "@supermousejs/utils": "2.2.0"
13
13
  },
14
14
  "peerDependencies": {
15
- "@supermousejs/core": "2.0.5"
15
+ "@supermousejs/core": "2.1.0"
16
16
  },
17
17
  "devDependencies": {
18
- "@supermousejs/core": "2.0.5"
18
+ "@supermousejs/core": "2.1.0"
19
19
  },
20
20
  "repository": {
21
21
  "type": "git",