@webenza/ui 0.0.2 → 0.0.4

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 CHANGED
@@ -5,21 +5,59 @@ Internal UI and animation components for Webenza.
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @webenza/ui react react-dom gsap
8
+ npm install @webenza/ui
9
+ ```
10
+
11
+ ## Peer Dependencies
12
+
13
+ @webenza/ui does not bundle external animation or rendering libraries.
14
+ Install only the dependencies required for the components you use.
15
+
16
+ > **Note:** Peer dependencies are **not** installed automatically with the library.
17
+
18
+ ### Core (Required)
19
+ ```bash
20
+ npm install react react-dom
21
+ ```
22
+
23
+ ### Motion Components
24
+ If you use components like `HoverFillButton`, `CircularText`, or `ImageTrail`:
25
+ ```bash
26
+ npm install framer-motion
27
+ ```
28
+
29
+ ### GSAP Components
30
+ If you use components like `CursorFollower`:
31
+ ```bash
32
+ npm install gsap
33
+ ```
34
+
35
+ ### Icon / Button Components
36
+ If you use components like `HoverFillButton`:
37
+ ```bash
38
+ npm install react-icons
39
+ ```
40
+
41
+ ### 3D Components
42
+ If you use components like `WaterRipple`:
43
+ ```bash
44
+ npm install three @react-three/fiber
9
45
  ```
10
46
 
11
47
  ## Usage
12
48
 
49
+ Most components are designed to work out of the box with sensible defaults.
50
+
13
51
  ```tsx
14
- import { CursorFollower } from '@webenza/ui';
52
+ import { CursorFollower } from "@webenza/ui";
15
53
 
16
- function App() {
54
+ export default function App() {
17
55
  return (
18
- <CursorFollower />
56
+ <CursorFollower />
19
57
  );
20
58
  }
21
59
  ```
22
60
 
23
- ## Components
24
-
25
- - **CursorFollower**: A custom cursor follower with magnetic and scaling effects.
61
+ - **Works out of the box**
62
+ - **Sensible defaults** included
63
+ - **Optional customization** via props
package/dist/index.d.mts CHANGED
@@ -1,4 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+ import { HTMLMotionProps } from 'framer-motion';
2
4
 
3
5
  type CursorFollowerProps = {
4
6
  text?: string;
@@ -19,4 +21,50 @@ type CursorFollowerProps = {
19
21
  };
20
22
  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
23
 
22
- export { CursorFollower, type CursorFollowerProps };
24
+ interface ImageTrailProps {
25
+ images?: string[];
26
+ size?: number;
27
+ rotationRange?: number;
28
+ interval?: number;
29
+ fadeDuration?: number;
30
+ className?: string;
31
+ }
32
+ declare const ImageTrail: React$1.FC<ImageTrailProps>;
33
+
34
+ interface HoverFillButtonProps extends HTMLMotionProps<"button"> {
35
+ label?: string;
36
+ direction?: 'left' | 'right' | 'top' | 'bottom';
37
+ fillColor?: string;
38
+ textColor?: string;
39
+ hoverTextColor?: string;
40
+ padding?: string;
41
+ paddingHorizontal?: string;
42
+ paddingVertical?: string;
43
+ borderRadius?: string;
44
+ backgroundColor?: string;
45
+ borderColor?: string;
46
+ }
47
+ declare const HoverFillButton: React$1.FC<HoverFillButtonProps>;
48
+
49
+ interface ImageMarqueeProps {
50
+ images?: string[];
51
+ direction?: 'left' | 'right';
52
+ speed?: number;
53
+ gap?: string;
54
+ size?: number;
55
+ className?: string;
56
+ }
57
+ declare const ImageMarquee: React$1.FC<ImageMarqueeProps>;
58
+
59
+ interface CircularTextProps {
60
+ text?: string;
61
+ radius?: number;
62
+ fontSize?: string;
63
+ iconSize?: number;
64
+ color?: string;
65
+ spinDuration?: number;
66
+ className?: string;
67
+ }
68
+ declare const CircularText: React$1.FC<CircularTextProps>;
69
+
70
+ export { CircularText, type CircularTextProps, CursorFollower, type CursorFollowerProps, HoverFillButton, type HoverFillButtonProps, ImageMarquee, type ImageMarqueeProps, ImageTrail, type ImageTrailProps };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+ import { HTMLMotionProps } from 'framer-motion';
2
4
 
3
5
  type CursorFollowerProps = {
4
6
  text?: string;
@@ -19,4 +21,50 @@ type CursorFollowerProps = {
19
21
  };
20
22
  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
23
 
22
- export { CursorFollower, type CursorFollowerProps };
24
+ interface ImageTrailProps {
25
+ images?: string[];
26
+ size?: number;
27
+ rotationRange?: number;
28
+ interval?: number;
29
+ fadeDuration?: number;
30
+ className?: string;
31
+ }
32
+ declare const ImageTrail: React$1.FC<ImageTrailProps>;
33
+
34
+ interface HoverFillButtonProps extends HTMLMotionProps<"button"> {
35
+ label?: string;
36
+ direction?: 'left' | 'right' | 'top' | 'bottom';
37
+ fillColor?: string;
38
+ textColor?: string;
39
+ hoverTextColor?: string;
40
+ padding?: string;
41
+ paddingHorizontal?: string;
42
+ paddingVertical?: string;
43
+ borderRadius?: string;
44
+ backgroundColor?: string;
45
+ borderColor?: string;
46
+ }
47
+ declare const HoverFillButton: React$1.FC<HoverFillButtonProps>;
48
+
49
+ interface ImageMarqueeProps {
50
+ images?: string[];
51
+ direction?: 'left' | 'right';
52
+ speed?: number;
53
+ gap?: string;
54
+ size?: number;
55
+ className?: string;
56
+ }
57
+ declare const ImageMarquee: React$1.FC<ImageMarqueeProps>;
58
+
59
+ interface CircularTextProps {
60
+ text?: string;
61
+ radius?: number;
62
+ fontSize?: string;
63
+ iconSize?: number;
64
+ color?: string;
65
+ spinDuration?: number;
66
+ className?: string;
67
+ }
68
+ declare const CircularText: React$1.FC<CircularTextProps>;
69
+
70
+ export { CircularText, type CircularTextProps, CursorFollower, type CursorFollowerProps, HoverFillButton, type HoverFillButtonProps, ImageMarquee, type ImageMarqueeProps, ImageTrail, type ImageTrailProps };
package/dist/index.js CHANGED
@@ -3,6 +3,9 @@
3
3
  var react = require('react');
4
4
  var gsap = require('gsap');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
+ var framerMotion = require('framer-motion');
7
+ var fi = require('react-icons/fi');
8
+ var lu = require('react-icons/lu');
6
9
 
7
10
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
11
 
@@ -10,11 +13,10 @@ var gsap__default = /*#__PURE__*/_interopDefault(gsap);
10
13
 
11
14
  // src/cursor/CursorFollower/CursorFollower.tsx
12
15
  var CursorFollower = ({
13
- text = "",
14
- // Changed from "PLAY" to empty string for generic usage
16
+ text = "PLAY",
15
17
  size = 90,
16
18
  borderWidth = 2,
17
- borderColor = "#fff",
19
+ borderColor = "#ffffff",
18
20
  background = "transparent",
19
21
  fontFamily = "inherit",
20
22
  fontSize = 12,
@@ -25,11 +27,10 @@ var CursorFollower = ({
25
27
  hideScale = 0,
26
28
  enabled = true,
27
29
  blockSelectors = ["button", "a"],
28
- // Added sensible defaults
29
30
  containerRef
30
31
  }) => {
31
32
  const cursorRef = react.useRef(null);
32
- react.useEffect(() => {
33
+ react.useLayoutEffect(() => {
33
34
  if (!enabled) return;
34
35
  const cursor = cursorRef.current;
35
36
  if (!cursor) return;
@@ -58,6 +59,9 @@ var CursorFollower = ({
58
59
  targetX = e.clientX;
59
60
  targetY = e.clientY;
60
61
  }
62
+ if (!visible && !blocked) {
63
+ show();
64
+ }
61
65
  };
62
66
  const update = () => {
63
67
  currentX += (targetX - currentX) * lerp;
@@ -72,6 +76,23 @@ var CursorFollower = ({
72
76
  target.addEventListener("mouseenter", show);
73
77
  target.addEventListener("mouseleave", hide);
74
78
  gsap__default.default.ticker.add(update);
79
+ requestAnimationFrame(() => {
80
+ if (containerRef?.current) {
81
+ const bounds = containerRef.current.getBoundingClientRect();
82
+ targetX = bounds.width / 2;
83
+ targetY = bounds.height / 2;
84
+ } else {
85
+ targetX = window.innerWidth / 2;
86
+ targetY = window.innerHeight / 2;
87
+ }
88
+ currentX = targetX;
89
+ currentY = targetY;
90
+ gsap__default.default.set(cursor, {
91
+ x: currentX - size / 2,
92
+ y: currentY - size / 2
93
+ });
94
+ show();
95
+ });
75
96
  const cleanupFns = [];
76
97
  blockSelectors.forEach((selector) => {
77
98
  const elements = document.querySelectorAll(selector);
@@ -105,7 +126,8 @@ var CursorFollower = ({
105
126
  lerp,
106
127
  showScale,
107
128
  hideScale,
108
- blockSelectors,
129
+ // Stabilize dependency: only re-run if the joined string changes
130
+ blockSelectors.join(","),
109
131
  containerRef
110
132
  ]);
111
133
  if (!enabled) return null;
@@ -140,7 +162,396 @@ var CursorFollower = ({
140
162
  }
141
163
  );
142
164
  };
165
+ var defaultImages = [
166
+ "https://picsum.photos/id/237/200/200",
167
+ "https://picsum.photos/id/10/200/200",
168
+ "https://picsum.photos/id/20/200/200",
169
+ "https://picsum.photos/id/28/200/200",
170
+ "https://picsum.photos/id/29/200/200",
171
+ "https://picsum.photos/id/35/200/200",
172
+ "https://picsum.photos/id/40/200/200",
173
+ "https://picsum.photos/id/55/200/200",
174
+ "https://picsum.photos/id/60/200/200",
175
+ "https://picsum.photos/id/70/200/200"
176
+ ];
177
+ var ImageTrail = ({
178
+ images = defaultImages,
179
+ size = 100,
180
+ rotationRange = 15,
181
+ interval = 30,
182
+ // Default to fairly dense for smooth "train" effect
183
+ fadeDuration = 0.5,
184
+ className
185
+ }) => {
186
+ const [trail, setTrail] = react.useState([]);
187
+ const lastPosRef = react.useRef(null);
188
+ const indexRef = react.useRef(0);
189
+ const idCounterRef = react.useRef(0);
190
+ const containerRef = react.useRef(null);
191
+ react.useEffect(() => {
192
+ const cleanupInterval = setInterval(() => {
193
+ setTrail((prev) => {
194
+ return prev.filter((item) => Date.now() - item.created < fadeDuration * 1e3);
195
+ });
196
+ }, 100);
197
+ return () => clearInterval(cleanupInterval);
198
+ }, [fadeDuration]);
199
+ const handleMouseMove = (e) => {
200
+ if (!containerRef.current) return;
201
+ const rect = containerRef.current.getBoundingClientRect();
202
+ const x = e.clientX - rect.left;
203
+ const y = e.clientY - rect.top;
204
+ const currentPos = { x, y };
205
+ if (!lastPosRef.current) {
206
+ lastPosRef.current = currentPos;
207
+ return;
208
+ }
209
+ const dx = currentPos.x - lastPosRef.current.x;
210
+ const dy = currentPos.y - lastPosRef.current.y;
211
+ const distance = Math.sqrt(dx * dx + dy * dy);
212
+ if (distance > interval) {
213
+ const newImage = {
214
+ id: idCounterRef.current++,
215
+ created: Date.now(),
216
+ src: images[indexRef.current % images.length] || "",
217
+ x: currentPos.x,
218
+ y: currentPos.y,
219
+ rotation: Math.random() * (rotationRange * 2) - rotationRange
220
+ };
221
+ setTrail((prev) => [...prev, newImage]);
222
+ lastPosRef.current = currentPos;
223
+ indexRef.current++;
224
+ }
225
+ };
226
+ const handleMouseLeave = () => {
227
+ lastPosRef.current = null;
228
+ };
229
+ return /* @__PURE__ */ jsxRuntime.jsxs(
230
+ "div",
231
+ {
232
+ ref: containerRef,
233
+ className,
234
+ onMouseMove: handleMouseMove,
235
+ onMouseLeave: handleMouseLeave,
236
+ style: {
237
+ position: "relative",
238
+ width: "100%",
239
+ height: "100%",
240
+ minHeight: "400px",
241
+ overflow: "hidden",
242
+ background: "#111",
243
+ cursor: "none",
244
+ borderRadius: "12px"
245
+ },
246
+ children: [
247
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
248
+ pointerEvents: "none",
249
+ position: "absolute",
250
+ top: 0,
251
+ left: 0,
252
+ width: "100%",
253
+ height: "100%"
254
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "popLayout", children: trail.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
255
+ framerMotion.motion.img,
256
+ {
257
+ src: item.src,
258
+ initial: {
259
+ opacity: 0,
260
+ scale: 0.8,
261
+ x: item.x - size / 2,
262
+ y: item.y - size / 2,
263
+ rotate: item.rotation
264
+ },
265
+ animate: {
266
+ opacity: 1,
267
+ scale: 1,
268
+ x: item.x - size / 2,
269
+ y: item.y - size / 2
270
+ },
271
+ exit: {
272
+ opacity: 0,
273
+ scale: 0.5,
274
+ transition: { duration: fadeDuration }
275
+ },
276
+ transition: { duration: 0.1 },
277
+ style: {
278
+ position: "absolute",
279
+ width: size,
280
+ height: size,
281
+ objectFit: "cover",
282
+ borderRadius: "8px",
283
+ boxShadow: "0 4px 12px rgba(0,0,0,0.3)",
284
+ pointerEvents: "none",
285
+ left: 0,
286
+ top: 0
287
+ }
288
+ },
289
+ item.id
290
+ )) }) }),
291
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
292
+ position: "absolute",
293
+ top: "50%",
294
+ left: "50%",
295
+ transform: "translate(-50%, -50%)",
296
+ color: "#444",
297
+ pointerEvents: "none",
298
+ fontWeight: 500,
299
+ textAlign: "center"
300
+ }, children: "Hover to see trail" })
301
+ ]
302
+ }
303
+ );
304
+ };
305
+ var HoverFillButton = ({
306
+ label = "Hover Me",
307
+ direction = "left",
308
+ fillColor = "#e9590c",
309
+ textColor = "#ffffff",
310
+ hoverTextColor = "#ffffff",
311
+ padding = "12px 24px",
312
+ paddingHorizontal,
313
+ paddingVertical,
314
+ borderRadius = "50px",
315
+ backgroundColor = "#000000",
316
+ borderColor = "#000000",
317
+ style,
318
+ ...props
319
+ }) => {
320
+ const getInitialPosition = () => {
321
+ switch (direction) {
322
+ case "left":
323
+ return { x: "-100%", y: "0%" };
324
+ case "right":
325
+ return { x: "100%", y: "0%" };
326
+ case "top":
327
+ return { x: "0%", y: "-100%" };
328
+ case "bottom":
329
+ return { x: "0%", y: "100%" };
330
+ default:
331
+ return { x: "-100%", y: "0%" };
332
+ }
333
+ };
334
+ const finalPadding = paddingHorizontal || paddingVertical ? `${paddingVertical || "12px"} ${paddingHorizontal || "24px"}` : padding;
335
+ return /* @__PURE__ */ jsxRuntime.jsxs(
336
+ framerMotion.motion.button,
337
+ {
338
+ initial: "initial",
339
+ whileHover: "hover",
340
+ style: {
341
+ position: "relative",
342
+ padding: finalPadding,
343
+ background: backgroundColor,
344
+ border: `1px solid ${borderColor}`,
345
+ color: textColor,
346
+ borderRadius,
347
+ cursor: "pointer",
348
+ overflow: "hidden",
349
+ fontSize: "16px",
350
+ fontWeight: 500,
351
+ ...style
352
+ },
353
+ ...props,
354
+ children: [
355
+ /* @__PURE__ */ jsxRuntime.jsx(
356
+ framerMotion.motion.div,
357
+ {
358
+ variants: {
359
+ initial: getInitialPosition(),
360
+ hover: { x: "0%", y: "0%" }
361
+ },
362
+ transition: { duration: 0.3, ease: "easeInOut" },
363
+ style: {
364
+ position: "absolute",
365
+ top: 0,
366
+ left: 0,
367
+ right: 0,
368
+ bottom: 0,
369
+ background: fillColor,
370
+ zIndex: 0
371
+ }
372
+ },
373
+ direction
374
+ ),
375
+ /* @__PURE__ */ jsxRuntime.jsxs(
376
+ framerMotion.motion.span,
377
+ {
378
+ variants: {
379
+ initial: { color: textColor },
380
+ hover: { color: hoverTextColor }
381
+ },
382
+ transition: { duration: 0.2 },
383
+ style: {
384
+ position: "relative",
385
+ zIndex: 1,
386
+ display: "flex",
387
+ alignItems: "center",
388
+ gap: "12px",
389
+ lineHeight: 1
390
+ },
391
+ children: [
392
+ label,
393
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
394
+ display: "flex",
395
+ alignItems: "center",
396
+ justifyContent: "center",
397
+ width: "24px",
398
+ height: "24px",
399
+ borderRadius: "50%",
400
+ border: "2px solid currentColor",
401
+ // Increased thickness
402
+ fontSize: "16px"
403
+ // Slightly larger container for icon
404
+ }, children: /* @__PURE__ */ jsxRuntime.jsx(fi.FiArrowRight, { strokeWidth: 3 }) })
405
+ ]
406
+ }
407
+ )
408
+ ]
409
+ }
410
+ );
411
+ };
412
+ var defaultImages2 = [
413
+ "/logos/Airbnb.png",
414
+ "/logos/Amazon.png",
415
+ "/logos/Apple.png",
416
+ "/logos/Bookmyshow.png",
417
+ "/logos/FedEx.png",
418
+ "/logos/Google.png",
419
+ "/logos/Microsoft.png",
420
+ "/logos/OLA.png",
421
+ "/logos/OYO.png",
422
+ "/logos/Walmart.png"
423
+ ];
424
+ var ImageMarquee = ({
425
+ images = defaultImages2,
426
+ direction = "left",
427
+ speed = 20,
428
+ gap = "2rem",
429
+ size = 60,
430
+ className
431
+ }) => {
432
+ return /* @__PURE__ */ jsxRuntime.jsxs(
433
+ "div",
434
+ {
435
+ className,
436
+ style: {
437
+ overflow: "hidden",
438
+ whiteSpace: "nowrap",
439
+ display: "flex",
440
+ width: "100%"
441
+ },
442
+ children: [
443
+ /* @__PURE__ */ jsxRuntime.jsx(MarqueeContent, { images, direction, speed, gap, size }),
444
+ /* @__PURE__ */ jsxRuntime.jsx(MarqueeContent, { images, direction, speed, gap, size }),
445
+ /* @__PURE__ */ jsxRuntime.jsx(MarqueeContent, { images, direction, speed, gap, size }),
446
+ /* @__PURE__ */ jsxRuntime.jsx(MarqueeContent, { images, direction, speed, gap, size })
447
+ ]
448
+ }
449
+ );
450
+ };
451
+ var MarqueeContent = ({ images, direction, speed, gap, size }) => {
452
+ return /* @__PURE__ */ jsxRuntime.jsx(
453
+ framerMotion.motion.div,
454
+ {
455
+ initial: { x: direction === "left" ? "0%" : "-100%" },
456
+ animate: { x: direction === "left" ? "-100%" : "0%" },
457
+ transition: {
458
+ duration: speed,
459
+ ease: "linear",
460
+ repeat: Infinity
461
+ },
462
+ style: {
463
+ display: "flex",
464
+ gap,
465
+ minWidth: "max-content",
466
+ flexShrink: 0,
467
+ alignItems: "center",
468
+ paddingRight: gap
469
+ // Ensure spacing at the end matches the gap for seamlessness
470
+ },
471
+ children: images.map((src, index) => /* @__PURE__ */ jsxRuntime.jsx(
472
+ "img",
473
+ {
474
+ src,
475
+ alt: `marquee-item-${index}`,
476
+ style: {
477
+ height: `${size}px`,
478
+ width: "auto",
479
+ objectFit: "contain",
480
+ borderRadius: "0px"
481
+ }
482
+ },
483
+ index
484
+ ))
485
+ },
486
+ `${direction}-${speed}`
487
+ );
488
+ };
489
+ var CircularText = ({
490
+ text = "SCROLL DOWN \u2022 SCROLL DOWN \u2022 ",
491
+ radius = 50,
492
+ fontSize = "12px",
493
+ iconSize = 24,
494
+ color = "#ffffff",
495
+ spinDuration = 10,
496
+ className
497
+ }) => {
498
+ const size = radius * 2 + 40;
499
+ return /* @__PURE__ */ jsxRuntime.jsxs(
500
+ "div",
501
+ {
502
+ className,
503
+ style: {
504
+ position: "relative",
505
+ width: size,
506
+ height: size,
507
+ display: "flex",
508
+ justifyContent: "center",
509
+ alignItems: "center"
510
+ },
511
+ children: [
512
+ /* @__PURE__ */ jsxRuntime.jsx(
513
+ framerMotion.motion.div,
514
+ {
515
+ animate: { rotate: 360 },
516
+ transition: {
517
+ duration: spinDuration,
518
+ repeat: Infinity,
519
+ ease: "linear"
520
+ },
521
+ style: {
522
+ width: "100%",
523
+ height: "100%",
524
+ position: "absolute",
525
+ top: 0,
526
+ left: 0
527
+ },
528
+ children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: `0 0 ${size} ${size}`, width: "100%", height: "100%", children: [
529
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx(
530
+ "path",
531
+ {
532
+ id: "circlePath",
533
+ d: `
534
+ M ${size / 2}, ${size / 2}
535
+ m -${radius}, 0
536
+ a ${radius},${radius} 0 1,1 ${radius * 2},0
537
+ a ${radius},${radius} 0 1,1 -${radius * 2},0
538
+ `
539
+ }
540
+ ) }),
541
+ /* @__PURE__ */ jsxRuntime.jsx("text", { fill: color, fontSize, fontWeight: "bold", letterSpacing: "2px", children: /* @__PURE__ */ jsxRuntime.jsx("textPath", { href: "#circlePath", startOffset: "0%", children: text }) })
542
+ ] })
543
+ }
544
+ ),
545
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "relative", color, display: "flex" }, children: /* @__PURE__ */ jsxRuntime.jsx(lu.LuMouse, { size: iconSize }) })
546
+ ]
547
+ }
548
+ );
549
+ };
143
550
 
551
+ exports.CircularText = CircularText;
144
552
  exports.CursorFollower = CursorFollower;
553
+ exports.HoverFillButton = HoverFillButton;
554
+ exports.ImageMarquee = ImageMarquee;
555
+ exports.ImageTrail = ImageTrail;
145
556
  //# sourceMappingURL=index.js.map
146
557
  //# sourceMappingURL=index.js.map