fancy-ui-react 0.2.1 → 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 (93) hide show
  1. package/README.md +56 -20
  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/button/Button.js +5 -1
  15. package/dist/components/compare/Compare.d.ts +32 -8
  16. package/dist/components/compare/Compare.js +213 -95
  17. package/dist/components/container-scroll/ContainerScroll.d.ts +26 -4
  18. package/dist/components/container-scroll/ContainerScroll.js +88 -49
  19. package/dist/components/datamosh-transition/DatamoshTransition.d.ts +76 -0
  20. package/dist/components/datamosh-transition/DatamoshTransition.js +368 -0
  21. package/dist/components/datamosh-transition/datamosh-transition-core.d.ts +180 -0
  22. package/dist/components/datamosh-transition/datamosh-transition-core.js +370 -0
  23. package/dist/components/datamosh-transition/index.d.ts +3 -0
  24. package/dist/components/dock/Dock.d.ts +10 -7
  25. package/dist/components/dock/Dock.js +76 -31
  26. package/dist/components/dock/DockIcon.d.ts +14 -3
  27. package/dist/components/dock/DockIcon.js +23 -19
  28. package/dist/components/dock/DockSeparator.d.ts +4 -1
  29. package/dist/components/dock/DockSeparator.js +5 -2
  30. package/dist/components/dock/types.d.ts +13 -6
  31. package/dist/components/dropdown-menu/menu-shared.d.ts +11 -8
  32. package/dist/components/editorial-engine/engine.js +1 -14
  33. package/dist/components/fireworks-hdr/webgl2-renderer.js +0 -19
  34. package/dist/components/fireworks-hdr/webgpu-renderer.js +3 -22
  35. package/dist/components/flip-card/FlipCard.d.ts +42 -1
  36. package/dist/components/flip-card/FlipCard.js +178 -25
  37. package/dist/components/flip-card/index.d.ts +1 -1
  38. package/dist/components/fluid-cursor/FluidCursor.js +5 -4
  39. package/dist/components/fluid-cursor/dev.d.ts +1 -0
  40. package/dist/components/fluid-cursor/dev.js +8 -0
  41. package/dist/components/fluid-cursor/fluid-shared.d.ts +0 -2
  42. package/dist/components/fluid-cursor/fluid-shared.js +0 -2
  43. package/dist/components/fluid-cursor/webgpu-engine.js +10 -24
  44. package/dist/components/glow-border/GlowBorder.d.ts +41 -1
  45. package/dist/components/glow-border/GlowBorder.js +96 -16
  46. package/dist/components/glow-border/index.d.ts +2 -2
  47. package/dist/components/gradient-button/GradientButton.d.ts +10 -5
  48. package/dist/components/gradient-button/GradientButton.js +25 -18
  49. package/dist/components/image-trail-cursor/ImageTrailCursor.js +1 -0
  50. package/dist/components/image-trail-cursor/trail-variants.d.ts +37 -1
  51. package/dist/components/image-trail-cursor/trail-variants.js +331 -8
  52. package/dist/components/interactive-hover-button/InteractiveHoverButton.js +30 -35
  53. package/dist/components/marquee/Marquee.d.ts +7 -3
  54. package/dist/components/marquee/Marquee.js +134 -2
  55. package/dist/components/marquee/ReviewCard.d.ts +2 -1
  56. package/dist/components/marquee/ReviewCard.js +20 -9
  57. package/dist/components/meteors/Meteors.d.ts +32 -10
  58. package/dist/components/meteors/Meteors.js +53 -20
  59. package/dist/components/mosaic-glow/mosaic-glow-core.d.ts +98 -10
  60. package/dist/components/neon-border/NeonBorder.d.ts +24 -5
  61. package/dist/components/neon-border/NeonBorder.js +37 -7
  62. package/dist/components/pagination/Pagination.js +220 -82
  63. package/dist/components/rainbow-button/RainbowButton.js +13 -5
  64. package/dist/components/ripple-button/RippleButton.d.ts +20 -1
  65. package/dist/components/ripple-button/RippleButton.js +44 -21
  66. package/dist/components/shimmer-button/ShimmerButton.d.ts +5 -5
  67. package/dist/components/shimmer-button/ShimmerButton.js +17 -19
  68. package/dist/components/smooth-cursor/SmoothCursor.d.ts +13 -9
  69. package/dist/components/smooth-cursor/SmoothCursor.js +114 -163
  70. package/dist/components/smooth-cursor/smooth-cursor-core.d.ts +85 -0
  71. package/dist/components/smooth-cursor/smooth-cursor-core.js +327 -0
  72. package/dist/components/stepper/Step.js +32 -19
  73. package/dist/components/stepper/Stepper.js +18 -2
  74. package/dist/components/stepper/types.d.ts +13 -0
  75. package/dist/components/timeline/Timeline.d.ts +8 -1
  76. package/dist/components/timeline/Timeline.js +165 -76
  77. package/dist/index.d.ts +1 -0
  78. package/dist/index.js +6 -1
  79. package/dist/internals/markdown.d.ts +5 -0
  80. package/dist/internals/motion/haptics.d.ts +0 -4
  81. package/dist/internals/motion/presence-core.d.ts +59 -0
  82. package/dist/internals/motion/presence-core.js +162 -0
  83. package/dist/internals/motion/presence.d.ts +2 -4
  84. package/dist/internals/motion/presence.js +1 -156
  85. package/dist/internals/motion/raf.d.ts +1 -1
  86. package/dist/internals/motion/stagger.d.ts +3 -4
  87. package/dist/internals/motion/tokens.js +4 -0
  88. package/dist/internals/motion/transitions.d.ts +17 -17
  89. package/dist/internals/motion/types.d.ts +6 -7
  90. package/dist/internals/relative-time.d.ts +1 -1
  91. package/dist/styles.css +3545 -204
  92. package/package.json +18 -2
  93. package/dist/components/fireworks-hdr/webgpu-types.d.ts +0 -159
@@ -4,25 +4,29 @@ import { forwardRef } from "react";
4
4
  import { cn } from "../../utils.js";
5
5
  import { useSoundCue } from "../../sound/use-sound.js";
6
6
  /* empty css */
7
- const DEFAULT_COLORS = [
8
- "#FF0000",
9
- "#FFA500",
10
- "#FFFF00",
11
- "#008000",
12
- "#0000FF",
13
- "#4B0082",
14
- "#EE82EE",
15
- "#FF0000"
16
- ];
7
+ function beamGradient(colors) {
8
+ const list = colors.length ? colors : ["#ffffff"];
9
+ const arc = (from, to, strength) => {
10
+ const span = to - from;
11
+ const stops = list.map((c, i) => {
12
+ const at = from + span * ((i + 1) / (list.length + 1));
13
+ const color = strength < 100 ? `color-mix(in srgb, ${c} ${strength}%, transparent)` : c;
14
+ return `${color} ${at.toFixed(1)}%`;
15
+ });
16
+ return [`transparent ${from}%`, ...stops, `transparent ${to}%`].join(", ");
17
+ };
18
+ return `conic-gradient(from var(--gb-angle), ${arc(0, 42, 100)}, ${arc(50, 78, 45)}, transparent 100%)`;
19
+ }
20
+ const DEFAULT_COLORS = ["#34d399", "#22d3ee", "#6366f1", "#d946ef", "#f43f5e", "#f59e0b"];
17
21
  const GradientButton = forwardRef(
18
22
  ({
19
23
  className,
20
24
  colors = DEFAULT_COLORS,
21
- duration = 2500,
22
- borderWidth = 2,
23
- borderRadius = 8,
25
+ duration = 3e3,
26
+ borderWidth = 1.5,
27
+ borderRadius = 12,
24
28
  blur = 4,
25
- bgColor = "#000",
29
+ bgColor = "#161616",
26
30
  children,
27
31
  onClick,
28
32
  sound = false,
@@ -35,6 +39,7 @@ const GradientButton = forwardRef(
35
39
  }
36
40
  const styleVars = {
37
41
  "--gb-colors": colors.join(", "),
42
+ "--gb-beam": beamGradient(colors),
38
43
  "--gb-duration": `${duration}ms`,
39
44
  "--gb-border-width": `${borderWidth}px`,
40
45
  "--gb-border-radius": `${borderRadius}px`,
@@ -46,15 +51,16 @@ const GradientButton = forwardRef(
46
51
  {
47
52
  ref,
48
53
  className: cn(
49
- "gradient-button relative flex min-h-10 min-w-28 cursor-pointer items-center justify-center overflow-hidden",
54
+ "gradient-button relative flex min-h-10 min-w-28 cursor-pointer items-center justify-center overflow-hidden text-white",
50
55
  className
51
56
  ),
52
57
  style: styleVars,
53
58
  onClick: handleClick,
54
59
  ...restProps,
55
60
  children: [
56
- /* @__PURE__ */ jsx("span", { className: "gradient-border", "aria-hidden": "true" }),
57
- /* @__PURE__ */ jsx("span", { className: "gradient-content inline-flex size-full items-center justify-center px-4 py-2", children })
61
+ /* @__PURE__ */ jsx("span", { className: "gradient-content inline-flex size-full items-center justify-center px-5 py-2.5", children }),
62
+ /* @__PURE__ */ jsx("span", { className: "gradient-glow", "aria-hidden": "true", children: /* @__PURE__ */ jsx("span", {}) }),
63
+ /* @__PURE__ */ jsx("span", { className: "gradient-border", "aria-hidden": "true" })
58
64
  ]
59
65
  }
60
66
  );
@@ -62,5 +68,6 @@ const GradientButton = forwardRef(
62
68
  );
63
69
  GradientButton.displayName = "GradientButton";
64
70
  export {
65
- GradientButton
71
+ GradientButton,
72
+ beamGradient
66
73
  };
@@ -7,6 +7,7 @@ function resetImageStyles(container) {
7
7
  const imgEls = container.querySelectorAll(".content__img");
8
8
  for (const el of imgEls) {
9
9
  el.style.cssText = "";
10
+ for (const frag of el.querySelectorAll(".content__img-frag")) frag.remove();
10
11
  const inner = el.querySelector(".content__img-inner");
11
12
  if (inner) {
12
13
  const bgImage = inner.style.backgroundImage;
@@ -1,4 +1,4 @@
1
- export type VariantType = "type1" | "type2" | "type3" | "type4" | "type5" | "type6" | "type7" | "type8" | "pixelated";
1
+ export type VariantType = "type1" | "type2" | "type3" | "type4" | "type5" | "type6" | "type7" | "type8" | "pixelated" | "scale" | "fall" | "gravity" | "flame" | "venetian" | "curtain" | "hexagon" | "liquid" | "zoom-split";
2
2
  export interface ImageTrailVariant {
3
3
  destroy(): void;
4
4
  }
@@ -60,6 +60,8 @@ declare abstract class BaseVariant implements ImageTrailVariant {
60
60
  protected render(): void;
61
61
  protected updateCache(): void;
62
62
  protected abstract showNextImage(): void;
63
+ /** Advance to the next image in the ring. */
64
+ protected nextImage(): ImageItem | undefined;
63
65
  protected onImageActivated(): void;
64
66
  protected onImageDeactivated(): void;
65
67
  destroy(): void;
@@ -108,5 +110,39 @@ export declare class ImageTrailVariantPixelated extends BaseVariant {
108
110
  constructor(container: HTMLDivElement);
109
111
  protected showNextImage(): void;
110
112
  }
113
+ export declare class ImageTrailVariantScale extends BaseVariant {
114
+ protected showNextImage(): void;
115
+ }
116
+ export declare class ImageTrailVariantFall extends BaseVariant {
117
+ protected showNextImage(): void;
118
+ }
119
+ export declare class ImageTrailVariantGravity extends BaseVariant {
120
+ protected showNextImage(): void;
121
+ }
122
+ export declare class ImageTrailVariantFlame extends BaseVariant {
123
+ protected showNextImage(): void;
124
+ }
125
+ export type RevealPattern = "venetian" | "curtain" | "hexagon" | "liquid" | "zoom-split";
126
+ export interface RevealFragment {
127
+ /** clip-path while hidden */
128
+ closed: string;
129
+ /** clip-path once revealed */
130
+ open: string;
131
+ /** 0 (first) … 1 (last): when the fragment opens within the stagger */
132
+ order: number;
133
+ }
134
+ /**
135
+ * The fragments of each reveal, as clip-paths in the image's own box.
136
+ * `closed` and `open` always have the same shape and point count, so the
137
+ * tween between them is a straight interpolation.
138
+ */
139
+ export declare function revealFragments(pattern: RevealPattern): RevealFragment[];
140
+ export declare class ImageTrailVariantReveal extends BaseVariant {
141
+ private static readonly STAGGER;
142
+ private readonly fragments;
143
+ constructor(container: HTMLDivElement, pattern: RevealPattern);
144
+ protected showNextImage(): void;
145
+ destroy(): void;
146
+ }
111
147
  export declare const variantMap: Record<VariantType, new (container: HTMLDivElement) => ImageTrailVariant>;
112
148
  export {};
@@ -37,12 +37,12 @@ class ImageItem {
37
37
  el: null,
38
38
  inner: null
39
39
  };
40
- // Port divergence: `private` where the Svelte source says `public`. gsap declares
41
- // `TweenVars` inside a GLOBAL `namespace gsap` with no module-level export, so a
42
- // public `gsap.TweenVars` member emits a bare `gsap.` reference into the shipped
43
- // .d.ts while tsc drops the value-only `import { gsap }` — consumers then hit
44
- // TS2503 "Cannot find namespace 'gsap'". A private member emits no type at all.
45
- // Read only by initEvents() below, so nothing outside this class loses access.
40
+ // `private`, not `public`: the animation library declares `TweenVars` inside a
41
+ // GLOBAL namespace with no module-level export, so a public `gsap.TweenVars`
42
+ // member emits a bare `gsap.` reference into the shipped .d.ts while tsc drops
43
+ // the value-only `import { gsap }` — deep-importing consumers then hit TS2503
44
+ // "Cannot find namespace 'gsap'". A private member emits no type at all, and it
45
+ // is read only by initEvents() below, so nothing outside this class loses access.
46
46
  defaultStyle = { scale: 1, x: 0, y: 0, opacity: 0 };
47
47
  rect = null;
48
48
  resizeHandler = null;
@@ -164,7 +164,8 @@ class BaseVariant {
164
164
  const now = performance.now();
165
165
  this.positionHistory.push({ x, y, t: now });
166
166
  const cutoff = now - BaseVariant.HISTORY_MAX_AGE;
167
- while (this.positionHistory.length > BaseVariant.HISTORY_MAX_LEN || this.positionHistory.length > 1 && this.positionHistory[0].t < cutoff) {
167
+ while (this.positionHistory.length > BaseVariant.HISTORY_MAX_LEN || // Non-null: `length > 1` on this same clause proves index 0 exists.
168
+ this.positionHistory.length > 1 && this.positionHistory[0].t < cutoff) {
168
169
  this.positionHistory.shift();
169
170
  }
170
171
  }
@@ -203,6 +204,11 @@ class BaseVariant {
203
204
  this.cacheMousePos.x = lerp(this.cacheMousePos.x, this.mousePos.x, 0.1);
204
205
  this.cacheMousePos.y = lerp(this.cacheMousePos.y, this.mousePos.y, 0.1);
205
206
  }
207
+ /** Advance to the next image in the ring. */
208
+ nextImage() {
209
+ this.imgPosition = this.imgPosition < this.imagesTotal - 1 ? this.imgPosition + 1 : 0;
210
+ return this.images[this.imgPosition];
211
+ }
206
212
  onImageActivated() {
207
213
  this.activeImagesCount++;
208
214
  this.isIdle = false;
@@ -761,6 +767,308 @@ class ImageTrailVariantPixelated extends BaseVariant {
761
767
  ).set(img.DOM.el, { opacity: 0, scale: 0.2 }, ImageTrailVariantPixelated.HOLD);
762
768
  }
763
769
  }
770
+ function randomBetween(min, max) {
771
+ return min + Math.random() * (max - min);
772
+ }
773
+ class ImageTrailVariantScale extends BaseVariant {
774
+ showNextImage() {
775
+ ++this.zIndexVal;
776
+ const img = this.nextImage();
777
+ if (!img) return;
778
+ const w = img.rect?.width ?? 0;
779
+ const h = img.rect?.height ?? 0;
780
+ gsap.killTweensOf(img.DOM.el);
781
+ gsap.timeline({
782
+ onStart: () => this.onImageActivated(),
783
+ onComplete: () => this.onImageDeactivated()
784
+ }).set(img.DOM.el, {
785
+ opacity: 1,
786
+ scale: 0,
787
+ rotation: randomBetween(-20, 20),
788
+ zIndex: this.zIndexVal,
789
+ x: this.mousePos.x - w / 2,
790
+ y: this.mousePos.y - h / 2
791
+ }).to(img.DOM.el, { scale: 1, duration: 0.6, ease: "back.out(2)" }, 0).to(img.DOM.el, { scale: 0, duration: 0.6, ease: "power2.in" }, 0.75).set(img.DOM.el, { opacity: 0 });
792
+ }
793
+ }
794
+ class ImageTrailVariantFall extends BaseVariant {
795
+ showNextImage() {
796
+ ++this.zIndexVal;
797
+ const img = this.nextImage();
798
+ if (!img) return;
799
+ const w = img.rect?.width ?? 0;
800
+ const h = img.rect?.height ?? 0;
801
+ const floor = this.container.getBoundingClientRect().height;
802
+ gsap.killTweensOf(img.DOM.el);
803
+ gsap.timeline({
804
+ onStart: () => this.onImageActivated(),
805
+ onComplete: () => this.onImageDeactivated()
806
+ }).set(img.DOM.el, {
807
+ opacity: 1,
808
+ scale: 0,
809
+ rotation: 0,
810
+ zIndex: this.zIndexVal,
811
+ x: this.mousePos.x - w / 2,
812
+ y: this.mousePos.y - h / 2
813
+ }).to(img.DOM.el, { scale: 1, duration: 0.8, ease: "elastic.out(1, 0.3)" }, 0).to(img.DOM.el, { rotation: randomBetween(-360, 360), duration: 1.1, ease: "power1.out" }, 0).to(img.DOM.el, { y: floor * 1.2 + h, duration: 1, ease: "back.in(0.4)" }, 0).set(img.DOM.el, { opacity: 0 });
814
+ }
815
+ }
816
+ class ImageTrailVariantGravity extends BaseVariant {
817
+ showNextImage() {
818
+ ++this.zIndexVal;
819
+ const img = this.nextImage();
820
+ if (!img) return;
821
+ const w = img.rect?.width ?? 0;
822
+ const h = img.rect?.height ?? 0;
823
+ const height = this.container.getBoundingClientRect().height;
824
+ const startY = this.mousePos.y - h / 2;
825
+ const floorY = Math.max(startY, height - h);
826
+ const drop = floorY - startY;
827
+ const push = Math.max(-140, Math.min(140, (this.mousePos.x - this.lastMousePos.x) * 1.4));
828
+ const fall = 0.3 + 0.35 * Math.sqrt(drop / Math.max(1, height));
829
+ const bounce = drop * 0.32;
830
+ gsap.killTweensOf(img.DOM.el);
831
+ const el = img.DOM.el;
832
+ gsap.timeline({
833
+ onStart: () => this.onImageActivated(),
834
+ onComplete: () => this.onImageDeactivated()
835
+ }).set(el, {
836
+ opacity: 1,
837
+ scale: 0,
838
+ rotation: randomBetween(-10, 10),
839
+ zIndex: this.zIndexVal,
840
+ x: this.mousePos.x - w / 2,
841
+ y: startY
842
+ }).to(el, { scale: 1, duration: 0.4, ease: "elastic.out(2, 0.6)" }, 0).to(
843
+ el,
844
+ {
845
+ x: `+=${push}`,
846
+ rotation: randomBetween(-30, 30),
847
+ duration: fall + 0.9,
848
+ ease: "power1.out"
849
+ },
850
+ 0.1
851
+ ).to(el, { y: floorY, duration: fall, ease: "power2.in" }, 0.15).to(el, { y: floorY - bounce, duration: 0.28, ease: "power2.out" }).to(el, { y: floorY, duration: 0.28, ease: "power2.in" }).to(el, { y: floorY - bounce * 0.3, duration: 0.16, ease: "power2.out" }).to(el, { y: floorY, duration: 0.16, ease: "power2.in" }).to(el, { opacity: 0, scale: 0.7, duration: 0.3, ease: "power2.in" }, "+=0.15");
852
+ }
853
+ }
854
+ class ImageTrailVariantFlame extends BaseVariant {
855
+ showNextImage() {
856
+ ++this.zIndexVal;
857
+ const img = this.nextImage();
858
+ if (!img) return;
859
+ const w = img.rect?.width ?? 0;
860
+ const h = img.rect?.height ?? 0;
861
+ const { dx, dy } = this.getTouchVelocity();
862
+ const speed = Math.min(1, Math.hypot(dx, dy) / 160);
863
+ const rotation = (Math.random() - 0.5) * 30 * (1 + speed * 2);
864
+ gsap.killTweensOf(img.DOM.el);
865
+ gsap.timeline({
866
+ onStart: () => this.onImageActivated(),
867
+ onComplete: () => this.onImageDeactivated()
868
+ }).set(img.DOM.el, {
869
+ opacity: 1,
870
+ scale: 0,
871
+ rotation,
872
+ zIndex: this.zIndexVal,
873
+ x: this.mousePos.x - w / 2,
874
+ y: this.mousePos.y - h / 2
875
+ }).to(img.DOM.el, { scale: 1, duration: 0.35, ease: "back.out(1.6)" }, 0).to(
876
+ img.DOM.el,
877
+ {
878
+ y: `-=${40 + speed * 40}`,
879
+ scale: 0,
880
+ opacity: 0,
881
+ rotation: rotation * 1.6,
882
+ duration: 0.55,
883
+ ease: "power2.in"
884
+ },
885
+ 0.55
886
+ );
887
+ }
888
+ }
889
+ const SEAM = 0.6;
890
+ const lo = (n) => Math.max(0, n - SEAM);
891
+ const hi = (n) => Math.min(100, n + SEAM);
892
+ const pc = (n) => `${Math.round(n * 100) / 100}%`;
893
+ const poly = (pts) => `polygon(${pts.map(([x, y]) => `${pc(x)} ${pc(y)}`).join(", ")})`;
894
+ function revealFragments(pattern) {
895
+ switch (pattern) {
896
+ case "venetian": {
897
+ const n = 6;
898
+ return Array.from({ length: n }, (_, i) => {
899
+ const y0 = lo(i * 100 / n);
900
+ const y1 = hi((i + 1) * 100 / n);
901
+ return {
902
+ closed: poly([
903
+ [0, y0],
904
+ [100, y0],
905
+ [100, y0],
906
+ [0, y0]
907
+ ]),
908
+ open: poly([
909
+ [0, y0],
910
+ [100, y0],
911
+ [100, y1],
912
+ [0, y1]
913
+ ]),
914
+ order: i / (n - 1)
915
+ };
916
+ });
917
+ }
918
+ case "curtain": {
919
+ const n = 6;
920
+ const mid = (n - 1) / 2;
921
+ return Array.from({ length: n }, (_, i) => {
922
+ const x0 = lo(i * 100 / n);
923
+ const x1 = hi((i + 1) * 100 / n);
924
+ const cx = (x0 + x1) / 2;
925
+ return {
926
+ closed: poly([
927
+ [cx, 0],
928
+ [cx, 0],
929
+ [cx, 100],
930
+ [cx, 100]
931
+ ]),
932
+ open: poly([
933
+ [x0, 0],
934
+ [x1, 0],
935
+ [x1, 100],
936
+ [x0, 100]
937
+ ]),
938
+ order: Math.abs(i - mid) / mid
939
+ };
940
+ });
941
+ }
942
+ case "hexagon": {
943
+ const centres = [16.67, 50, 83.33];
944
+ const r = 31;
945
+ const cells = [];
946
+ for (const cy of centres) {
947
+ for (const cx of centres) {
948
+ const hex = Array.from({ length: 6 }, (_, k) => {
949
+ const a = Math.PI / 3 * k + Math.PI / 6;
950
+ return [cx + r * Math.cos(a), cy + r * Math.sin(a)];
951
+ });
952
+ cells.push({
953
+ closed: poly(hex.map(() => [cx, cy])),
954
+ open: poly(hex),
955
+ order: Math.hypot(cx - 50, cy - 50) / Math.hypot(33.33, 33.33)
956
+ });
957
+ }
958
+ }
959
+ return cells;
960
+ }
961
+ case "liquid": {
962
+ const blobs = [
963
+ [50, 50, 48],
964
+ [22, 26, 36],
965
+ [80, 24, 36],
966
+ [26, 80, 36],
967
+ [78, 78, 38]
968
+ ];
969
+ return blobs.map(([x, y, r], i) => ({
970
+ closed: `circle(0% at ${pc(x)} ${pc(y)})`,
971
+ open: `circle(${pc(r)} at ${pc(x)} ${pc(y)})`,
972
+ order: i / (blobs.length - 1)
973
+ }));
974
+ }
975
+ case "zoom-split": {
976
+ const quads = [
977
+ [0, 0],
978
+ [50, 0],
979
+ [0, 50],
980
+ [50, 50]
981
+ ];
982
+ return quads.map(([x, y], i) => ({
983
+ closed: poly([
984
+ [50, 50],
985
+ [50, 50],
986
+ [50, 50],
987
+ [50, 50]
988
+ ]),
989
+ open: poly([
990
+ [lo(x), lo(y)],
991
+ [hi(x + 50), lo(y)],
992
+ [hi(x + 50), hi(y + 50)],
993
+ [lo(x), hi(y + 50)]
994
+ ]),
995
+ order: i / 3
996
+ }));
997
+ }
998
+ }
999
+ }
1000
+ const FRAG_CLASS = "content__img-frag";
1001
+ class ImageTrailVariantReveal extends BaseVariant {
1002
+ static STAGGER = 0.22;
1003
+ // seconds from first to last fragment
1004
+ fragments;
1005
+ constructor(container, pattern) {
1006
+ super(container);
1007
+ this.fragments = revealFragments(pattern);
1008
+ for (const img of this.images) {
1009
+ const bg = img.DOM.inner?.style.backgroundImage ?? "";
1010
+ for (const f of this.fragments) {
1011
+ const frag = document.createElement("div");
1012
+ frag.className = FRAG_CLASS;
1013
+ frag.style.cssText = `position:absolute;inset:0;background-image:${bg};background-size:cover;background-position:center;clip-path:${f.closed};`;
1014
+ img.DOM.el.appendChild(frag);
1015
+ }
1016
+ if (img.DOM.inner) img.DOM.inner.style.opacity = "0";
1017
+ }
1018
+ }
1019
+ showNextImage() {
1020
+ ++this.zIndexVal;
1021
+ const img = this.nextImage();
1022
+ if (!img) return;
1023
+ const w = img.rect?.width ?? 0;
1024
+ const h = img.rect?.height ?? 0;
1025
+ const frags = [...img.DOM.el.querySelectorAll(`.${FRAG_CLASS}`)];
1026
+ const stagger = ImageTrailVariantReveal.STAGGER;
1027
+ gsap.killTweensOf([img.DOM.el, ...frags]);
1028
+ const tl = gsap.timeline({
1029
+ onStart: () => this.onImageActivated(),
1030
+ onComplete: () => this.onImageDeactivated()
1031
+ }).set(img.DOM.el, {
1032
+ opacity: 1,
1033
+ scale: 0.85,
1034
+ rotation: 0,
1035
+ zIndex: this.zIndexVal,
1036
+ x: this.mousePos.x - w / 2,
1037
+ y: this.mousePos.y - h / 2
1038
+ }).to(img.DOM.el, { scale: 1, duration: 0.5, ease: "power3.out" }, 0);
1039
+ frags.forEach((frag, i) => {
1040
+ const f = this.fragments[i];
1041
+ tl.fromTo(
1042
+ frag,
1043
+ { clipPath: f.closed },
1044
+ { clipPath: f.open, duration: 0.45, ease: "power3.out" },
1045
+ f.order * stagger
1046
+ );
1047
+ tl.to(
1048
+ frag,
1049
+ { clipPath: f.closed, duration: 0.35, ease: "power3.in" },
1050
+ 0.95 + (1 - f.order) * stagger
1051
+ );
1052
+ });
1053
+ tl.set(img.DOM.el, { opacity: 0 });
1054
+ }
1055
+ destroy() {
1056
+ for (const img of this.images) {
1057
+ const frags = img.DOM.el.querySelectorAll(`.${FRAG_CLASS}`);
1058
+ gsap.killTweensOf([...frags]);
1059
+ frags.forEach((f) => f.remove());
1060
+ if (img.DOM.inner) img.DOM.inner.style.opacity = "";
1061
+ }
1062
+ super.destroy();
1063
+ }
1064
+ }
1065
+ function revealVariant(pattern) {
1066
+ return class extends ImageTrailVariantReveal {
1067
+ constructor(container) {
1068
+ super(container, pattern);
1069
+ }
1070
+ };
1071
+ }
764
1072
  const variantMap = {
765
1073
  type1: ImageTrailVariant1,
766
1074
  type2: ImageTrailVariant2,
@@ -770,7 +1078,16 @@ const variantMap = {
770
1078
  type6: ImageTrailVariant6,
771
1079
  type7: ImageTrailVariant7,
772
1080
  type8: ImageTrailVariant8,
773
- pixelated: ImageTrailVariantPixelated
1081
+ pixelated: ImageTrailVariantPixelated,
1082
+ scale: ImageTrailVariantScale,
1083
+ fall: ImageTrailVariantFall,
1084
+ gravity: ImageTrailVariantGravity,
1085
+ flame: ImageTrailVariantFlame,
1086
+ venetian: revealVariant("venetian"),
1087
+ curtain: revealVariant("curtain"),
1088
+ hexagon: revealVariant("hexagon"),
1089
+ liquid: revealVariant("liquid"),
1090
+ "zoom-split": revealVariant("zoom-split")
774
1091
  };
775
1092
  export {
776
1093
  ImageItem,
@@ -782,6 +1099,12 @@ export {
782
1099
  ImageTrailVariant6,
783
1100
  ImageTrailVariant7,
784
1101
  ImageTrailVariant8,
1102
+ ImageTrailVariantFall,
1103
+ ImageTrailVariantFlame,
1104
+ ImageTrailVariantGravity,
785
1105
  ImageTrailVariantPixelated,
1106
+ ImageTrailVariantReveal,
1107
+ ImageTrailVariantScale,
1108
+ revealFragments,
786
1109
  variantMap
787
1110
  };
@@ -3,12 +3,13 @@ import { jsxs, jsx } from "react/jsx-runtime";
3
3
  import { forwardRef } from "react";
4
4
  import { cn } from "../../utils.js";
5
5
  import { useSoundCue } from "../../sound/use-sound.js";
6
+ /* empty css */
6
7
  const InteractiveHoverButton = forwardRef(
7
- ({ text = "Button", className, children, sound = false, onClick, disabled, ...restProps }, ref) => {
8
+ ({ text = "Button", className, children, onClick, sound = false, ...restProps }, ref) => {
8
9
  const label = children ?? text;
9
10
  const playCue = useSoundCue(sound);
10
11
  function handleClick(event) {
11
- if (sound && !disabled) playCue("press");
12
+ if (sound && !restProps.disabled) playCue("press");
12
13
  onClick?.(event);
13
14
  }
14
15
  return /* @__PURE__ */ jsxs(
@@ -16,45 +17,39 @@ const InteractiveHoverButton = forwardRef(
16
17
  {
17
18
  ref,
18
19
  className: cn(
19
- "group bg-background relative w-auto cursor-pointer overflow-hidden rounded-full border p-2 px-6 text-center font-semibold",
20
+ "ihb group bg-background relative isolate w-auto cursor-pointer overflow-hidden rounded-full border px-6 py-2.5 text-center font-semibold",
20
21
  className
21
22
  ),
22
23
  onClick: handleClick,
23
- disabled,
24
24
  ...restProps,
25
25
  children: [
26
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
27
- /* @__PURE__ */ jsx("div", { className: "bg-primary size-2 rounded-lg group-hover:scale-[100.8] motion-safe:transition-all motion-safe:duration-300" }),
28
- /* @__PURE__ */ jsx("span", { className: "inline-block group-hover:translate-x-12 group-hover:opacity-0 motion-safe:transition-all motion-safe:duration-300", children: label })
26
+ /* @__PURE__ */ jsx("span", { className: "ihb-fill", "aria-hidden": "true" }),
27
+ /* @__PURE__ */ jsxs("span", { className: "ihb-rest", children: [
28
+ /* @__PURE__ */ jsx("span", { className: "ihb-dot-space", "aria-hidden": "true" }),
29
+ /* @__PURE__ */ jsx("span", { className: "ihb-label", children: label })
29
30
  ] }),
30
- /* @__PURE__ */ jsxs(
31
- "div",
32
- {
33
- "aria-hidden": "true",
34
- className: "text-primary-foreground absolute top-0 z-10 flex size-full translate-x-12 items-center justify-center gap-2 opacity-0 group-hover:-translate-x-5 group-hover:opacity-100 motion-safe:transition-all motion-safe:duration-300",
35
- children: [
36
- /* @__PURE__ */ jsx("span", { children: label }),
37
- /* @__PURE__ */ jsxs(
38
- "svg",
39
- {
40
- xmlns: "http://www.w3.org/2000/svg",
41
- width: "24",
42
- height: "24",
43
- viewBox: "0 0 24 24",
44
- fill: "none",
45
- stroke: "currentColor",
46
- strokeWidth: "2",
47
- strokeLinecap: "round",
48
- strokeLinejoin: "round",
49
- children: [
50
- /* @__PURE__ */ jsx("path", { d: "M5 12h14" }),
51
- /* @__PURE__ */ jsx("path", { d: "m12 5 7 7-7 7" })
52
- ]
53
- }
54
- )
55
- ]
56
- }
57
- )
31
+ /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "ihb-hover", children: [
32
+ /* @__PURE__ */ jsx("span", { className: "ihb-hover-label", children: label }),
33
+ /* @__PURE__ */ jsxs(
34
+ "svg",
35
+ {
36
+ className: "ihb-arrow",
37
+ xmlns: "http://www.w3.org/2000/svg",
38
+ width: "18",
39
+ height: "18",
40
+ viewBox: "0 0 24 24",
41
+ fill: "none",
42
+ stroke: "currentColor",
43
+ strokeWidth: "2",
44
+ strokeLinecap: "round",
45
+ strokeLinejoin: "round",
46
+ children: [
47
+ /* @__PURE__ */ jsx("path", { d: "M5 12h14" }),
48
+ /* @__PURE__ */ jsx("path", { d: "m12 5 7 7-7 7" })
49
+ ]
50
+ }
51
+ )
52
+ ] })
58
53
  ]
59
54
  }
60
55
  );
@@ -4,13 +4,17 @@ export interface MarqueeProps {
4
4
  className?: string;
5
5
  /** Reverse the scroll direction */
6
6
  reverse?: boolean;
7
- /** Pause the animation on hover */
7
+ /** Ease the conveyor to a stop while the pointer (or focus) is inside */
8
8
  pauseOnHover?: boolean;
9
9
  /** Scroll vertically instead of horizontally */
10
10
  vertical?: boolean;
11
- /** Number of times to repeat the children track */
11
+ /** Number of copies of the children rendered on the track */
12
12
  repeat?: number;
13
+ /** Dissolve items at both edges with a gradient mask */
14
+ fade?: boolean;
15
+ /** Speed multiplier applied on top of `--duration` (2 = twice as fast) */
16
+ speed?: number;
13
17
  /** Content to repeat and scroll */
14
18
  children?: ReactNode;
15
19
  }
16
- export declare function Marquee({ className, reverse, pauseOnHover, vertical, repeat, children, }: MarqueeProps): import("react").JSX.Element;
20
+ export declare function Marquee({ className, reverse, pauseOnHover, vertical, repeat, fade, speed, children, }: MarqueeProps): import("react").JSX.Element;