@farzadbagheri/fb-components 0.1.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/LICENSE +21 -0
- package/README.md +131 -0
- package/dist/ai.cjs +16 -0
- package/dist/ai.cjs.map +1 -0
- package/dist/ai.css +176 -0
- package/dist/ai.css.map +1 -0
- package/dist/ai.d.cts +33 -0
- package/dist/ai.d.ts +33 -0
- package/dist/ai.js +3 -0
- package/dist/ai.js.map +1 -0
- package/dist/backgrounds.cjs +32 -0
- package/dist/backgrounds.cjs.map +1 -0
- package/dist/backgrounds.css +253 -0
- package/dist/backgrounds.css.map +1 -0
- package/dist/backgrounds.d.cts +71 -0
- package/dist/backgrounds.d.ts +71 -0
- package/dist/backgrounds.js +3 -0
- package/dist/backgrounds.js.map +1 -0
- package/dist/buttons.cjs +20 -0
- package/dist/buttons.cjs.map +1 -0
- package/dist/buttons.css +116 -0
- package/dist/buttons.css.map +1 -0
- package/dist/buttons.d.cts +40 -0
- package/dist/buttons.d.ts +40 -0
- package/dist/buttons.js +3 -0
- package/dist/buttons.js.map +1 -0
- package/dist/chunk-4FWJRWS5.cjs +125 -0
- package/dist/chunk-4FWJRWS5.cjs.map +1 -0
- package/dist/chunk-BSEOOGOV.cjs +217 -0
- package/dist/chunk-BSEOOGOV.cjs.map +1 -0
- package/dist/chunk-C3ASXASL.cjs +205 -0
- package/dist/chunk-C3ASXASL.cjs.map +1 -0
- package/dist/chunk-CTD2GDO6.cjs +121 -0
- package/dist/chunk-CTD2GDO6.cjs.map +1 -0
- package/dist/chunk-EIE6FLCL.js +202 -0
- package/dist/chunk-EIE6FLCL.js.map +1 -0
- package/dist/chunk-H2AV67DY.cjs +260 -0
- package/dist/chunk-H2AV67DY.cjs.map +1 -0
- package/dist/chunk-H6Y3EJPA.cjs +83 -0
- package/dist/chunk-H6Y3EJPA.cjs.map +1 -0
- package/dist/chunk-JHOJY54P.js +123 -0
- package/dist/chunk-JHOJY54P.js.map +1 -0
- package/dist/chunk-JWV3IITG.js +80 -0
- package/dist/chunk-JWV3IITG.js.map +1 -0
- package/dist/chunk-K5QRX5CZ.js +194 -0
- package/dist/chunk-K5QRX5CZ.js.map +1 -0
- package/dist/chunk-MKCSRMHF.cjs +198 -0
- package/dist/chunk-MKCSRMHF.cjs.map +1 -0
- package/dist/chunk-R2F3FTBL.js +119 -0
- package/dist/chunk-R2F3FTBL.js.map +1 -0
- package/dist/chunk-ROKPXWY2.cjs +198 -0
- package/dist/chunk-ROKPXWY2.cjs.map +1 -0
- package/dist/chunk-RUSFF3MZ.js +214 -0
- package/dist/chunk-RUSFF3MZ.js.map +1 -0
- package/dist/chunk-T7CC3CLH.js +195 -0
- package/dist/chunk-T7CC3CLH.js.map +1 -0
- package/dist/chunk-UWQ5QNE3.cjs +311 -0
- package/dist/chunk-UWQ5QNE3.cjs.map +1 -0
- package/dist/chunk-WDUETPNG.js +256 -0
- package/dist/chunk-WDUETPNG.js.map +1 -0
- package/dist/chunk-YQSTEIU5.js +304 -0
- package/dist/chunk-YQSTEIU5.js.map +1 -0
- package/dist/data.cjs +20 -0
- package/dist/data.cjs.map +1 -0
- package/dist/data.css +151 -0
- package/dist/data.css.map +1 -0
- package/dist/data.d.cts +47 -0
- package/dist/data.d.ts +47 -0
- package/dist/data.js +3 -0
- package/dist/data.js.map +1 -0
- package/dist/heroes.cjs +12 -0
- package/dist/heroes.cjs.map +1 -0
- package/dist/heroes.css +190 -0
- package/dist/heroes.css.map +1 -0
- package/dist/heroes.d.cts +19 -0
- package/dist/heroes.d.ts +19 -0
- package/dist/heroes.js +3 -0
- package/dist/heroes.js.map +1 -0
- package/dist/index.cjs +104 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +1269 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/landing.cjs +12 -0
- package/dist/landing.cjs.map +1 -0
- package/dist/landing.css +137 -0
- package/dist/landing.css.map +1 -0
- package/dist/landing.d.cts +14 -0
- package/dist/landing.d.ts +14 -0
- package/dist/landing.js +3 -0
- package/dist/landing.js.map +1 -0
- package/dist/motion.cjs +16 -0
- package/dist/motion.cjs.map +1 -0
- package/dist/motion.css +79 -0
- package/dist/motion.css.map +1 -0
- package/dist/motion.d.cts +26 -0
- package/dist/motion.d.ts +26 -0
- package/dist/motion.js +3 -0
- package/dist/motion.js.map +1 -0
- package/dist/text.cjs +16 -0
- package/dist/text.cjs.map +1 -0
- package/dist/text.css +72 -0
- package/dist/text.css.map +1 -0
- package/dist/text.d.cts +28 -0
- package/dist/text.d.ts +28 -0
- package/dist/text.js +3 -0
- package/dist/text.js.map +1 -0
- package/dist/ui.cjs +16 -0
- package/dist/ui.cjs.map +1 -0
- package/dist/ui.css +95 -0
- package/dist/ui.css.map +1 -0
- package/dist/ui.d.cts +28 -0
- package/dist/ui.d.ts +28 -0
- package/dist/ui.js +3 -0
- package/dist/ui.js.map +1 -0
- package/package.json +134 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { Sparkles, Paperclip, ArrowUp } from 'lucide-react';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/ai/AiPromptBox.tsx
|
|
6
|
+
function AiPromptBox({
|
|
7
|
+
background = "#111116",
|
|
8
|
+
accent = "#9b7cff",
|
|
9
|
+
textColor = "#ffffff",
|
|
10
|
+
radius = 20,
|
|
11
|
+
minHeight = 150,
|
|
12
|
+
showModel = true,
|
|
13
|
+
showAttachment = true,
|
|
14
|
+
modelLabel = "FB AI \xB7 Fast",
|
|
15
|
+
placeholder = "Ask anything...",
|
|
16
|
+
defaultValue = "",
|
|
17
|
+
disabled = false,
|
|
18
|
+
onSubmit,
|
|
19
|
+
className = "",
|
|
20
|
+
style,
|
|
21
|
+
...props
|
|
22
|
+
}) {
|
|
23
|
+
const [
|
|
24
|
+
value,
|
|
25
|
+
setValue
|
|
26
|
+
] = useState(
|
|
27
|
+
defaultValue
|
|
28
|
+
);
|
|
29
|
+
function handleSubmit(event) {
|
|
30
|
+
event.preventDefault();
|
|
31
|
+
const trimmed = value.trim();
|
|
32
|
+
if (disabled || !trimmed) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
onSubmit?.(
|
|
36
|
+
trimmed
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return /* @__PURE__ */ jsx(
|
|
40
|
+
"div",
|
|
41
|
+
{
|
|
42
|
+
...props,
|
|
43
|
+
className: `fb-ai-prompt-box ${className}`,
|
|
44
|
+
style: {
|
|
45
|
+
...style,
|
|
46
|
+
background,
|
|
47
|
+
color: textColor,
|
|
48
|
+
borderRadius: radius,
|
|
49
|
+
minHeight,
|
|
50
|
+
["--fb-ai-prompt-accent"]: accent
|
|
51
|
+
},
|
|
52
|
+
children: /* @__PURE__ */ jsxs(
|
|
53
|
+
"form",
|
|
54
|
+
{
|
|
55
|
+
className: "fb-ai-prompt-box__form",
|
|
56
|
+
onSubmit: handleSubmit,
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsxs("div", { className: "fb-ai-prompt-box__field", children: [
|
|
59
|
+
/* @__PURE__ */ jsx(
|
|
60
|
+
Sparkles,
|
|
61
|
+
{
|
|
62
|
+
className: "fb-ai-prompt-box__spark",
|
|
63
|
+
size: 16,
|
|
64
|
+
"aria-hidden": "true"
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
/* @__PURE__ */ jsx(
|
|
68
|
+
"textarea",
|
|
69
|
+
{
|
|
70
|
+
value,
|
|
71
|
+
disabled,
|
|
72
|
+
placeholder,
|
|
73
|
+
"aria-label": placeholder,
|
|
74
|
+
onChange: (event) => setValue(
|
|
75
|
+
event.target.value
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
] }),
|
|
80
|
+
/* @__PURE__ */ jsxs("div", { className: "fb-ai-prompt-box__footer", children: [
|
|
81
|
+
/* @__PURE__ */ jsxs("div", { className: "fb-ai-prompt-box__actions", children: [
|
|
82
|
+
showAttachment && /* @__PURE__ */ jsx(
|
|
83
|
+
"button",
|
|
84
|
+
{
|
|
85
|
+
type: "button",
|
|
86
|
+
"aria-label": "Attach file",
|
|
87
|
+
className: "fb-ai-prompt-box__secondary",
|
|
88
|
+
children: /* @__PURE__ */ jsx(
|
|
89
|
+
Paperclip,
|
|
90
|
+
{
|
|
91
|
+
size: 15,
|
|
92
|
+
"aria-hidden": "true"
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
),
|
|
97
|
+
showModel && /* @__PURE__ */ jsx("span", { className: "fb-ai-prompt-box__model", children: modelLabel })
|
|
98
|
+
] }),
|
|
99
|
+
/* @__PURE__ */ jsx(
|
|
100
|
+
"button",
|
|
101
|
+
{
|
|
102
|
+
type: "submit",
|
|
103
|
+
disabled: disabled || !value.trim(),
|
|
104
|
+
className: "fb-ai-prompt-box__submit",
|
|
105
|
+
"aria-label": "Submit prompt",
|
|
106
|
+
children: /* @__PURE__ */ jsx(
|
|
107
|
+
ArrowUp,
|
|
108
|
+
{
|
|
109
|
+
size: 16,
|
|
110
|
+
"aria-hidden": "true"
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
] })
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
function StreamingResponse({
|
|
123
|
+
text = "FB Components gives your application a reusable system for motion, interaction and AI-native interfaces.",
|
|
124
|
+
accent = "#9b7cff",
|
|
125
|
+
textColor = "#ffffff",
|
|
126
|
+
speed = 24,
|
|
127
|
+
showCursor = true,
|
|
128
|
+
showStatus = true,
|
|
129
|
+
statusLabel = "GENERATING",
|
|
130
|
+
className = "",
|
|
131
|
+
style,
|
|
132
|
+
...props
|
|
133
|
+
}) {
|
|
134
|
+
const [
|
|
135
|
+
length,
|
|
136
|
+
setLength
|
|
137
|
+
] = useState(0);
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
setLength(
|
|
140
|
+
0
|
|
141
|
+
);
|
|
142
|
+
if (text.length === 0) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const interval = window.setInterval(
|
|
146
|
+
() => {
|
|
147
|
+
setLength(
|
|
148
|
+
(current) => {
|
|
149
|
+
if (current >= text.length) {
|
|
150
|
+
window.clearInterval(
|
|
151
|
+
interval
|
|
152
|
+
);
|
|
153
|
+
return current;
|
|
154
|
+
}
|
|
155
|
+
return current + 1;
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
},
|
|
159
|
+
Math.max(
|
|
160
|
+
5,
|
|
161
|
+
speed
|
|
162
|
+
)
|
|
163
|
+
);
|
|
164
|
+
return () => window.clearInterval(
|
|
165
|
+
interval
|
|
166
|
+
);
|
|
167
|
+
}, [
|
|
168
|
+
text,
|
|
169
|
+
speed
|
|
170
|
+
]);
|
|
171
|
+
const complete = length >= text.length;
|
|
172
|
+
return /* @__PURE__ */ jsxs(
|
|
173
|
+
"div",
|
|
174
|
+
{
|
|
175
|
+
...props,
|
|
176
|
+
className: `fb-streaming-response ${className}`,
|
|
177
|
+
style: {
|
|
178
|
+
...style,
|
|
179
|
+
color: textColor,
|
|
180
|
+
["--fb-streaming-accent"]: accent
|
|
181
|
+
},
|
|
182
|
+
"aria-live": "polite",
|
|
183
|
+
children: [
|
|
184
|
+
showStatus && /* @__PURE__ */ jsxs("div", { className: "fb-streaming-response__status", children: [
|
|
185
|
+
/* @__PURE__ */ jsx(
|
|
186
|
+
"span",
|
|
187
|
+
{
|
|
188
|
+
className: complete ? "is-complete" : "",
|
|
189
|
+
"aria-hidden": "true"
|
|
190
|
+
}
|
|
191
|
+
),
|
|
192
|
+
complete ? "COMPLETE" : statusLabel
|
|
193
|
+
] }),
|
|
194
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
195
|
+
text.slice(
|
|
196
|
+
0,
|
|
197
|
+
length
|
|
198
|
+
),
|
|
199
|
+
showCursor && !complete && /* @__PURE__ */ jsx(
|
|
200
|
+
"span",
|
|
201
|
+
{
|
|
202
|
+
className: "fb-streaming-response__cursor",
|
|
203
|
+
"aria-hidden": "true"
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
] })
|
|
207
|
+
]
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export { AiPromptBox, StreamingResponse };
|
|
213
|
+
//# sourceMappingURL=chunk-RUSFF3MZ.js.map
|
|
214
|
+
//# sourceMappingURL=chunk-RUSFF3MZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ai/AiPromptBox.tsx","../src/ai/StreamingResponse.tsx"],"names":["useState","jsxs","jsx"],"mappings":"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","file":"chunk-RUSFF3MZ.js","sourcesContent":["import {\r\n useState,\r\n} from \"react\";\r\n\r\nimport type {\r\n FormEvent,\r\n HTMLAttributes,\r\n} from \"react\";\r\n\r\nimport {\r\n ArrowUp,\r\n Paperclip,\r\n Sparkles,\r\n} from \"lucide-react\";\r\n\r\nimport \"./AiPromptBox.css\";\r\n\r\nexport interface AiPromptBoxProps\r\n extends Omit<\r\n HTMLAttributes<HTMLDivElement>,\r\n \"onSubmit\"\r\n > {\r\n background?: string;\r\n\r\n accent?: string;\r\n\r\n textColor?: string;\r\n\r\n radius?: number;\r\n\r\n minHeight?: number;\r\n\r\n showModel?: boolean;\r\n\r\n showAttachment?: boolean;\r\n\r\n modelLabel?: string;\r\n\r\n placeholder?: string;\r\n\r\n defaultValue?: string;\r\n\r\n disabled?: boolean;\r\n\r\n onSubmit?: (\r\n value: string\r\n ) => void;\r\n\r\n className?: string;\r\n}\r\n\r\nexport function AiPromptBox({\r\n background = \"#111116\",\r\n\r\n accent = \"#9b7cff\",\r\n\r\n textColor = \"#ffffff\",\r\n\r\n radius = 20,\r\n\r\n minHeight = 150,\r\n\r\n showModel = true,\r\n\r\n showAttachment = true,\r\n\r\n modelLabel = \"FB AI · Fast\",\r\n\r\n placeholder =\r\n \"Ask anything...\",\r\n\r\n defaultValue = \"\",\r\n\r\n disabled = false,\r\n\r\n onSubmit,\r\n\r\n className = \"\",\r\n\r\n style,\r\n\r\n ...props\r\n}: AiPromptBoxProps) {\r\n const [\r\n value,\r\n setValue,\r\n ] =\r\n useState(\r\n defaultValue\r\n );\r\n\r\n function handleSubmit(\r\n event:\r\n FormEvent<HTMLFormElement>\r\n ) {\r\n event.preventDefault();\r\n\r\n const trimmed =\r\n value.trim();\r\n\r\n if (\r\n disabled ||\r\n !trimmed\r\n ) {\r\n return;\r\n }\r\n\r\n onSubmit?.(\r\n trimmed\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n {...props}\r\n className={`fb-ai-prompt-box ${className}`}\r\n style={{\r\n ...style,\r\n\r\n background,\r\n\r\n color:\r\n textColor,\r\n\r\n borderRadius:\r\n radius,\r\n\r\n minHeight,\r\n\r\n [\"--fb-ai-prompt-accent\" as string]:\r\n accent,\r\n }}\r\n >\r\n <form\r\n className=\"fb-ai-prompt-box__form\"\r\n onSubmit={\r\n handleSubmit\r\n }\r\n >\r\n <div className=\"fb-ai-prompt-box__field\">\r\n <Sparkles\r\n className=\"fb-ai-prompt-box__spark\"\r\n size={16}\r\n aria-hidden=\"true\"\r\n />\r\n\r\n <textarea\r\n value={\r\n value\r\n }\r\n disabled={\r\n disabled\r\n }\r\n placeholder={\r\n placeholder\r\n }\r\n aria-label={\r\n placeholder\r\n }\r\n onChange={(\r\n event\r\n ) =>\r\n setValue(\r\n event.target\r\n .value\r\n )\r\n }\r\n />\r\n </div>\r\n\r\n <div className=\"fb-ai-prompt-box__footer\">\r\n <div className=\"fb-ai-prompt-box__actions\">\r\n {showAttachment && (\r\n <button\r\n type=\"button\"\r\n aria-label=\"Attach file\"\r\n className=\"fb-ai-prompt-box__secondary\"\r\n >\r\n <Paperclip\r\n size={15}\r\n aria-hidden=\"true\"\r\n />\r\n </button>\r\n )}\r\n\r\n {showModel && (\r\n <span className=\"fb-ai-prompt-box__model\">\r\n {\r\n modelLabel\r\n }\r\n </span>\r\n )}\r\n </div>\r\n\r\n <button\r\n type=\"submit\"\r\n disabled={\r\n disabled ||\r\n !value.trim()\r\n }\r\n className=\"fb-ai-prompt-box__submit\"\r\n aria-label=\"Submit prompt\"\r\n >\r\n <ArrowUp\r\n size={16}\r\n aria-hidden=\"true\"\r\n />\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n );\r\n}","import {\r\n useEffect,\r\n useState,\r\n} from \"react\";\r\n\r\nimport type {\r\n HTMLAttributes,\r\n} from \"react\";\r\n\r\nimport \"./StreamingResponse.css\";\r\n\r\nexport interface StreamingResponseProps\r\n extends HTMLAttributes<HTMLDivElement> {\r\n text?: string;\r\n\r\n accent?: string;\r\n textColor?: string;\r\n\r\n speed?: number;\r\n\r\n showCursor?: boolean;\r\n showStatus?: boolean;\r\n\r\n statusLabel?: string;\r\n\r\n className?: string;\r\n}\r\n\r\nexport function StreamingResponse({\r\n text =\r\n \"FB Components gives your application a reusable system for motion, interaction and AI-native interfaces.\",\r\n\r\n accent = \"#9b7cff\",\r\n textColor = \"#ffffff\",\r\n\r\n speed = 24,\r\n\r\n showCursor = true,\r\n showStatus = true,\r\n\r\n statusLabel =\r\n \"GENERATING\",\r\n\r\n className = \"\",\r\n style,\r\n\r\n ...props\r\n}: StreamingResponseProps) {\r\n const [\r\n length,\r\n setLength,\r\n ] =\r\n useState(0);\r\n\r\n useEffect(() => {\r\n setLength(\r\n 0\r\n );\r\n\r\n if (\r\n text.length ===\r\n 0\r\n ) {\r\n return;\r\n }\r\n\r\n const interval =\r\n window.setInterval(\r\n () => {\r\n setLength(\r\n (\r\n current\r\n ) => {\r\n if (\r\n current >=\r\n text.length\r\n ) {\r\n window.clearInterval(\r\n interval\r\n );\r\n\r\n return current;\r\n }\r\n\r\n return (\r\n current +\r\n 1\r\n );\r\n }\r\n );\r\n },\r\n Math.max(\r\n 5,\r\n speed\r\n )\r\n );\r\n\r\n return () =>\r\n window.clearInterval(\r\n interval\r\n );\r\n }, [\r\n text,\r\n speed,\r\n ]);\r\n\r\n const complete =\r\n length >=\r\n text.length;\r\n\r\n return (\r\n <div\r\n {...props}\r\n className={`fb-streaming-response ${className}`}\r\n style={{\r\n ...style,\r\n\r\n color:\r\n textColor,\r\n\r\n [\"--fb-streaming-accent\" as string]:\r\n accent,\r\n }}\r\n aria-live=\"polite\"\r\n >\r\n {showStatus && (\r\n <div className=\"fb-streaming-response__status\">\r\n <span\r\n className={\r\n complete\r\n ? \"is-complete\"\r\n : \"\"\r\n }\r\n aria-hidden=\"true\"\r\n />\r\n\r\n {complete\r\n ? \"COMPLETE\"\r\n : statusLabel}\r\n </div>\r\n )}\r\n\r\n <p>\r\n {text.slice(\r\n 0,\r\n length\r\n )}\r\n\r\n {showCursor &&\r\n !complete && (\r\n <span\r\n className=\"fb-streaming-response__cursor\"\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n </p>\r\n </div>\r\n );\r\n}"]}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { useState, useRef, useEffect } from 'react';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
// src/motion/GlowCursor.tsx
|
|
5
|
+
function GlowCursor({
|
|
6
|
+
children,
|
|
7
|
+
color = "#825dff",
|
|
8
|
+
size = 110,
|
|
9
|
+
blur = 35,
|
|
10
|
+
opacity = 0.45,
|
|
11
|
+
followSpeed = 0.12,
|
|
12
|
+
className = ""
|
|
13
|
+
}) {
|
|
14
|
+
const [
|
|
15
|
+
point,
|
|
16
|
+
setPoint
|
|
17
|
+
] = useState({
|
|
18
|
+
x: 0,
|
|
19
|
+
y: 0
|
|
20
|
+
});
|
|
21
|
+
return /* @__PURE__ */ jsxs(
|
|
22
|
+
"div",
|
|
23
|
+
{
|
|
24
|
+
className: `fb-glow-cursor ${className}`,
|
|
25
|
+
onMouseMove: (event) => {
|
|
26
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
27
|
+
setPoint({
|
|
28
|
+
x: event.clientX - rect.left,
|
|
29
|
+
y: event.clientY - rect.top
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ jsx(
|
|
34
|
+
"div",
|
|
35
|
+
{
|
|
36
|
+
className: "fb-glow-cursor__glow",
|
|
37
|
+
style: {
|
|
38
|
+
width: size,
|
|
39
|
+
height: size,
|
|
40
|
+
left: point.x,
|
|
41
|
+
top: point.y,
|
|
42
|
+
background: color,
|
|
43
|
+
filter: `blur(${blur}px)`,
|
|
44
|
+
opacity,
|
|
45
|
+
transitionDuration: `${followSpeed}s`
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
/* @__PURE__ */ jsx("div", { className: "fb-glow-cursor__content", children })
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
function MagneticCursor({
|
|
55
|
+
children,
|
|
56
|
+
color = "#b99cff",
|
|
57
|
+
size = 18,
|
|
58
|
+
ringSize = 44,
|
|
59
|
+
followSpeed = 0.14,
|
|
60
|
+
magneticStrength = 0.25,
|
|
61
|
+
className = "",
|
|
62
|
+
style,
|
|
63
|
+
...props
|
|
64
|
+
}) {
|
|
65
|
+
const containerRef = useRef(
|
|
66
|
+
null
|
|
67
|
+
);
|
|
68
|
+
const [
|
|
69
|
+
point,
|
|
70
|
+
setPoint
|
|
71
|
+
] = useState({
|
|
72
|
+
x: 0,
|
|
73
|
+
y: 0
|
|
74
|
+
});
|
|
75
|
+
const [
|
|
76
|
+
visible,
|
|
77
|
+
setVisible
|
|
78
|
+
] = useState(false);
|
|
79
|
+
const [
|
|
80
|
+
hoveringTarget,
|
|
81
|
+
setHoveringTarget
|
|
82
|
+
] = useState(false);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
const element = containerRef.current;
|
|
85
|
+
if (!element) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
function handlePointerMove(event) {
|
|
89
|
+
const rect = element.getBoundingClientRect();
|
|
90
|
+
let x = event.clientX - rect.left;
|
|
91
|
+
let y = event.clientY - rect.top;
|
|
92
|
+
const target = event.target?.closest(
|
|
93
|
+
"[data-magnetic-target]"
|
|
94
|
+
);
|
|
95
|
+
if (target) {
|
|
96
|
+
const targetRect = target.getBoundingClientRect();
|
|
97
|
+
const centerX = targetRect.left + targetRect.width / 2;
|
|
98
|
+
const centerY = targetRect.top + targetRect.height / 2;
|
|
99
|
+
x += (centerX - event.clientX) * magneticStrength;
|
|
100
|
+
y += (centerY - event.clientY) * magneticStrength;
|
|
101
|
+
setHoveringTarget(
|
|
102
|
+
true
|
|
103
|
+
);
|
|
104
|
+
} else {
|
|
105
|
+
setHoveringTarget(
|
|
106
|
+
false
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
setPoint({
|
|
110
|
+
x,
|
|
111
|
+
y
|
|
112
|
+
});
|
|
113
|
+
setVisible(
|
|
114
|
+
true
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
function handlePointerLeave() {
|
|
118
|
+
setVisible(
|
|
119
|
+
false
|
|
120
|
+
);
|
|
121
|
+
setHoveringTarget(
|
|
122
|
+
false
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
element.addEventListener(
|
|
126
|
+
"pointermove",
|
|
127
|
+
handlePointerMove
|
|
128
|
+
);
|
|
129
|
+
element.addEventListener(
|
|
130
|
+
"pointerleave",
|
|
131
|
+
handlePointerLeave
|
|
132
|
+
);
|
|
133
|
+
return () => {
|
|
134
|
+
element.removeEventListener(
|
|
135
|
+
"pointermove",
|
|
136
|
+
handlePointerMove
|
|
137
|
+
);
|
|
138
|
+
element.removeEventListener(
|
|
139
|
+
"pointerleave",
|
|
140
|
+
handlePointerLeave
|
|
141
|
+
);
|
|
142
|
+
};
|
|
143
|
+
}, [
|
|
144
|
+
magneticStrength
|
|
145
|
+
]);
|
|
146
|
+
return /* @__PURE__ */ jsxs(
|
|
147
|
+
"div",
|
|
148
|
+
{
|
|
149
|
+
...props,
|
|
150
|
+
ref: containerRef,
|
|
151
|
+
className: `fb-magnetic-cursor ${className}`,
|
|
152
|
+
style: {
|
|
153
|
+
...style,
|
|
154
|
+
cursor: "none"
|
|
155
|
+
},
|
|
156
|
+
children: [
|
|
157
|
+
/* @__PURE__ */ jsx("div", { className: "fb-magnetic-cursor__content", children }),
|
|
158
|
+
/* @__PURE__ */ jsx(
|
|
159
|
+
"span",
|
|
160
|
+
{
|
|
161
|
+
"aria-hidden": "true",
|
|
162
|
+
className: `fb-magnetic-cursor__ring ${visible ? "is-visible" : ""} ${hoveringTarget ? "is-targeting" : ""}`,
|
|
163
|
+
style: {
|
|
164
|
+
width: ringSize,
|
|
165
|
+
height: ringSize,
|
|
166
|
+
left: point.x,
|
|
167
|
+
top: point.y,
|
|
168
|
+
borderColor: color,
|
|
169
|
+
transitionDuration: `${followSpeed}s`
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
),
|
|
173
|
+
/* @__PURE__ */ jsx(
|
|
174
|
+
"span",
|
|
175
|
+
{
|
|
176
|
+
"aria-hidden": "true",
|
|
177
|
+
className: `fb-magnetic-cursor__dot ${visible ? "is-visible" : ""}`,
|
|
178
|
+
style: {
|
|
179
|
+
width: size,
|
|
180
|
+
height: size,
|
|
181
|
+
left: point.x,
|
|
182
|
+
top: point.y,
|
|
183
|
+
background: color,
|
|
184
|
+
boxShadow: `0 0 ${size}px ${color}`
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
]
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export { GlowCursor, MagneticCursor };
|
|
194
|
+
//# sourceMappingURL=chunk-T7CC3CLH.js.map
|
|
195
|
+
//# sourceMappingURL=chunk-T7CC3CLH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/motion/GlowCursor.tsx","../src/motion/MagneticCursor.tsx"],"names":["useState","jsxs","jsx"],"mappings":"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","file":"chunk-T7CC3CLH.js","sourcesContent":["import {\r\n useState,\r\n} from \"react\";\r\n\r\nimport \"./GlowCursor.css\";\r\n\r\nexport interface GlowCursorProps {\r\n children?:\r\n React.ReactNode;\r\n\r\n color?:\r\n string;\r\n\r\n size?:\r\n number;\r\n\r\n blur?:\r\n number;\r\n\r\n opacity?:\r\n number;\r\n\r\n followSpeed?:\r\n number;\r\n\r\n className?:\r\n string;\r\n}\r\n\r\nexport function GlowCursor({\r\n children,\r\n\r\n color =\r\n \"#825dff\",\r\n\r\n size =\r\n 110,\r\n\r\n blur =\r\n 35,\r\n\r\n opacity =\r\n 0.45,\r\n\r\n followSpeed =\r\n 0.12,\r\n\r\n className =\r\n \"\",\r\n}: GlowCursorProps) {\r\n const [\r\n point,\r\n setPoint,\r\n ] =\r\n useState({\r\n x: 0,\r\n y: 0,\r\n });\r\n\r\n return (\r\n <div\r\n className={`fb-glow-cursor ${className}`}\r\n onMouseMove={(\r\n event\r\n ) => {\r\n const rect =\r\n event.currentTarget.getBoundingClientRect();\r\n\r\n setPoint({\r\n x:\r\n event.clientX -\r\n rect.left,\r\n\r\n y:\r\n event.clientY -\r\n rect.top,\r\n });\r\n }}\r\n >\r\n <div\r\n className=\"fb-glow-cursor__glow\"\r\n style={{\r\n width:\r\n size,\r\n\r\n height:\r\n size,\r\n\r\n left:\r\n point.x,\r\n\r\n top:\r\n point.y,\r\n\r\n background:\r\n color,\r\n\r\n filter:\r\n `blur(${blur}px)`,\r\n\r\n opacity,\r\n\r\n transitionDuration:\r\n `${followSpeed}s`,\r\n }}\r\n />\r\n\r\n <div className=\"fb-glow-cursor__content\">\r\n {children}\r\n </div>\r\n </div>\r\n );\r\n}","import {\r\n useEffect,\r\n useRef,\r\n useState,\r\n} from \"react\";\r\n\r\nimport type {\r\n HTMLAttributes,\r\n ReactNode,\r\n} from \"react\";\r\n\r\nimport \"./MagneticCursor.css\";\r\n\r\nexport interface MagneticCursorProps\r\n extends HTMLAttributes<HTMLDivElement> {\r\n children?: ReactNode;\r\n\r\n color?: string;\r\n\r\n size?: number;\r\n\r\n ringSize?: number;\r\n\r\n followSpeed?: number;\r\n\r\n magneticStrength?: number;\r\n\r\n className?: string;\r\n}\r\n\r\ninterface Point {\r\n x: number;\r\n y: number;\r\n}\r\n\r\nexport function MagneticCursor({\r\n children,\r\n\r\n color = \"#b99cff\",\r\n\r\n size = 18,\r\n\r\n ringSize = 44,\r\n\r\n followSpeed = 0.14,\r\n\r\n magneticStrength = 0.25,\r\n\r\n className = \"\",\r\n\r\n style,\r\n\r\n ...props\r\n}: MagneticCursorProps) {\r\n const containerRef =\r\n useRef<HTMLDivElement>(\r\n null\r\n );\r\n\r\n const [\r\n point,\r\n setPoint,\r\n ] =\r\n useState<Point>({\r\n x: 0,\r\n y: 0,\r\n });\r\n\r\n const [\r\n visible,\r\n setVisible,\r\n ] =\r\n useState(false);\r\n\r\n const [\r\n hoveringTarget,\r\n setHoveringTarget,\r\n ] =\r\n useState(false);\r\n\r\n useEffect(() => {\r\n const element =\r\n containerRef.current;\r\n\r\n if (!element) {\r\n return;\r\n }\r\n\r\n function handlePointerMove(\r\n event: PointerEvent\r\n ) {\r\n const rect =\r\n element!.getBoundingClientRect();\r\n\r\n let x =\r\n event.clientX -\r\n rect.left;\r\n\r\n let y =\r\n event.clientY -\r\n rect.top;\r\n\r\n const target =\r\n (\r\n event.target as\r\n HTMLElement | null\r\n )?.closest(\r\n \"[data-magnetic-target]\"\r\n ) as\r\n | HTMLElement\r\n | null;\r\n\r\n if (target) {\r\n const targetRect =\r\n target.getBoundingClientRect();\r\n\r\n const centerX =\r\n targetRect.left +\r\n targetRect.width /\r\n 2;\r\n\r\n const centerY =\r\n targetRect.top +\r\n targetRect.height /\r\n 2;\r\n\r\n x +=\r\n (\r\n centerX -\r\n event.clientX\r\n ) *\r\n magneticStrength;\r\n\r\n y +=\r\n (\r\n centerY -\r\n event.clientY\r\n ) *\r\n magneticStrength;\r\n\r\n setHoveringTarget(\r\n true\r\n );\r\n } else {\r\n setHoveringTarget(\r\n false\r\n );\r\n }\r\n\r\n setPoint({\r\n x,\r\n y,\r\n });\r\n\r\n setVisible(\r\n true\r\n );\r\n }\r\n\r\n function handlePointerLeave() {\r\n setVisible(\r\n false\r\n );\r\n\r\n setHoveringTarget(\r\n false\r\n );\r\n }\r\n\r\n element.addEventListener(\r\n \"pointermove\",\r\n handlePointerMove\r\n );\r\n\r\n element.addEventListener(\r\n \"pointerleave\",\r\n handlePointerLeave\r\n );\r\n\r\n return () => {\r\n element.removeEventListener(\r\n \"pointermove\",\r\n handlePointerMove\r\n );\r\n\r\n element.removeEventListener(\r\n \"pointerleave\",\r\n handlePointerLeave\r\n );\r\n };\r\n }, [\r\n magneticStrength,\r\n ]);\r\n\r\n return (\r\n <div\r\n {...props}\r\n ref={\r\n containerRef\r\n }\r\n className={`fb-magnetic-cursor ${className}`}\r\n style={{\r\n ...style,\r\n\r\n cursor:\r\n \"none\",\r\n }}\r\n >\r\n <div className=\"fb-magnetic-cursor__content\">\r\n {children}\r\n </div>\r\n\r\n <span\r\n aria-hidden=\"true\"\r\n className={`fb-magnetic-cursor__ring ${\r\n visible\r\n ? \"is-visible\"\r\n : \"\"\r\n } ${\r\n hoveringTarget\r\n ? \"is-targeting\"\r\n : \"\"\r\n }`}\r\n style={{\r\n width:\r\n ringSize,\r\n\r\n height:\r\n ringSize,\r\n\r\n left:\r\n point.x,\r\n\r\n top:\r\n point.y,\r\n\r\n borderColor:\r\n color,\r\n\r\n transitionDuration:\r\n `${followSpeed}s`,\r\n }}\r\n />\r\n\r\n <span\r\n aria-hidden=\"true\"\r\n className={`fb-magnetic-cursor__dot ${\r\n visible\r\n ? \"is-visible\"\r\n : \"\"\r\n }`}\r\n style={{\r\n width:\r\n size,\r\n\r\n height:\r\n size,\r\n\r\n left:\r\n point.x,\r\n\r\n top:\r\n point.y,\r\n\r\n background:\r\n color,\r\n\r\n boxShadow:\r\n `0 0 ${size}px ${color}`,\r\n }}\r\n />\r\n </div>\r\n );\r\n}"]}
|