fancy-ui-react 0.3.0 → 0.4.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.
Files changed (86) hide show
  1. package/README.md +52 -19
  2. package/dist/components/animated-beam/AnimatedBeam.d.ts +47 -11
  3. package/dist/components/animated-beam/AnimatedBeam.js +293 -118
  4. package/dist/components/animated-tooltip/AnimatedTooltip.d.ts +10 -1
  5. package/dist/components/animated-tooltip/AnimatedTooltip.js +170 -101
  6. package/dist/components/bento-grid/BentoFrame.d.ts +16 -0
  7. package/dist/components/bento-grid/BentoFrame.js +28 -0
  8. package/dist/components/bento-grid/BentoGrid.d.ts +5 -1
  9. package/dist/components/bento-grid/BentoGrid.js +71 -2
  10. package/dist/components/bento-grid/BentoGridCard.js +34 -26
  11. package/dist/components/bento-grid/BentoGridItem.js +10 -10
  12. package/dist/components/border-beam/BorderBeam.d.ts +55 -10
  13. package/dist/components/border-beam/BorderBeam.js +93 -16
  14. package/dist/components/compare/Compare.d.ts +32 -8
  15. package/dist/components/compare/Compare.js +213 -95
  16. package/dist/components/container-scroll/ContainerScroll.d.ts +26 -4
  17. package/dist/components/container-scroll/ContainerScroll.js +88 -49
  18. package/dist/components/dock/Dock.d.ts +10 -7
  19. package/dist/components/dock/Dock.js +76 -31
  20. package/dist/components/dock/DockIcon.d.ts +14 -3
  21. package/dist/components/dock/DockIcon.js +23 -19
  22. package/dist/components/dock/DockSeparator.d.ts +4 -1
  23. package/dist/components/dock/DockSeparator.js +5 -2
  24. package/dist/components/dock/types.d.ts +13 -6
  25. package/dist/components/dropdown-menu/menu-shared.d.ts +11 -8
  26. package/dist/components/editorial-engine/engine.js +1 -14
  27. package/dist/components/fireworks-hdr/webgl2-renderer.js +0 -19
  28. package/dist/components/fireworks-hdr/webgpu-renderer.js +3 -22
  29. package/dist/components/flip-card/FlipCard.d.ts +42 -1
  30. package/dist/components/flip-card/FlipCard.js +178 -25
  31. package/dist/components/flip-card/index.d.ts +1 -1
  32. package/dist/components/fluid-cursor/FluidCursor.js +5 -4
  33. package/dist/components/fluid-cursor/dev.d.ts +1 -0
  34. package/dist/components/fluid-cursor/dev.js +8 -0
  35. package/dist/components/fluid-cursor/fluid-shared.d.ts +0 -2
  36. package/dist/components/fluid-cursor/fluid-shared.js +0 -2
  37. package/dist/components/fluid-cursor/webgpu-engine.js +10 -24
  38. package/dist/components/glow-border/GlowBorder.d.ts +41 -1
  39. package/dist/components/glow-border/GlowBorder.js +96 -16
  40. package/dist/components/glow-border/index.d.ts +2 -2
  41. package/dist/components/gradient-button/GradientButton.d.ts +10 -5
  42. package/dist/components/gradient-button/GradientButton.js +25 -18
  43. package/dist/components/image-trail-cursor/ImageTrailCursor.js +1 -0
  44. package/dist/components/image-trail-cursor/trail-variants.d.ts +37 -1
  45. package/dist/components/image-trail-cursor/trail-variants.js +331 -8
  46. package/dist/components/interactive-hover-button/InteractiveHoverButton.js +30 -35
  47. package/dist/components/marquee/Marquee.d.ts +7 -3
  48. package/dist/components/marquee/Marquee.js +134 -2
  49. package/dist/components/marquee/ReviewCard.d.ts +2 -1
  50. package/dist/components/marquee/ReviewCard.js +20 -9
  51. package/dist/components/meteors/Meteors.d.ts +32 -10
  52. package/dist/components/meteors/Meteors.js +53 -20
  53. package/dist/components/mosaic-glow/mosaic-glow-core.d.ts +98 -10
  54. package/dist/components/neon-border/NeonBorder.d.ts +24 -5
  55. package/dist/components/neon-border/NeonBorder.js +37 -7
  56. package/dist/components/pagination/Pagination.js +220 -82
  57. package/dist/components/rainbow-button/RainbowButton.js +13 -5
  58. package/dist/components/ripple-button/RippleButton.d.ts +20 -1
  59. package/dist/components/ripple-button/RippleButton.js +44 -21
  60. package/dist/components/shimmer-button/ShimmerButton.d.ts +5 -5
  61. package/dist/components/shimmer-button/ShimmerButton.js +17 -19
  62. package/dist/components/smooth-cursor/SmoothCursor.d.ts +13 -9
  63. package/dist/components/smooth-cursor/SmoothCursor.js +114 -163
  64. package/dist/components/smooth-cursor/smooth-cursor-core.d.ts +85 -0
  65. package/dist/components/smooth-cursor/smooth-cursor-core.js +327 -0
  66. package/dist/components/stepper/Step.js +32 -19
  67. package/dist/components/stepper/Stepper.js +18 -2
  68. package/dist/components/stepper/types.d.ts +13 -0
  69. package/dist/components/timeline/Timeline.d.ts +8 -1
  70. package/dist/components/timeline/Timeline.js +165 -76
  71. package/dist/index.js +2 -1
  72. package/dist/internals/markdown.d.ts +5 -0
  73. package/dist/internals/motion/haptics.d.ts +0 -4
  74. package/dist/internals/motion/presence-core.d.ts +59 -0
  75. package/dist/internals/motion/presence-core.js +162 -0
  76. package/dist/internals/motion/presence.d.ts +2 -4
  77. package/dist/internals/motion/presence.js +1 -156
  78. package/dist/internals/motion/raf.d.ts +1 -1
  79. package/dist/internals/motion/stagger.d.ts +3 -4
  80. package/dist/internals/motion/tokens.js +4 -0
  81. package/dist/internals/motion/transitions.d.ts +17 -17
  82. package/dist/internals/motion/types.d.ts +6 -7
  83. package/dist/internals/relative-time.d.ts +1 -1
  84. package/dist/styles.css +3470 -203
  85. package/package.json +18 -2
  86. package/dist/components/fireworks-hdr/webgpu-types.d.ts +0 -159
@@ -1,183 +1,134 @@
1
1
  "use client";
2
- import { jsx } from "react/jsx-runtime";
3
- import { useRef, useState, useEffect } from "react";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { useId, useRef, useState, useEffect, useCallback } from "react";
4
4
  import { useLiveRef } from "../../internals/dom/use-live-ref.js";
5
+ import { useReducedMotion } from "../../internals/motion/media-query.js";
5
6
  import { cn } from "../../utils.js";
6
- function SmoothCursor({ cursor, springConfig = {}, className = "" }) {
7
- const config = {
8
- damping: springConfig.damping ?? 45,
9
- stiffness: springConfig.stiffness ?? 400,
10
- mass: springConfig.mass ?? 1
11
- };
7
+ import { createSmoothCursor } from "./smooth-cursor-core.js";
8
+ /* empty css */
9
+ const TIP_X = 4;
10
+ const TIP_Y = 3;
11
+ function SmoothCursor({
12
+ cursor,
13
+ springConfig = {},
14
+ className = "",
15
+ label,
16
+ color = "#0e9f6e",
17
+ rotate = false,
18
+ idleFade = 1500,
19
+ labelSpring
20
+ }) {
21
+ const uid = useId().replace(/[^A-Za-z0-9_-]/g, "");
22
+ const fillId = `smooth-cursor-fill-${uid}`;
12
23
  const cursorElRef = useRef(null);
24
+ const labelElRef = useRef(null);
25
+ const engineRef = useRef(null);
13
26
  const [visible, setVisible] = useState(false);
14
- const configRef = useLiveRef(config);
15
- const stateRef = useRef({
16
- visible: false,
17
- reducedMotion: false,
18
- posX: 0,
19
- posY: 0,
20
- velX: 0,
21
- velY: 0,
22
- targetX: 0,
23
- targetY: 0,
24
- rotation: 0,
25
- prevX: 0,
26
- prevY: 0,
27
- rafId: null,
28
- lastTime: 0
29
- });
27
+ const [idle, setIdle] = useState(false);
28
+ const reducedMotion = useReducedMotion();
29
+ const initRef = useLiveRef({ springConfig, labelSpring, rotate, idleFade, reducedMotion });
30
+ const appliedReducedMotionRef = useRef(false);
31
+ const hotspot = !cursor && !rotate ? `-${TIP_X}px -${TIP_Y}px` : "-50% -50%";
30
32
  useEffect(() => {
31
- const s = stateRef.current;
32
- function startAnimation() {
33
- if (s.rafId === null) {
34
- s.lastTime = 0;
35
- s.rafId = requestAnimationFrame(animate);
33
+ const init = initRef.current;
34
+ appliedReducedMotionRef.current = init.reducedMotion;
35
+ const engine = createSmoothCursor(
36
+ { cursor: cursorElRef.current, label: labelElRef.current },
37
+ {
38
+ springConfig: init.springConfig,
39
+ labelSpring: init.labelSpring,
40
+ rotate: init.rotate,
41
+ idleFade: init.idleFade,
42
+ reducedMotion: init.reducedMotion,
43
+ onVisibleChange: setVisible,
44
+ onIdleChange: setIdle
36
45
  }
37
- }
38
- function stopAnimation() {
39
- if (s.rafId !== null) {
40
- cancelAnimationFrame(s.rafId);
41
- s.rafId = null;
42
- }
43
- }
44
- function snapToTarget() {
45
- s.posX = s.targetX;
46
- s.posY = s.targetY;
47
- s.velX = 0;
48
- s.velY = 0;
49
- if (cursorElRef.current) {
50
- cursorElRef.current.style.transform = `translate3d(${s.posX}px, ${s.posY}px, 0)`;
51
- }
52
- }
53
- function onMouseMove(e) {
54
- s.targetX = e.clientX;
55
- s.targetY = e.clientY;
56
- if (!s.visible) {
57
- s.posX = s.targetX;
58
- s.posY = s.targetY;
59
- s.prevX = s.targetX;
60
- s.prevY = s.targetY;
61
- s.visible = true;
62
- setVisible(true);
63
- }
64
- if (s.reducedMotion) {
65
- snapToTarget();
66
- } else {
67
- startAnimation();
68
- }
69
- }
70
- function onMouseLeave() {
71
- s.visible = false;
72
- setVisible(false);
73
- stopAnimation();
74
- }
75
- function onMouseEnter(e) {
76
- s.targetX = e.clientX;
77
- s.targetY = e.clientY;
78
- s.posX = s.targetX;
79
- s.posY = s.targetY;
80
- s.prevX = s.targetX;
81
- s.prevY = s.targetY;
82
- s.visible = true;
83
- setVisible(true);
84
- if (!s.reducedMotion) {
85
- startAnimation();
86
- } else {
87
- snapToTarget();
88
- }
89
- }
90
- function animate(time) {
91
- if (!s.visible) {
92
- s.rafId = null;
93
- return;
94
- }
95
- s.rafId = requestAnimationFrame(animate);
96
- if (s.lastTime === 0) {
97
- s.lastTime = time;
98
- return;
99
- }
100
- const dt = Math.min((time - s.lastTime) / 1e3, 0.064);
101
- s.lastTime = time;
102
- const { stiffness, damping, mass } = configRef.current;
103
- const forceX = -stiffness * (s.posX - s.targetX) - damping * s.velX;
104
- const forceY = -stiffness * (s.posY - s.targetY) - damping * s.velY;
105
- const accX = forceX / mass;
106
- const accY = forceY / mass;
107
- s.velX += accX * dt;
108
- s.velY += accY * dt;
109
- s.posX += s.velX * dt;
110
- s.posY += s.velY * dt;
111
- const dx = s.posX - s.prevX;
112
- const dy = s.posY - s.prevY;
113
- const distance = Math.sqrt(dx * dx + dy * dy);
114
- if (distance > 0.1) {
115
- const targetRotation = Math.atan2(dy, dx) * (180 / Math.PI) + 90;
116
- let diff = targetRotation - s.rotation;
117
- while (diff > 180) diff -= 360;
118
- while (diff < -180) diff += 360;
119
- s.rotation += diff * 0.3;
120
- }
121
- s.prevX = s.posX;
122
- s.prevY = s.posY;
123
- if (cursorElRef.current) {
124
- cursorElRef.current.style.transform = `translate3d(${s.posX}px, ${s.posY}px, 0) rotate(${s.rotation}deg)`;
125
- }
126
- }
127
- const motionQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
128
- s.reducedMotion = motionQuery.matches;
129
- function onMotionChange(e) {
130
- s.reducedMotion = e.matches;
131
- if (s.reducedMotion) {
132
- stopAnimation();
133
- snapToTarget();
134
- } else if (s.visible) {
135
- startAnimation();
136
- }
137
- }
138
- motionQuery.addEventListener("change", onMotionChange);
139
- document.body.style.cursor = "none";
140
- document.addEventListener("mousemove", onMouseMove);
141
- document.documentElement.addEventListener("mouseleave", onMouseLeave);
142
- document.documentElement.addEventListener("mouseenter", onMouseEnter);
46
+ );
47
+ engineRef.current = engine;
143
48
  return () => {
144
- document.body.style.cursor = "";
145
- motionQuery.removeEventListener("change", onMotionChange);
146
- document.removeEventListener("mousemove", onMouseMove);
147
- document.documentElement.removeEventListener("mouseleave", onMouseLeave);
148
- document.documentElement.removeEventListener("mouseenter", onMouseEnter);
149
- stopAnimation();
49
+ engine.destroy();
50
+ engineRef.current = null;
150
51
  };
52
+ }, [initRef]);
53
+ useEffect(() => {
54
+ if (appliedReducedMotionRef.current === reducedMotion) return;
55
+ appliedReducedMotionRef.current = reducedMotion;
56
+ engineRef.current?.setOptions({ reducedMotion });
57
+ }, [reducedMotion]);
58
+ useEffect(() => {
59
+ engineRef.current?.setOptions({ springConfig });
60
+ }, [springConfig]);
61
+ useEffect(() => {
62
+ engineRef.current?.setOptions({ labelSpring });
63
+ }, [labelSpring]);
64
+ useEffect(() => {
65
+ engineRef.current?.setOptions({ rotate });
66
+ }, [rotate]);
67
+ useEffect(() => {
68
+ engineRef.current?.setOptions({ idleFade });
69
+ }, [idleFade]);
70
+ const setLabelEl = useCallback((node) => {
71
+ labelElRef.current = node;
72
+ engineRef.current?.setLabel(node);
151
73
  }, []);
152
- return /* @__PURE__ */ jsx(
74
+ return /* @__PURE__ */ jsxs(
153
75
  "div",
154
76
  {
155
- ref: cursorElRef,
156
77
  "aria-hidden": "true",
157
78
  className: cn(
158
- "pointer-events-none fixed top-0 left-0 z-[9999]",
79
+ "smooth-cursor pointer-events-none fixed top-0 left-0 z-[9999]",
159
80
  visible ? "opacity-100" : "opacity-0",
160
81
  className
161
82
  ),
162
- style: { willChange: "transform", translate: "-50% -50%" },
163
- children: cursor || // Default cursor: arrow SVG
164
- /* @__PURE__ */ jsx(
165
- "svg",
166
- {
167
- xmlns: "http://www.w3.org/2000/svg",
168
- width: "32",
169
- height: "32",
170
- viewBox: "0 0 32 32",
171
- focusable: "false",
172
- children: /* @__PURE__ */ jsx(
173
- "path",
174
- {
175
- fill: "currentColor",
176
- d: "M9.391 2.32C8.42 1.56 7 2.253 7 3.486V28.41c0 1.538 1.966 2.18 2.874.938l6.225-8.523a2 2 0 0 1 1.615-.82h9.69c1.512 0 2.17-1.912.978-2.844z"
177
- }
178
- )
179
- }
180
- )
83
+ style: { "--_sc-color": `var(--smooth-cursor-color, ${color})` },
84
+ children: [
85
+ /* @__PURE__ */ jsx(
86
+ "div",
87
+ {
88
+ ref: cursorElRef,
89
+ className: rotate ? "sc-pointer sc-pointer--rotate" : "sc-pointer",
90
+ style: { translate: hotspot },
91
+ children: cursor ? cursor : (
92
+ // Default cursor: coloured arrowhead with a white rim
93
+ /* @__PURE__ */ jsxs(
94
+ "svg",
95
+ {
96
+ className: "sc-arrow",
97
+ xmlns: "http://www.w3.org/2000/svg",
98
+ width: "24",
99
+ height: "24",
100
+ viewBox: "0 0 24 24",
101
+ focusable: "false",
102
+ children: [
103
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: fillId, x1: "0.1", y1: "0", x2: "0.75", y2: "1", children: [
104
+ /* @__PURE__ */ jsx("stop", { offset: "0", className: "sc-stop-hot" }),
105
+ /* @__PURE__ */ jsx("stop", { offset: "0.55", className: "sc-stop-body" }),
106
+ /* @__PURE__ */ jsx("stop", { offset: "1", className: "sc-stop-deep" })
107
+ ] }) }),
108
+ /* @__PURE__ */ jsx(
109
+ "path",
110
+ {
111
+ className: "sc-arrow-rim",
112
+ d: "M4 3 L19.6 13.9 L10.2 12.7 L7.3 21.7 Z",
113
+ fill: `url(#${fillId})`
114
+ }
115
+ )
116
+ ]
117
+ }
118
+ )
119
+ )
120
+ }
121
+ ),
122
+ label ? /* @__PURE__ */ jsx(
123
+ "div",
124
+ {
125
+ ref: setLabelEl,
126
+ className: idle ? "sc-label is-idle" : "sc-label",
127
+ "data-smooth-cursor-label": "",
128
+ children: /* @__PURE__ */ jsx("span", { className: "sc-label-text", children: label })
129
+ }
130
+ ) : null
131
+ ]
181
132
  }
182
133
  );
183
134
  }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * SmoothCursor core — framework-free spring-physics cursor engine.
3
+ *
4
+ * Owns the rAF loop, the spring integration, rotation-from-velocity, the
5
+ * trailing name label (its own softer spring, tethered to the arrow), the idle
6
+ * timer, the `document`-level pointer listeners and the native-cursor
7
+ * hide/restore. The wrapper owns markup, the cursor snippet, `class`, a11y
8
+ * attributes and the `prefers-reduced-motion` query. The query's *mount* value
9
+ * is forwarded as a creation option (plain assignment, no snap); only a later
10
+ * *change* event is forwarded through `setOptions({ reducedMotion })`, which
11
+ * snaps. That split reproduces the original wrapper's two distinct
12
+ * reduced-motion entry points.
13
+ *
14
+ * The loop sleeps once both springs have settled on the pointer and wakes on
15
+ * the next pointer move; the first frame after a wake is capped to one 60 Hz
16
+ * step so a long rest never turns into a single oversized integration step.
17
+ */
18
+ export interface SpringConfig {
19
+ /** Controls how quickly the animation settles (default: 45) */
20
+ damping?: number;
21
+ /** Controls the spring stiffness (default: 400) */
22
+ stiffness?: number;
23
+ /** Controls the virtual mass of the animated object (default: 1) */
24
+ mass?: number;
25
+ }
26
+ export interface SmoothCursorElements {
27
+ /** The fixed-position element the engine transforms in place. */
28
+ cursor: HTMLElement;
29
+ /**
30
+ * Optional name-label element. It trails the cursor on its own, softer
31
+ * spring (see `labelSpring`) and is written as
32
+ * `translate3d(x, y, 0) rotate(<tilt>deg)` — the wrapper adds the visual
33
+ * offset from the arrow tip with the CSS `translate` property. Can also be
34
+ * attached or swapped later with `setLabel()`.
35
+ */
36
+ label?: HTMLElement | null;
37
+ }
38
+ export interface SmoothCursorInitOptions {
39
+ /** Called whenever the engine's visibility (pointer on/off screen) changes. */
40
+ onVisibleChange?: (visible: boolean) => void;
41
+ /**
42
+ * Called when the pointer has rested for `idleFade` ms (`true`) and again on
43
+ * the next movement (`false`). Never called while `idleFade` is 0.
44
+ */
45
+ onIdleChange?: (idle: boolean) => void;
46
+ }
47
+ export interface SmoothCursorLiveOptions {
48
+ /** Spring physics configuration. */
49
+ springConfig?: SpringConfig;
50
+ /**
51
+ * Spring for the label. Every field left out is derived from the resolved
52
+ * `springConfig`: stiffness × 0.55, damping × 1.1, same mass — a softer,
53
+ * more damped follow that lags the arrow by a few frames.
54
+ */
55
+ labelSpring?: SpringConfig;
56
+ /**
57
+ * Rotate the cursor toward its direction of travel. Defaults to `true` here
58
+ * (the engine's original behaviour); wrappers that render an upright arrow
59
+ * pass `false`, which eases any existing rotation back to 0.
60
+ */
61
+ rotate?: boolean;
62
+ /**
63
+ * Milliseconds without pointer movement before `onIdleChange(true)` fires.
64
+ * 0 (the default) disables idle tracking entirely.
65
+ */
66
+ idleFade?: number;
67
+ /**
68
+ * Wrapper-owned `prefers-reduced-motion` result. Passed at creation it is a
69
+ * plain initial value; pushed through `setOptions` it additionally stops the
70
+ * loop and snaps to the pointer (zeroing velocity), matching the original
71
+ * wrapper's media-query `change` handler.
72
+ */
73
+ reducedMotion?: boolean;
74
+ }
75
+ export interface SmoothCursorEngine {
76
+ setOptions(next: Partial<SmoothCursorLiveOptions>): void;
77
+ /** Attach, swap or detach (`null`) the label element after creation. */
78
+ setLabel(label: HTMLElement | null): void;
79
+ resize(): void;
80
+ destroy(): void;
81
+ }
82
+ export declare function resolveConfig(springConfig: SpringConfig | undefined): Required<SpringConfig>;
83
+ /** The label's spring: explicit fields win, the rest derive from the arrow's. */
84
+ export declare function resolveLabelConfig(labelSpring: SpringConfig | undefined, springConfig: SpringConfig | undefined): Required<SpringConfig>;
85
+ export declare function createSmoothCursor(el: SmoothCursorElements, options: SmoothCursorInitOptions & SmoothCursorLiveOptions): SmoothCursorEngine;