@supermousejs/labs 2.1.1 → 2.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/CHANGELOG.md +28 -0
- package/LICENSE.md +21 -21
- package/README.md +45 -42
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +114 -107
- package/dist/index.umd.js +9 -1
- package/meta.json +148 -59
- package/package.json +5 -5
- package/src/SmartIcon.ts +200 -239
- package/src/SmartRing.ts +105 -105
- package/src/Sparkles.ts +168 -168
- package/src/TextRing.ts +159 -156
- package/src/index.ts +4 -5
- package/tsconfig.json +4 -21
- package/vite.config.ts +24 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @supermousejs/labs
|
|
2
2
|
|
|
3
|
+
## 2.3.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [f6f44b2]
|
|
8
|
+
- @supermousejs/core@2.2.0
|
|
9
|
+
- @supermousejs/utils@2.3.0
|
|
10
|
+
- @supermousejs/zoetrope@2.3.0
|
|
11
|
+
|
|
12
|
+
## 2.2.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- 9fa6ece: Add `injectStyles` to safely handle injecting global CSS styles into the document head
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 6d70c18: remove legacy package and update supermouse domain in readme
|
|
21
|
+
- 14fb5b6: Updated tsconfig to be reference-compliant with core, utils and zoetrope when required
|
|
22
|
+
- Updated dependencies [6d70c18]
|
|
23
|
+
- Updated dependencies [2590af3]
|
|
24
|
+
- Updated dependencies [14fb5b6]
|
|
25
|
+
- Updated dependencies [9fe1a7b]
|
|
26
|
+
- Updated dependencies [9fa6ece]
|
|
27
|
+
- @supermousejs/core@2.1.0
|
|
28
|
+
- @supermousejs/utils@2.2.0
|
|
29
|
+
- @supermousejs/zoetrope@2.2.0
|
|
30
|
+
|
|
3
31
|
## 2.1.1
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
package/LICENSE.md
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Sijibomi Olusunmbola
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Sijibomi Olusunmbola
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,42 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Morphs SVG icons based on semantic tags (links, inputs) or context.
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
import { SmartIcon } from
|
|
13
|
-
app.use(SmartIcon({ icons: { default:
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
### SmartRing
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
1
|
+
# @supermousejs/labs
|
|
2
|
+
|
|
3
|
+
Experimental and advanced plugins for Supermouse.
|
|
4
|
+
|
|
5
|
+
## Included Plugins
|
|
6
|
+
|
|
7
|
+
### SmartIcon
|
|
8
|
+
|
|
9
|
+
Morphs SVG icons based on semantic tags (links, inputs) or context.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { SmartIcon } from "@supermousejs/labs";
|
|
13
|
+
app.use(SmartIcon({ icons: { default: "...", pointer: "..." } }));
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### SmartRing
|
|
17
|
+
|
|
18
|
+
A reactive ring that distorts with velocity and adapts to stuck elements.
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { SmartRing } from "@supermousejs/labs";
|
|
22
|
+
app.use(SmartRing({ enableSkew: true }));
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Sparkles
|
|
26
|
+
|
|
27
|
+
Emits particle trails based on movement velocity.
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { Sparkles } from "@supermousejs/labs";
|
|
31
|
+
app.use(Sparkles({ color: "gold" }));
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### TextRing
|
|
35
|
+
|
|
36
|
+
Rotates text around the cursor position.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { TextRing } from "@supermousejs/labs";
|
|
40
|
+
app.use(TextRing({ text: "LOADING • " }));
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Documentation
|
|
44
|
+
|
|
45
|
+
Full documentation and interactive playground available at [supermouse](https://supermouse.js.org) or [check out the repo](https://github.com/Whitestar14/supermouse-js).
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SupermousePlugin } from '
|
|
2
|
-
import { ValueOrGetter } from '
|
|
1
|
+
import { SupermousePlugin } from '../packages/core/src';
|
|
2
|
+
import { ValueOrGetter } from '../packages/core/src';
|
|
3
3
|
|
|
4
4
|
export declare const SmartIcon: (options: SmartIconOptions) => SupermousePlugin;
|
|
5
5
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,29 +1,27 @@
|
|
|
1
|
-
import { normalize as
|
|
1
|
+
import { normalize as p, definePlugin as N, dom as n, math as w, Layers as k, effects as F } from "@supermousejs/utils";
|
|
2
2
|
import { getCirclePath as H, getCircumference as X, formatLoopText as Y } from "@supermousejs/zoetrope";
|
|
3
|
-
function
|
|
3
|
+
function j(t, a) {
|
|
4
4
|
const o = t.tagName.toLowerCase();
|
|
5
5
|
if (o === "input" || o === "textarea" || t.isContentEditable) {
|
|
6
6
|
const i = t.type;
|
|
7
|
-
if (["button", "submit", "checkbox", "radio", "range", "color"].includes(
|
|
8
|
-
|
|
9
|
-
)) {
|
|
10
|
-
if (l.pointer)
|
|
7
|
+
if (["button", "submit", "checkbox", "radio", "range", "color"].includes(i)) {
|
|
8
|
+
if (a.pointer)
|
|
11
9
|
return "pointer";
|
|
12
|
-
} else if (
|
|
13
|
-
} else if ((o === "a" || o === "button" || t.closest("a") || t.closest("button")) &&
|
|
10
|
+
} else if (a.text) return "text";
|
|
11
|
+
} else if ((o === "a" || o === "button" || t.closest("a") || t.closest("button")) && a.pointer)
|
|
14
12
|
return "pointer";
|
|
15
13
|
return null;
|
|
16
14
|
}
|
|
17
15
|
const q = (t) => {
|
|
18
|
-
let
|
|
19
|
-
const E =
|
|
16
|
+
let a, o = t.defaultState || "default", i = t.defaultState || "default", d = null, T = null, A = !1, x, h = 0, C = 0;
|
|
17
|
+
const E = p(t.size, 24), r = p(t.followStrategy, "smooth"), S = p(t.anchor, "center"), v = p(t.rotateWithVelocity, !1), m = t.useSemanticTags ?? !0, c = t.transitionDuration ?? 200, s = t.offset ? t.offset[0] : 0, R = t.offset ? t.offset[1] : 0;
|
|
20
18
|
return N(
|
|
21
19
|
{
|
|
22
20
|
name: t.name || "smart-icon",
|
|
23
21
|
selector: "[data-supermouse-icon]",
|
|
24
22
|
create: () => {
|
|
25
|
-
const
|
|
26
|
-
return
|
|
23
|
+
const l = n.createActor("div");
|
|
24
|
+
return l.style.zIndex = k.CURSOR, a = n.createActor("div"), n.applyStyles(a, {
|
|
27
25
|
width: "100%",
|
|
28
26
|
height: "100%",
|
|
29
27
|
display: "flex",
|
|
@@ -31,45 +29,51 @@ const q = (t) => {
|
|
|
31
29
|
justifyContent: "center",
|
|
32
30
|
transformOrigin: "center center",
|
|
33
31
|
transform: "scale(1)",
|
|
34
|
-
// Pre-baked ease. Note: If duration changes dynamically, this won't update.
|
|
35
32
|
transition: `transform ${c / 2}ms cubic-bezier(0.16, 1, 0.3, 1)`
|
|
36
|
-
}),
|
|
33
|
+
}), a.innerHTML = t.icons[o] || "", n.injectStyles(
|
|
34
|
+
"supermouse-smart-icon-styles",
|
|
35
|
+
`
|
|
36
|
+
@keyframes sm {
|
|
37
|
+
0% { transform: rotate(0deg); }
|
|
38
|
+
100% { transform: rotate(360deg); }
|
|
39
|
+
}
|
|
40
|
+
.supermouse-spin {
|
|
41
|
+
animation: sm 1s linear infinite;
|
|
42
|
+
}
|
|
43
|
+
`
|
|
44
|
+
), l.appendChild(a), l;
|
|
37
45
|
},
|
|
38
46
|
styles: {
|
|
39
47
|
color: "color"
|
|
40
48
|
},
|
|
41
|
-
update: (
|
|
42
|
-
const e = t.icons,
|
|
49
|
+
update: (l, y) => {
|
|
50
|
+
const e = t.icons, g = l.state.hoverTarget;
|
|
43
51
|
let f = t.defaultState || "default";
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
const L =
|
|
52
|
+
if (g) {
|
|
53
|
+
g !== d && (d = g, T = m ? j(g, e) : null);
|
|
54
|
+
const L = l.state.interaction?.icon;
|
|
47
55
|
L && e[L] ? f = L : T && (f = T);
|
|
48
56
|
} else
|
|
49
57
|
d = null, T = null;
|
|
50
|
-
f !== o && !
|
|
51
|
-
o = i,
|
|
52
|
-
|
|
58
|
+
f !== o && !A && (e[f] || f === (t.defaultState || "default")) && (i = f, A = !0, clearTimeout(x), a.style.transform = "scale(0)", x = setTimeout(() => {
|
|
59
|
+
o = i, a.innerHTML = e[o] || "", a.style.transform = "scale(1)", x = setTimeout(() => {
|
|
60
|
+
A = !1;
|
|
53
61
|
}, c / 2);
|
|
54
62
|
}, c / 2));
|
|
55
|
-
const b = E(
|
|
56
|
-
n.setStyle(
|
|
63
|
+
const b = E(l.state);
|
|
64
|
+
n.setStyle(y, "width", `${b}px`), n.setStyle(y, "height", `${b}px`);
|
|
57
65
|
let u = 0, z = 0;
|
|
58
|
-
const $ = b / 2, O = S(
|
|
66
|
+
const $ = b / 2, O = S(l.state);
|
|
59
67
|
O !== "center" && (O.includes("left") && (u = $), O.includes("right") && (u = -$), O.includes("top") && (z = $), O.includes("bottom") && (z = -$));
|
|
60
68
|
const P = o === "pointer" || o === "text";
|
|
61
|
-
if (v(
|
|
62
|
-
const { x: L, y: I } =
|
|
63
|
-
w.dist(L, I) > 1 && (
|
|
64
|
-
h,
|
|
65
|
-
p,
|
|
66
|
-
0.15
|
|
67
|
-
);
|
|
69
|
+
if (v(l.state) && !P && !l.state.reducedMotion) {
|
|
70
|
+
const { x: L, y: I } = l.state.velocity;
|
|
71
|
+
w.dist(L, I) > 1 && (C = w.angle(L, I)), h = w.lerpAngle(h, C, 0.15);
|
|
68
72
|
} else
|
|
69
73
|
h = w.lerpAngle(h, 0, 0.15);
|
|
70
|
-
const M = r(
|
|
74
|
+
const M = r(l.state) === "raw" ? l.state.pointer : l.state.smooth;
|
|
71
75
|
n.setTransform(
|
|
72
|
-
|
|
76
|
+
y,
|
|
73
77
|
M.x + s + u,
|
|
74
78
|
M.y + R + z,
|
|
75
79
|
h
|
|
@@ -82,14 +86,14 @@ const q = (t) => {
|
|
|
82
86
|
t
|
|
83
87
|
);
|
|
84
88
|
}, V = (t = {}) => {
|
|
85
|
-
const
|
|
86
|
-
let
|
|
89
|
+
const a = p(t.size, 20), o = p(t.hoverSize, 40), i = p(t.color, "#ffffff"), d = p(t.borderWidth, 2), T = p(t.fill, "transparent");
|
|
90
|
+
let A = 20, x = 20, h = 0, C = 1, E = 1;
|
|
87
91
|
return N(
|
|
88
92
|
{
|
|
89
93
|
name: t.name || "smart-ring",
|
|
90
94
|
selector: "[data-supermouse-color]",
|
|
91
95
|
create: (r) => {
|
|
92
|
-
const S = n.createCircle(
|
|
96
|
+
const S = n.createCircle(a(r.state), T(r.state));
|
|
93
97
|
return n.applyStyles(S, {
|
|
94
98
|
zIndex: k.FOLLOWER,
|
|
95
99
|
mixBlendMode: t.mixBlendMode || "difference",
|
|
@@ -98,39 +102,39 @@ const q = (t) => {
|
|
|
98
102
|
}), S;
|
|
99
103
|
},
|
|
100
104
|
update: (r, S) => {
|
|
101
|
-
const v =
|
|
102
|
-
let c = v, s = v, R = "50%",
|
|
103
|
-
|
|
104
|
-
let
|
|
105
|
-
if (!
|
|
105
|
+
const v = a(r.state), m = r.state.shape;
|
|
106
|
+
let c = v, s = v, R = "50%", l = i(r.state);
|
|
107
|
+
m ? (c = m.width, s = m.height, R = `${m.borderRadius}px`) : (r.state.isHover && (c = o(r.state), s = o(r.state)), r.state.isDown && (c *= 0.9, s *= 0.9)), r.state.interaction.color && (l = r.state.interaction.color), A = w.lerp(A, c, 0.2), x = w.lerp(x, s, 0.2), n.setStyle(S, "width", `${A}px`), n.setStyle(S, "height", `${x}px`), n.setStyle(S, "borderRadius", R), n.setStyle(S, "borderColor", l), n.setStyle(S, "backgroundColor", T(r.state)), n.setStyle(S, "borderWidth", `${d(r.state)}px`);
|
|
108
|
+
let y = 0, e = 1, g = 1;
|
|
109
|
+
if (!m && t.enableSkew && !r.state.reducedMotion) {
|
|
106
110
|
const { velocity: u } = r.state, z = F.getVelocityDistortion(u.x, u.y);
|
|
107
|
-
|
|
111
|
+
y = z.rotation, e = z.scaleX, g = z.scaleY, h = w.lerpAngle(h, y, 0.15);
|
|
108
112
|
} else
|
|
109
113
|
h = 0;
|
|
110
|
-
|
|
114
|
+
C = w.lerp(C, e, 0.15), E = w.lerp(E, g, 0.15);
|
|
111
115
|
const { x: f, y: b } = r.state.smooth;
|
|
112
|
-
n.setTransform(S, f, b, h,
|
|
116
|
+
n.setTransform(S, f, b, h, C, E);
|
|
113
117
|
}
|
|
114
118
|
},
|
|
115
119
|
t
|
|
116
120
|
);
|
|
117
121
|
}, G = (t = {}) => {
|
|
118
|
-
const
|
|
119
|
-
let h = 0,
|
|
120
|
-
const S = (v,
|
|
122
|
+
const a = t.count || 30, o = t.decay || 0.05, i = t.frequency || 10, d = t.scatter || 5, A = p(t.color, "#ff00ff"), x = [];
|
|
123
|
+
let h = 0, C = 0, E = !1, r = 0;
|
|
124
|
+
const S = (v, m, c) => {
|
|
121
125
|
const s = x.find((e) => !e.isActive);
|
|
122
126
|
if (!s) return;
|
|
123
|
-
s.isActive = !0, s.life = 1, s.x = v + w.random(-d, d), s.y =
|
|
124
|
-
const R = w.random(0, Math.PI * 2),
|
|
125
|
-
s.vx = Math.cos(R) *
|
|
126
|
-
const
|
|
127
|
-
n.setStyle(s.el, "width", `${
|
|
127
|
+
s.isActive = !0, s.life = 1, s.x = v + w.random(-d, d), s.y = m + w.random(-d, d);
|
|
128
|
+
const R = w.random(0, Math.PI * 2), l = w.random(0.5, 1.5);
|
|
129
|
+
s.vx = Math.cos(R) * l, s.vy = Math.sin(R) * l, s.scale = w.random(0.5, 1.2), s.color = c;
|
|
130
|
+
const y = w.random(2, 5);
|
|
131
|
+
n.setStyle(s.el, "width", `${y}px`), n.setStyle(s.el, "height", `${y}px`), n.setStyle(s.el, "backgroundColor", c), n.setStyle(s.el, "opacity", "1"), n.setTransform(s.el, s.x, s.y, 0, s.scale, s.scale);
|
|
128
132
|
};
|
|
129
133
|
return N(
|
|
130
134
|
{
|
|
131
135
|
name: t.name || "sparkles",
|
|
132
136
|
install(v) {
|
|
133
|
-
for (let
|
|
137
|
+
for (let m = 0; m < a; m++) {
|
|
134
138
|
const c = n.createCircle(0, "transparent");
|
|
135
139
|
n.applyStyles(c, {
|
|
136
140
|
zIndex: k.TRACE,
|
|
@@ -151,27 +155,27 @@ const q = (t) => {
|
|
|
151
155
|
}
|
|
152
156
|
},
|
|
153
157
|
update(v) {
|
|
154
|
-
const { x:
|
|
155
|
-
E || (h =
|
|
156
|
-
const s =
|
|
157
|
-
if (r +=
|
|
158
|
-
const
|
|
159
|
-
for (let
|
|
160
|
-
const f =
|
|
161
|
-
S(b, u,
|
|
158
|
+
const { x: m, y: c } = v.state.pointer;
|
|
159
|
+
E || (h = m, C = c, E = !0);
|
|
160
|
+
const s = m - h, R = c - C, l = Math.hypot(s, R);
|
|
161
|
+
if (r += l, r > i) {
|
|
162
|
+
const y = A(v.state), e = Math.floor(r / i);
|
|
163
|
+
for (let g = 0; g < e; g++) {
|
|
164
|
+
const f = g / e, b = h + s * f, u = C + R * f;
|
|
165
|
+
S(b, u, y);
|
|
162
166
|
}
|
|
163
167
|
r = r % i;
|
|
164
168
|
}
|
|
165
|
-
h =
|
|
166
|
-
for (let
|
|
167
|
-
const e = x[
|
|
169
|
+
h = m, C = c;
|
|
170
|
+
for (let y = 0; y < a; y++) {
|
|
171
|
+
const e = x[y];
|
|
168
172
|
if (e.isActive)
|
|
169
173
|
if (e.x += e.vx, e.y += e.vy, e.life -= o, e.life <= 0)
|
|
170
174
|
e.isActive = !1, e.el.style.opacity = "0";
|
|
171
175
|
else {
|
|
172
176
|
e.el.style.opacity = String(e.life);
|
|
173
|
-
const
|
|
174
|
-
n.setTransform(e.el, e.x, e.y, 0,
|
|
177
|
+
const g = e.scale * e.life;
|
|
178
|
+
n.setTransform(e.el, e.x, e.y, 0, g, g);
|
|
175
179
|
}
|
|
176
180
|
}
|
|
177
181
|
},
|
|
@@ -182,48 +186,51 @@ const q = (t) => {
|
|
|
182
186
|
t
|
|
183
187
|
);
|
|
184
188
|
};
|
|
185
|
-
let
|
|
189
|
+
let U = 0;
|
|
186
190
|
const J = (t = {}) => {
|
|
187
|
-
let
|
|
188
|
-
const
|
|
189
|
-
let
|
|
190
|
-
return N(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
191
|
+
let a, o, i, d, T;
|
|
192
|
+
const A = `supermouse-text-ring-path-${U++}`, x = "SUPERMOUSE • SUPERMOUSE • ", h = 60, C = 12, E = 0.5, r = t.className || "", S = t.spread ?? !1, v = p(t.text, x), m = p(t.radius, h), c = p(t.fontSize, C), s = p(t.speed, E), R = p(t.opacity, 1);
|
|
193
|
+
let l = 0, y = "", e = 0, g = 0;
|
|
194
|
+
return N(
|
|
195
|
+
{
|
|
196
|
+
name: "text-ring",
|
|
197
|
+
selector: "[data-supermouse-text-ring]",
|
|
198
|
+
create: (f) => {
|
|
199
|
+
const b = n.createActor("div");
|
|
200
|
+
n.applyStyles(b, {
|
|
201
|
+
zIndex: k.FOLLOWER,
|
|
202
|
+
transition: "opacity 0.2s ease",
|
|
203
|
+
opacity: "1",
|
|
204
|
+
width: "0px",
|
|
205
|
+
height: "0px",
|
|
206
|
+
overflow: "visible",
|
|
207
|
+
display: "flex",
|
|
208
|
+
alignItems: "center",
|
|
209
|
+
justifyContent: "center"
|
|
210
|
+
}), r && b.classList.add(...r.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", o = document.createElementNS("http://www.w3.org/2000/svg", "path"), o.setAttribute("id", A), o.setAttribute("fill", "none"), d = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
|
211
|
+
const u = c(f.state);
|
|
212
|
+
return d.setAttribute("font-size", `${u}px`), g = u, d.setAttribute("fill", "currentColor"), d.style.textTransform = "uppercase", d.style.letterSpacing = "2px", i = document.createElementNS("http://www.w3.org/2000/svg", "textPath"), i.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", `#${A}`), i.setAttribute("href", `#${A}`), i.setAttribute("startOffset", "0%"), T = document.createTextNode(""), i.appendChild(T), d.appendChild(i), a.appendChild(o), a.appendChild(d), b.appendChild(a), b;
|
|
213
|
+
},
|
|
214
|
+
styles: {
|
|
215
|
+
color: "color"
|
|
216
|
+
},
|
|
217
|
+
update: (f, b) => {
|
|
218
|
+
let u = v(f.state);
|
|
219
|
+
const z = m(f.state), $ = c(f.state), O = s(f.state), P = R(f.state);
|
|
220
|
+
n.setStyle(b, "opacity", String(P));
|
|
221
|
+
const M = f.state.interaction;
|
|
222
|
+
if (M.textRing && typeof M.textRing == "string" ? u = M.textRing : M.text && typeof M.text == "string" && (u = M.text), z !== e && (o.setAttribute("d", H(z)), e = z), S) {
|
|
223
|
+
const W = X(z);
|
|
224
|
+
i.setAttribute("textLength", String(W)), i.setAttribute("lengthAdjust", "spacing"), u = Y(u, !0);
|
|
225
|
+
} else
|
|
226
|
+
i.removeAttribute("textLength"), i.removeAttribute("lengthAdjust");
|
|
227
|
+
$ !== g && (d.setAttribute("font-size", `${$}px`), g = $), u !== y && (T.textContent = u, y = u), l += O;
|
|
228
|
+
const { x: L, y: I } = f.state.smooth;
|
|
229
|
+
n.setTransform(b, L, I, l);
|
|
230
|
+
}
|
|
211
231
|
},
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const z = y(f.state), $ = c(f.state), O = s(f.state), P = R(f.state);
|
|
215
|
-
n.setStyle(b, "opacity", String(P));
|
|
216
|
-
const M = f.state.interaction;
|
|
217
|
-
if (M.textRing && typeof M.textRing == "string" ? u = M.textRing : M.text && typeof M.text == "string" && (u = M.text), z !== e && (o.setAttribute("d", H(z)), e = z), S) {
|
|
218
|
-
const W = X(z);
|
|
219
|
-
i.setAttribute("textLength", String(W)), i.setAttribute("lengthAdjust", "spacing"), u = Y(u, !0);
|
|
220
|
-
} else
|
|
221
|
-
i.removeAttribute("textLength"), i.removeAttribute("lengthAdjust");
|
|
222
|
-
$ !== m && (d.setAttribute("font-size", `${$}px`), m = $), u !== g && (T.textContent = u, g = u), a += O;
|
|
223
|
-
const { x: L, y: I } = f.state.smooth;
|
|
224
|
-
n.setTransform(b, L, I, a);
|
|
225
|
-
}
|
|
226
|
-
}, t);
|
|
232
|
+
t
|
|
233
|
+
);
|
|
227
234
|
};
|
|
228
235
|
export {
|
|
229
236
|
q as SmartIcon,
|
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
|
|
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"})}));
|