@webenza/ui 0.0.1

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 ADDED
@@ -0,0 +1,25 @@
1
+ # @webenza/ui
2
+
3
+ Internal UI and animation components for Webenza.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @webenza/ui react react-dom gsap
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```tsx
14
+ import { CursorFollower } from '@webenza/ui';
15
+
16
+ function App() {
17
+ return (
18
+ <CursorFollower />
19
+ );
20
+ }
21
+ ```
22
+
23
+ ## Components
24
+
25
+ - **CursorFollower**: A custom cursor follower with magnetic and scaling effects.
@@ -0,0 +1,22 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type CursorFollowerProps = {
4
+ text?: string;
5
+ size?: number;
6
+ borderWidth?: number;
7
+ borderColor?: string;
8
+ background?: string;
9
+ fontFamily?: string;
10
+ fontSize?: number;
11
+ fontWeight?: number | string;
12
+ letterSpacing?: number;
13
+ lerp?: number;
14
+ showScale?: number;
15
+ hideScale?: number;
16
+ enabled?: boolean;
17
+ blockSelectors?: string[];
18
+ containerRef?: React.RefObject<HTMLElement>;
19
+ };
20
+ declare const CursorFollower: ({ text, size, borderWidth, borderColor, background, fontFamily, fontSize, fontWeight, letterSpacing, lerp, showScale, hideScale, enabled, blockSelectors, containerRef, }: CursorFollowerProps) => react_jsx_runtime.JSX.Element | null;
21
+
22
+ export { CursorFollower, type CursorFollowerProps };
@@ -0,0 +1,22 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type CursorFollowerProps = {
4
+ text?: string;
5
+ size?: number;
6
+ borderWidth?: number;
7
+ borderColor?: string;
8
+ background?: string;
9
+ fontFamily?: string;
10
+ fontSize?: number;
11
+ fontWeight?: number | string;
12
+ letterSpacing?: number;
13
+ lerp?: number;
14
+ showScale?: number;
15
+ hideScale?: number;
16
+ enabled?: boolean;
17
+ blockSelectors?: string[];
18
+ containerRef?: React.RefObject<HTMLElement>;
19
+ };
20
+ declare const CursorFollower: ({ text, size, borderWidth, borderColor, background, fontFamily, fontSize, fontWeight, letterSpacing, lerp, showScale, hideScale, enabled, blockSelectors, containerRef, }: CursorFollowerProps) => react_jsx_runtime.JSX.Element | null;
21
+
22
+ export { CursorFollower, type CursorFollowerProps };
package/dist/index.js ADDED
@@ -0,0 +1,143 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var gsap = require('gsap');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var gsap__default = /*#__PURE__*/_interopDefault(gsap);
10
+
11
+ // src/cursor/CursorFollower/CursorFollower.tsx
12
+ var CursorFollower = ({
13
+ text = "PLAY",
14
+ size = 90,
15
+ borderWidth = 2,
16
+ borderColor = "#fff",
17
+ background = "transparent",
18
+ fontFamily = "inherit",
19
+ fontSize = 12,
20
+ fontWeight = 400,
21
+ letterSpacing = 2,
22
+ lerp = 0.035,
23
+ showScale = 1,
24
+ hideScale = 0,
25
+ enabled = true,
26
+ blockSelectors = [],
27
+ containerRef
28
+ }) => {
29
+ const cursorRef = react.useRef(null);
30
+ react.useEffect(() => {
31
+ if (!enabled) return;
32
+ const cursor = cursorRef.current;
33
+ if (!cursor) return;
34
+ let targetX = 0;
35
+ let targetY = 0;
36
+ let currentX = 0;
37
+ let currentY = 0;
38
+ let visible = false;
39
+ let blocked = false;
40
+ const show = () => {
41
+ if (visible || blocked) return;
42
+ visible = true;
43
+ gsap__default.default.to(cursor, { scale: showScale, opacity: 1, duration: 0.25 });
44
+ };
45
+ const hide = () => {
46
+ if (!visible) return;
47
+ visible = false;
48
+ gsap__default.default.to(cursor, { scale: hideScale, opacity: 0, duration: 0.25 });
49
+ };
50
+ const move = (e) => {
51
+ if (containerRef?.current) {
52
+ const bounds = containerRef.current.getBoundingClientRect();
53
+ targetX = e.clientX - bounds.left;
54
+ targetY = e.clientY - bounds.top;
55
+ } else {
56
+ targetX = e.clientX;
57
+ targetY = e.clientY;
58
+ }
59
+ };
60
+ const update = () => {
61
+ currentX += (targetX - currentX) * lerp;
62
+ currentY += (targetY - currentY) * lerp;
63
+ gsap__default.default.set(cursor, {
64
+ x: currentX - size / 2,
65
+ y: currentY - size / 2
66
+ });
67
+ };
68
+ const target = containerRef?.current || window;
69
+ target.addEventListener("mousemove", move);
70
+ target.addEventListener("mouseenter", show);
71
+ target.addEventListener("mouseleave", hide);
72
+ gsap__default.default.ticker.add(update);
73
+ const unbinds = blockSelectors.map((selector) => {
74
+ const el = document.querySelector(selector);
75
+ if (!el) return () => {
76
+ };
77
+ const enter = () => {
78
+ blocked = true;
79
+ hide();
80
+ };
81
+ const leave = () => {
82
+ blocked = false;
83
+ show();
84
+ };
85
+ el.addEventListener("mouseenter", enter);
86
+ el.addEventListener("mouseleave", leave);
87
+ return () => {
88
+ el.removeEventListener("mouseenter", enter);
89
+ el.removeEventListener("mouseleave", leave);
90
+ };
91
+ });
92
+ return () => {
93
+ target.removeEventListener("mousemove", move);
94
+ target.removeEventListener("mouseenter", show);
95
+ target.removeEventListener("mouseleave", hide);
96
+ gsap__default.default.ticker.remove(update);
97
+ unbinds.forEach((u) => u());
98
+ };
99
+ }, [
100
+ enabled,
101
+ size,
102
+ lerp,
103
+ showScale,
104
+ hideScale,
105
+ blockSelectors,
106
+ containerRef
107
+ ]);
108
+ if (!enabled) return null;
109
+ return /* @__PURE__ */ jsxRuntime.jsx(
110
+ "div",
111
+ {
112
+ ref: cursorRef,
113
+ style: {
114
+ position: containerRef ? "absolute" : "fixed",
115
+ top: 0,
116
+ left: 0,
117
+ width: size,
118
+ height: size,
119
+ border: `${borderWidth}px solid ${borderColor}`,
120
+ background,
121
+ borderRadius: "50%",
122
+ display: "flex",
123
+ alignItems: "center",
124
+ justifyContent: "center",
125
+ pointerEvents: "none",
126
+ zIndex: 9999,
127
+ opacity: 0,
128
+ transform: "scale(0)",
129
+ fontFamily,
130
+ fontSize,
131
+ fontWeight,
132
+ letterSpacing,
133
+ textTransform: "uppercase",
134
+ color: borderColor
135
+ },
136
+ children: text
137
+ }
138
+ );
139
+ };
140
+
141
+ exports.CursorFollower = CursorFollower;
142
+ //# sourceMappingURL=index.js.map
143
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cursor/CursorFollower/CursorFollower.tsx"],"names":["useRef","useEffect","gsap","jsx"],"mappings":";;;;;;;;;;;AAyBO,IAAM,iBAAiB,CAAC;AAAA,EAC3B,IAAA,GAAO,MAAA;AAAA,EAEP,IAAA,GAAO,EAAA;AAAA,EACP,WAAA,GAAc,CAAA;AAAA,EACd,WAAA,GAAc,MAAA;AAAA,EACd,UAAA,GAAa,aAAA;AAAA,EAEb,UAAA,GAAa,SAAA;AAAA,EACb,QAAA,GAAW,EAAA;AAAA,EACX,UAAA,GAAa,GAAA;AAAA,EACb,aAAA,GAAgB,CAAA;AAAA,EAEhB,IAAA,GAAO,KAAA;AAAA,EACP,SAAA,GAAY,CAAA;AAAA,EACZ,SAAA,GAAY,CAAA;AAAA,EAEZ,OAAA,GAAU,IAAA;AAAA,EACV,iBAAiB,EAAC;AAAA,EAClB;AACJ,CAAA,KAA2B;AACvB,EAAA,MAAM,SAAA,GAAYA,aAAuB,IAAI,CAAA;AAE7C,EAAAC,eAAA,CAAU,MAAM;AACZ,IAAA,IAAI,CAAC,OAAA,EAAS;AAEd,IAAA,MAAM,SAAS,SAAA,CAAU,OAAA;AACzB,IAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,IAAI,QAAA,GAAW,CAAA;AACf,IAAA,IAAI,QAAA,GAAW,CAAA;AACf,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,IAAI,OAAA,GAAU,KAAA;AAEd,IAAA,MAAM,OAAO,MAAM;AACf,MAAA,IAAI,WAAW,OAAA,EAAS;AACxB,MAAA,OAAA,GAAU,IAAA;AACV,MAAAC,qBAAA,CAAK,EAAA,CAAG,QAAQ,EAAE,KAAA,EAAO,WAAW,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,IAAA,EAAM,CAAA;AAAA,IACpE,CAAA;AAEA,IAAA,MAAM,OAAO,MAAM;AACf,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,OAAA,GAAU,KAAA;AACV,MAAAA,qBAAA,CAAK,EAAA,CAAG,QAAQ,EAAE,KAAA,EAAO,WAAW,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,IAAA,EAAM,CAAA;AAAA,IACpE,CAAA;AAEA,IAAA,MAAM,IAAA,GAAO,CAAC,CAAA,KAAkB;AAC5B,MAAA,IAAI,cAAc,OAAA,EAAS;AACvB,QAAA,MAAM,MAAA,GAAS,YAAA,CAAa,OAAA,CAAQ,qBAAA,EAAsB;AAE1D,QAAA,OAAA,GAAU,CAAA,CAAE,UAAU,MAAA,CAAO,IAAA;AAC7B,QAAA,OAAA,GAAU,CAAA,CAAE,UAAU,MAAA,CAAO,GAAA;AAAA,MACjC,CAAA,MAAO;AACH,QAAA,OAAA,GAAU,CAAA,CAAE,OAAA;AACZ,QAAA,OAAA,GAAU,CAAA,CAAE,OAAA;AAAA,MAChB;AAAA,IACJ,CAAA;AAEA,IAAA,MAAM,SAAS,MAAM;AACjB,MAAA,QAAA,IAAA,CAAa,UAAU,QAAA,IAAY,IAAA;AACnC,MAAA,QAAA,IAAA,CAAa,UAAU,QAAA,IAAY,IAAA;AAEnC,MAAAA,qBAAA,CAAK,IAAI,MAAA,EAAQ;AAAA,QACb,CAAA,EAAG,WAAW,IAAA,GAAO,CAAA;AAAA,QACrB,CAAA,EAAG,WAAW,IAAA,GAAO;AAAA,OACxB,CAAA;AAAA,IACL,CAAA;AAGA,IAAA,MAAM,MAAA,GAAS,cAAc,OAAA,IAAW,MAAA;AAExC,IAAA,MAAA,CAAO,gBAAA,CAAiB,aAAa,IAAW,CAAA;AAChD,IAAA,MAAA,CAAO,gBAAA,CAAiB,cAAc,IAAW,CAAA;AACjD,IAAA,MAAA,CAAO,gBAAA,CAAiB,cAAc,IAAW,CAAA;AAEjD,IAAAA,qBAAA,CAAK,MAAA,CAAO,IAAI,MAAM,CAAA;AAEtB,IAAA,MAAM,OAAA,GAAU,cAAA,CAAe,GAAA,CAAI,CAAC,QAAA,KAAa;AAC7C,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC1C,MAAA,IAAI,CAAC,EAAA,EAAI,OAAO,MAAM;AAAA,MAAE,CAAA;AAExB,MAAA,MAAM,QAAQ,MAAM;AAChB,QAAA,OAAA,GAAU,IAAA;AACV,QAAA,IAAA,EAAK;AAAA,MACT,CAAA;AACA,MAAA,MAAM,QAAQ,MAAM;AAChB,QAAA,OAAA,GAAU,KAAA;AACV,QAAA,IAAA,EAAK;AAAA,MACT,CAAA;AAEA,MAAA,EAAA,CAAG,gBAAA,CAAiB,cAAc,KAAK,CAAA;AACvC,MAAA,EAAA,CAAG,gBAAA,CAAiB,cAAc,KAAK,CAAA;AAEvC,MAAA,OAAO,MAAM;AACT,QAAA,EAAA,CAAG,mBAAA,CAAoB,cAAc,KAAK,CAAA;AAC1C,QAAA,EAAA,CAAG,mBAAA,CAAoB,cAAc,KAAK,CAAA;AAAA,MAC9C,CAAA;AAAA,IACJ,CAAC,CAAA;AAED,IAAA,OAAO,MAAM;AACT,MAAA,MAAA,CAAO,mBAAA,CAAoB,aAAa,IAAW,CAAA;AACnD,MAAA,MAAA,CAAO,mBAAA,CAAoB,cAAc,IAAW,CAAA;AACpD,MAAA,MAAA,CAAO,mBAAA,CAAoB,cAAc,IAAW,CAAA;AACpD,MAAAA,qBAAA,CAAK,MAAA,CAAO,OAAO,MAAM,CAAA;AACzB,MAAA,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAA,EAAG,CAAA;AAAA,IAC9B,CAAA;AAAA,EACJ,CAAA,EAAG;AAAA,IACC,OAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACH,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AAErB,EAAA,uBACIC,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACG,GAAA,EAAK,SAAA;AAAA,MACL,KAAA,EAAO;AAAA,QACH,QAAA,EAAU,eAAe,UAAA,GAAa,OAAA;AAAA,QACtC,GAAA,EAAK,CAAA;AAAA,QACL,IAAA,EAAM,CAAA;AAAA,QACN,KAAA,EAAO,IAAA;AAAA,QACP,MAAA,EAAQ,IAAA;AAAA,QACR,MAAA,EAAQ,CAAA,EAAG,WAAW,CAAA,SAAA,EAAY,WAAW,CAAA,CAAA;AAAA,QAC7C,UAAA;AAAA,QACA,YAAA,EAAc,KAAA;AAAA,QACd,OAAA,EAAS,MAAA;AAAA,QACT,UAAA,EAAY,QAAA;AAAA,QACZ,cAAA,EAAgB,QAAA;AAAA,QAChB,aAAA,EAAe,MAAA;AAAA,QACf,MAAA,EAAQ,IAAA;AAAA,QACR,OAAA,EAAS,CAAA;AAAA,QACT,SAAA,EAAW,UAAA;AAAA,QACX,UAAA;AAAA,QACA,QAAA;AAAA,QACA,UAAA;AAAA,QACA,aAAA;AAAA,QACA,aAAA,EAAe,WAAA;AAAA,QACf,KAAA,EAAO;AAAA,OACX;AAAA,MAEC,QAAA,EAAA;AAAA;AAAA,GACL;AAER","file":"index.js","sourcesContent":["import { useEffect, useRef } from \"react\";\r\nimport gsap from \"gsap\";\r\n\r\nexport type CursorFollowerProps = {\r\n text?: string;\r\n\r\n size?: number;\r\n borderWidth?: number;\r\n borderColor?: string;\r\n background?: string;\r\n\r\n fontFamily?: string;\r\n fontSize?: number;\r\n fontWeight?: number | string;\r\n letterSpacing?: number;\r\n\r\n lerp?: number;\r\n showScale?: number;\r\n hideScale?: number;\r\n\r\n enabled?: boolean;\r\n blockSelectors?: string[];\r\n containerRef?: React.RefObject<HTMLElement>;\r\n};\r\n\r\nexport const CursorFollower = ({\r\n text = \"PLAY\",\r\n\r\n size = 90,\r\n borderWidth = 2,\r\n borderColor = \"#fff\",\r\n background = \"transparent\",\r\n\r\n fontFamily = \"inherit\",\r\n fontSize = 12,\r\n fontWeight = 400,\r\n letterSpacing = 2,\r\n\r\n lerp = 0.035,\r\n showScale = 1,\r\n hideScale = 0,\r\n\r\n enabled = true,\r\n blockSelectors = [],\r\n containerRef,\r\n}: CursorFollowerProps) => {\r\n const cursorRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n if (!enabled) return;\r\n\r\n const cursor = cursorRef.current;\r\n if (!cursor) return;\r\n\r\n let targetX = 0;\r\n let targetY = 0;\r\n let currentX = 0;\r\n let currentY = 0;\r\n let visible = false;\r\n let blocked = false;\r\n\r\n const show = () => {\r\n if (visible || blocked) return;\r\n visible = true;\r\n gsap.to(cursor, { scale: showScale, opacity: 1, duration: 0.25 });\r\n };\r\n\r\n const hide = () => {\r\n if (!visible) return;\r\n visible = false;\r\n gsap.to(cursor, { scale: hideScale, opacity: 0, duration: 0.25 });\r\n };\r\n\r\n const move = (e: MouseEvent) => {\r\n if (containerRef?.current) {\r\n const bounds = containerRef.current.getBoundingClientRect();\r\n // Calculate relative coordinates\r\n targetX = e.clientX - bounds.left;\r\n targetY = e.clientY - bounds.top;\r\n } else {\r\n targetX = e.clientX;\r\n targetY = e.clientY;\r\n }\r\n };\r\n\r\n const update = () => {\r\n currentX += (targetX - currentX) * lerp;\r\n currentY += (targetY - currentY) * lerp;\r\n\r\n gsap.set(cursor, {\r\n x: currentX - size / 2,\r\n y: currentY - size / 2,\r\n });\r\n };\r\n\r\n // Event Listeners Source\r\n const target = containerRef?.current || window;\r\n\r\n target.addEventListener(\"mousemove\", move as any);\r\n target.addEventListener(\"mouseenter\", show as any);\r\n target.addEventListener(\"mouseleave\", hide as any);\r\n\r\n gsap.ticker.add(update);\r\n\r\n const unbinds = blockSelectors.map((selector) => {\r\n const el = document.querySelector(selector);\r\n if (!el) return () => { };\r\n\r\n const enter = () => {\r\n blocked = true;\r\n hide();\r\n };\r\n const leave = () => {\r\n blocked = false;\r\n show();\r\n };\r\n\r\n el.addEventListener(\"mouseenter\", enter);\r\n el.addEventListener(\"mouseleave\", leave);\r\n\r\n return () => {\r\n el.removeEventListener(\"mouseenter\", enter);\r\n el.removeEventListener(\"mouseleave\", leave);\r\n };\r\n });\r\n\r\n return () => {\r\n target.removeEventListener(\"mousemove\", move as any);\r\n target.removeEventListener(\"mouseenter\", show as any);\r\n target.removeEventListener(\"mouseleave\", hide as any);\r\n gsap.ticker.remove(update);\r\n unbinds.forEach((u) => u());\r\n };\r\n }, [\r\n enabled,\r\n size,\r\n lerp,\r\n showScale,\r\n hideScale,\r\n blockSelectors,\r\n containerRef\r\n ]);\r\n\r\n if (!enabled) return null;\r\n\r\n return (\r\n <div\r\n ref={cursorRef}\r\n style={{\r\n position: containerRef ? \"absolute\" : \"fixed\",\r\n top: 0,\r\n left: 0,\r\n width: size,\r\n height: size,\r\n border: `${borderWidth}px solid ${borderColor}`,\r\n background,\r\n borderRadius: \"50%\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n pointerEvents: \"none\",\r\n zIndex: 9999,\r\n opacity: 0,\r\n transform: \"scale(0)\",\r\n fontFamily,\r\n fontSize,\r\n fontWeight,\r\n letterSpacing,\r\n textTransform: \"uppercase\",\r\n color: borderColor,\r\n }}\r\n >\r\n {text}\r\n </div>\r\n );\r\n};\r\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,137 @@
1
+ import { useRef, useEffect } from 'react';
2
+ import gsap from 'gsap';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ // src/cursor/CursorFollower/CursorFollower.tsx
6
+ var CursorFollower = ({
7
+ text = "PLAY",
8
+ size = 90,
9
+ borderWidth = 2,
10
+ borderColor = "#fff",
11
+ background = "transparent",
12
+ fontFamily = "inherit",
13
+ fontSize = 12,
14
+ fontWeight = 400,
15
+ letterSpacing = 2,
16
+ lerp = 0.035,
17
+ showScale = 1,
18
+ hideScale = 0,
19
+ enabled = true,
20
+ blockSelectors = [],
21
+ containerRef
22
+ }) => {
23
+ const cursorRef = useRef(null);
24
+ useEffect(() => {
25
+ if (!enabled) return;
26
+ const cursor = cursorRef.current;
27
+ if (!cursor) return;
28
+ let targetX = 0;
29
+ let targetY = 0;
30
+ let currentX = 0;
31
+ let currentY = 0;
32
+ let visible = false;
33
+ let blocked = false;
34
+ const show = () => {
35
+ if (visible || blocked) return;
36
+ visible = true;
37
+ gsap.to(cursor, { scale: showScale, opacity: 1, duration: 0.25 });
38
+ };
39
+ const hide = () => {
40
+ if (!visible) return;
41
+ visible = false;
42
+ gsap.to(cursor, { scale: hideScale, opacity: 0, duration: 0.25 });
43
+ };
44
+ const move = (e) => {
45
+ if (containerRef?.current) {
46
+ const bounds = containerRef.current.getBoundingClientRect();
47
+ targetX = e.clientX - bounds.left;
48
+ targetY = e.clientY - bounds.top;
49
+ } else {
50
+ targetX = e.clientX;
51
+ targetY = e.clientY;
52
+ }
53
+ };
54
+ const update = () => {
55
+ currentX += (targetX - currentX) * lerp;
56
+ currentY += (targetY - currentY) * lerp;
57
+ gsap.set(cursor, {
58
+ x: currentX - size / 2,
59
+ y: currentY - size / 2
60
+ });
61
+ };
62
+ const target = containerRef?.current || window;
63
+ target.addEventListener("mousemove", move);
64
+ target.addEventListener("mouseenter", show);
65
+ target.addEventListener("mouseleave", hide);
66
+ gsap.ticker.add(update);
67
+ const unbinds = blockSelectors.map((selector) => {
68
+ const el = document.querySelector(selector);
69
+ if (!el) return () => {
70
+ };
71
+ const enter = () => {
72
+ blocked = true;
73
+ hide();
74
+ };
75
+ const leave = () => {
76
+ blocked = false;
77
+ show();
78
+ };
79
+ el.addEventListener("mouseenter", enter);
80
+ el.addEventListener("mouseleave", leave);
81
+ return () => {
82
+ el.removeEventListener("mouseenter", enter);
83
+ el.removeEventListener("mouseleave", leave);
84
+ };
85
+ });
86
+ return () => {
87
+ target.removeEventListener("mousemove", move);
88
+ target.removeEventListener("mouseenter", show);
89
+ target.removeEventListener("mouseleave", hide);
90
+ gsap.ticker.remove(update);
91
+ unbinds.forEach((u) => u());
92
+ };
93
+ }, [
94
+ enabled,
95
+ size,
96
+ lerp,
97
+ showScale,
98
+ hideScale,
99
+ blockSelectors,
100
+ containerRef
101
+ ]);
102
+ if (!enabled) return null;
103
+ return /* @__PURE__ */ jsx(
104
+ "div",
105
+ {
106
+ ref: cursorRef,
107
+ style: {
108
+ position: containerRef ? "absolute" : "fixed",
109
+ top: 0,
110
+ left: 0,
111
+ width: size,
112
+ height: size,
113
+ border: `${borderWidth}px solid ${borderColor}`,
114
+ background,
115
+ borderRadius: "50%",
116
+ display: "flex",
117
+ alignItems: "center",
118
+ justifyContent: "center",
119
+ pointerEvents: "none",
120
+ zIndex: 9999,
121
+ opacity: 0,
122
+ transform: "scale(0)",
123
+ fontFamily,
124
+ fontSize,
125
+ fontWeight,
126
+ letterSpacing,
127
+ textTransform: "uppercase",
128
+ color: borderColor
129
+ },
130
+ children: text
131
+ }
132
+ );
133
+ };
134
+
135
+ export { CursorFollower };
136
+ //# sourceMappingURL=index.mjs.map
137
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cursor/CursorFollower/CursorFollower.tsx"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { useEffect, useRef } from \"react\";\r\nimport gsap from \"gsap\";\r\n\r\nexport type CursorFollowerProps = {\r\n text?: string;\r\n\r\n size?: number;\r\n borderWidth?: number;\r\n borderColor?: string;\r\n background?: string;\r\n\r\n fontFamily?: string;\r\n fontSize?: number;\r\n fontWeight?: number | string;\r\n letterSpacing?: number;\r\n\r\n lerp?: number;\r\n showScale?: number;\r\n hideScale?: number;\r\n\r\n enabled?: boolean;\r\n blockSelectors?: string[];\r\n containerRef?: React.RefObject<HTMLElement>;\r\n};\r\n\r\nexport const CursorFollower = ({\r\n text = \"PLAY\",\r\n\r\n size = 90,\r\n borderWidth = 2,\r\n borderColor = \"#fff\",\r\n background = \"transparent\",\r\n\r\n fontFamily = \"inherit\",\r\n fontSize = 12,\r\n fontWeight = 400,\r\n letterSpacing = 2,\r\n\r\n lerp = 0.035,\r\n showScale = 1,\r\n hideScale = 0,\r\n\r\n enabled = true,\r\n blockSelectors = [],\r\n containerRef,\r\n}: CursorFollowerProps) => {\r\n const cursorRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n if (!enabled) return;\r\n\r\n const cursor = cursorRef.current;\r\n if (!cursor) return;\r\n\r\n let targetX = 0;\r\n let targetY = 0;\r\n let currentX = 0;\r\n let currentY = 0;\r\n let visible = false;\r\n let blocked = false;\r\n\r\n const show = () => {\r\n if (visible || blocked) return;\r\n visible = true;\r\n gsap.to(cursor, { scale: showScale, opacity: 1, duration: 0.25 });\r\n };\r\n\r\n const hide = () => {\r\n if (!visible) return;\r\n visible = false;\r\n gsap.to(cursor, { scale: hideScale, opacity: 0, duration: 0.25 });\r\n };\r\n\r\n const move = (e: MouseEvent) => {\r\n if (containerRef?.current) {\r\n const bounds = containerRef.current.getBoundingClientRect();\r\n // Calculate relative coordinates\r\n targetX = e.clientX - bounds.left;\r\n targetY = e.clientY - bounds.top;\r\n } else {\r\n targetX = e.clientX;\r\n targetY = e.clientY;\r\n }\r\n };\r\n\r\n const update = () => {\r\n currentX += (targetX - currentX) * lerp;\r\n currentY += (targetY - currentY) * lerp;\r\n\r\n gsap.set(cursor, {\r\n x: currentX - size / 2,\r\n y: currentY - size / 2,\r\n });\r\n };\r\n\r\n // Event Listeners Source\r\n const target = containerRef?.current || window;\r\n\r\n target.addEventListener(\"mousemove\", move as any);\r\n target.addEventListener(\"mouseenter\", show as any);\r\n target.addEventListener(\"mouseleave\", hide as any);\r\n\r\n gsap.ticker.add(update);\r\n\r\n const unbinds = blockSelectors.map((selector) => {\r\n const el = document.querySelector(selector);\r\n if (!el) return () => { };\r\n\r\n const enter = () => {\r\n blocked = true;\r\n hide();\r\n };\r\n const leave = () => {\r\n blocked = false;\r\n show();\r\n };\r\n\r\n el.addEventListener(\"mouseenter\", enter);\r\n el.addEventListener(\"mouseleave\", leave);\r\n\r\n return () => {\r\n el.removeEventListener(\"mouseenter\", enter);\r\n el.removeEventListener(\"mouseleave\", leave);\r\n };\r\n });\r\n\r\n return () => {\r\n target.removeEventListener(\"mousemove\", move as any);\r\n target.removeEventListener(\"mouseenter\", show as any);\r\n target.removeEventListener(\"mouseleave\", hide as any);\r\n gsap.ticker.remove(update);\r\n unbinds.forEach((u) => u());\r\n };\r\n }, [\r\n enabled,\r\n size,\r\n lerp,\r\n showScale,\r\n hideScale,\r\n blockSelectors,\r\n containerRef\r\n ]);\r\n\r\n if (!enabled) return null;\r\n\r\n return (\r\n <div\r\n ref={cursorRef}\r\n style={{\r\n position: containerRef ? \"absolute\" : \"fixed\",\r\n top: 0,\r\n left: 0,\r\n width: size,\r\n height: size,\r\n border: `${borderWidth}px solid ${borderColor}`,\r\n background,\r\n borderRadius: \"50%\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n pointerEvents: \"none\",\r\n zIndex: 9999,\r\n opacity: 0,\r\n transform: \"scale(0)\",\r\n fontFamily,\r\n fontSize,\r\n fontWeight,\r\n letterSpacing,\r\n textTransform: \"uppercase\",\r\n color: borderColor,\r\n }}\r\n >\r\n {text}\r\n </div>\r\n );\r\n};\r\n"]}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@webenza/ui",
3
+ "version": "0.0.1",
4
+ "description": "Internal UI and animation components for Webenza",
5
+ "private": false,
6
+ "sideEffects": false,
7
+ "license": "MIT",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.mjs",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "lint": "tsc --noEmit"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/tech-webenza/webenza-ui.git"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/tech-webenza/webenza-ui/issues"
31
+ },
32
+ "homepage": "https://github.com/tech-webenza/webenza-ui#readme",
33
+ "peerDependencies": {
34
+ "gsap": ">=3",
35
+ "react": ">=18",
36
+ "react-dom": ">=18"
37
+ },
38
+ "devDependencies": {
39
+ "@types/react": "^19.2.10",
40
+ "@types/react-dom": "^19.2.3",
41
+ "tsup": "^8.5.1",
42
+ "typescript": "^5.9.3"
43
+ }
44
+ }