aura-ui-library 1.0.4 → 1.0.5

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/dist/index.js CHANGED
@@ -29,6 +29,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/index.js
30
30
  var index_exports = {};
31
31
  __export(index_exports, {
32
+ Carousel: () => Carousel,
32
33
  MagneticButton: () => MagneticButton,
33
34
  Navbar: () => Navbar,
34
35
  SpotlightCard: () => SpotlightCard
@@ -3697,8 +3698,587 @@ var SpotlightCard = ({
3697
3698
  )
3698
3699
  );
3699
3700
  };
3701
+
3702
+ // src/components/Carousel/Carousel.jsx
3703
+ var import_react4 = __toESM(require("react"));
3704
+ var TRANSITION_MODES = ["slide", "fade", "zoom"];
3705
+ var KEN_BURNS = [
3706
+ { from: "scale(1.12) translate(2%, 1%)", to: "scale(1) translate(0%, 0%)" },
3707
+ { from: "scale(1.1) translate(-3%, -2%)", to: "scale(1) translate(0%, 0%)" },
3708
+ { from: "scale(1) translate(0%, 0%)", to: "scale(1.1) translate(3%, 2%)" },
3709
+ { from: "scale(1.08) translate(1%, -3%)", to: "scale(1) translate(-1%, 1%)" }
3710
+ ];
3711
+ var DEFAULT_CAPTIONS = [];
3712
+ var prefersReducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
3713
+ var Carousel = ({
3714
+ images = [],
3715
+ captions = DEFAULT_CAPTIONS,
3716
+ height = "520px",
3717
+ borderRadius = "20px",
3718
+ autoPlay = true,
3719
+ interval = 5e3,
3720
+ showDots = true,
3721
+ showThumbnails = true,
3722
+ showProgress = true,
3723
+ showCounter = true,
3724
+ showFullscreen = true,
3725
+ showCaptions = true,
3726
+ accentColor = "#ffffff",
3727
+ transitionMode = "slide",
3728
+ gap = 0
3729
+ }) => {
3730
+ const [currentIndex, setCurrentIndex] = (0, import_react4.useState)(0);
3731
+ const [prevIndex, setPrevIndex] = (0, import_react4.useState)(null);
3732
+ const [isDragging, setIsDragging] = (0, import_react4.useState)(false);
3733
+ const [startX, setStartX] = (0, import_react4.useState)(0);
3734
+ const [startTime, setStartTime] = (0, import_react4.useState)(0);
3735
+ const [dragOffset, setDragOffset] = (0, import_react4.useState)(0);
3736
+ const [isHovered, setIsHovered] = (0, import_react4.useState)(false);
3737
+ const [isFullscreen, setIsFullscreen] = (0, import_react4.useState)(false);
3738
+ const [captionVisible, setCaptionVisible] = (0, import_react4.useState)(true);
3739
+ const [loadedImages, setLoadedImages] = (0, import_react4.useState)(/* @__PURE__ */ new Set([0]));
3740
+ const [activeMode, setActiveMode] = (0, import_react4.useState)(transitionMode);
3741
+ const [progressKey, setProgressKey] = (0, import_react4.useState)(0);
3742
+ const containerRef = (0, import_react4.useRef)(null);
3743
+ const timerRef = (0, import_react4.useRef)(null);
3744
+ const count = images.length;
3745
+ const goTo = (0, import_react4.useCallback)(
3746
+ (index, direction) => {
3747
+ const next = (index % count + count) % count;
3748
+ setCaptionVisible(false);
3749
+ setPrevIndex(currentIndex);
3750
+ setTimeout(() => {
3751
+ setCurrentIndex(next);
3752
+ setProgressKey((k) => k + 1);
3753
+ setLoadedImages((prev) => {
3754
+ const s = new Set(prev);
3755
+ s.add(next);
3756
+ s.add((next + 1) % count);
3757
+ return s;
3758
+ });
3759
+ setTimeout(() => setCaptionVisible(true), 80);
3760
+ }, 40);
3761
+ },
3762
+ [currentIndex, count]
3763
+ );
3764
+ const handleNext = (0, import_react4.useCallback)(
3765
+ () => goTo(currentIndex + 1),
3766
+ [goTo, currentIndex]
3767
+ );
3768
+ const handlePrev = (0, import_react4.useCallback)(
3769
+ () => goTo(currentIndex - 1),
3770
+ [goTo, currentIndex]
3771
+ );
3772
+ (0, import_react4.useEffect)(() => {
3773
+ if (!autoPlay || isHovered || isDragging) return;
3774
+ timerRef.current = setInterval(handleNext, interval);
3775
+ return () => clearInterval(timerRef.current);
3776
+ }, [autoPlay, isHovered, isDragging, handleNext, interval, currentIndex]);
3777
+ (0, import_react4.useEffect)(() => {
3778
+ const onKey = (e) => {
3779
+ if (e.key === "ArrowRight") handleNext();
3780
+ if (e.key === "ArrowLeft") handlePrev();
3781
+ if (e.key === "Escape" && isFullscreen) exitFullscreen();
3782
+ const num = parseInt(e.key);
3783
+ if (!isNaN(num) && num >= 1 && num <= count) goTo(num - 1);
3784
+ };
3785
+ window.addEventListener("keydown", onKey);
3786
+ return () => window.removeEventListener("keydown", onKey);
3787
+ }, [handleNext, handlePrev, isFullscreen, count, goTo]);
3788
+ (0, import_react4.useEffect)(() => {
3789
+ const onFsChange = () => {
3790
+ setIsFullscreen(!!document.fullscreenElement);
3791
+ };
3792
+ document.addEventListener("fullscreenchange", onFsChange);
3793
+ return () => document.removeEventListener("fullscreenchange", onFsChange);
3794
+ }, []);
3795
+ const toggleFullscreen = () => {
3796
+ var _a;
3797
+ if (!document.fullscreenElement) {
3798
+ (_a = containerRef.current) == null ? void 0 : _a.requestFullscreen();
3799
+ } else {
3800
+ document.exitFullscreen();
3801
+ }
3802
+ };
3803
+ const exitFullscreen = () => document.exitFullscreen();
3804
+ const onStart = (e) => {
3805
+ setIsDragging(true);
3806
+ const x = e.type.includes("mouse") ? e.pageX : e.touches[0].pageX;
3807
+ setStartX(x);
3808
+ setStartTime(Date.now());
3809
+ };
3810
+ const onMove = (e) => {
3811
+ if (!isDragging) return;
3812
+ const x = e.type.includes("mouse") ? e.pageX : e.touches[0].pageX;
3813
+ setDragOffset(x - startX);
3814
+ };
3815
+ const onEnd = () => {
3816
+ if (!isDragging) return;
3817
+ const velocity = dragOffset / (Date.now() - startTime);
3818
+ const threshold = Math.abs(velocity) > 0.4 ? 30 : 80;
3819
+ if (dragOffset < -threshold) handleNext();
3820
+ else if (dragOffset > threshold) handlePrev();
3821
+ setIsDragging(false);
3822
+ setDragOffset(0);
3823
+ };
3824
+ const kb = KEN_BURNS[currentIndex % KEN_BURNS.length];
3825
+ const animDuration = prefersReducedMotion ? 0 : interval + 500;
3826
+ const getTransform = (idx) => {
3827
+ var _a;
3828
+ if (activeMode !== "slide") return "translateX(0)";
3829
+ const base = (idx - currentIndex) * 100;
3830
+ const drag = isDragging ? dragOffset / (((_a = containerRef.current) == null ? void 0 : _a.offsetWidth) || 1) * 100 : 0;
3831
+ return `translateX(calc(${base}% + ${drag}px))`;
3832
+ };
3833
+ const getOpacity = (idx) => activeMode === "slide" ? 1 : idx === currentIndex ? 1 : 0;
3834
+ const getScale = (idx) => activeMode === "zoom" && idx === currentIndex ? 1 : activeMode === "zoom" ? 0.9 : 1;
3835
+ const caption = captions[currentIndex];
3836
+ return /* @__PURE__ */ import_react4.default.createElement(
3837
+ "div",
3838
+ {
3839
+ ref: containerRef,
3840
+ onMouseEnter: () => setIsHovered(true),
3841
+ onMouseLeave: () => {
3842
+ setIsHovered(false);
3843
+ onEnd();
3844
+ },
3845
+ onMouseDown: onStart,
3846
+ onMouseMove: onMove,
3847
+ onMouseUp: onEnd,
3848
+ onTouchStart: onStart,
3849
+ onTouchMove: onMove,
3850
+ onTouchEnd: onEnd,
3851
+ style: {
3852
+ position: "relative",
3853
+ width: "100%",
3854
+ height: isFullscreen ? "100vh" : height,
3855
+ borderRadius: isFullscreen ? 0 : borderRadius,
3856
+ overflow: "hidden",
3857
+ background: "#000",
3858
+ cursor: isDragging ? "grabbing" : "grab",
3859
+ userSelect: "none",
3860
+ WebkitUserSelect: "none",
3861
+ fontFamily: "system-ui, sans-serif"
3862
+ }
3863
+ },
3864
+ images.map((src, idx) => {
3865
+ const shouldRender = loadedImages.has(idx);
3866
+ return /* @__PURE__ */ import_react4.default.createElement(
3867
+ "div",
3868
+ {
3869
+ key: idx,
3870
+ style: {
3871
+ position: "absolute",
3872
+ inset: 0,
3873
+ opacity: getOpacity(idx),
3874
+ transform: activeMode === "slide" ? getTransform(idx) : `scale(${getScale(idx)})`,
3875
+ transition: isDragging ? "none" : prefersReducedMotion ? "none" : activeMode === "slide" ? "transform 0.75s cubic-bezier(0.23, 1, 0.32, 1)" : "opacity 0.7s ease, transform 0.7s ease",
3876
+ zIndex: idx === currentIndex ? 2 : 1
3877
+ }
3878
+ },
3879
+ shouldRender && /* @__PURE__ */ import_react4.default.createElement(
3880
+ "img",
3881
+ {
3882
+ src,
3883
+ alt: `Slide ${idx + 1}`,
3884
+ draggable: false,
3885
+ style: {
3886
+ width: "100%",
3887
+ height: "100%",
3888
+ objectFit: "cover",
3889
+ pointerEvents: "none",
3890
+ transformOrigin: "center center",
3891
+ transform: idx === currentIndex ? kb.to : kb.from,
3892
+ transition: prefersReducedMotion ? "none" : `transform ${animDuration}ms ease-out`,
3893
+ willChange: "transform"
3894
+ }
3895
+ }
3896
+ )
3897
+ );
3898
+ }),
3899
+ /* @__PURE__ */ import_react4.default.createElement(
3900
+ "div",
3901
+ {
3902
+ style: {
3903
+ position: "absolute",
3904
+ inset: 0,
3905
+ zIndex: 3,
3906
+ pointerEvents: "none",
3907
+ background: "linear-gradient(to top, rgba(0,0,0,0.65) 0%, rgba(0,0,0,0.2) 40%, transparent 70%)"
3908
+ }
3909
+ }
3910
+ ),
3911
+ /* @__PURE__ */ import_react4.default.createElement(
3912
+ "div",
3913
+ {
3914
+ style: {
3915
+ position: "absolute",
3916
+ inset: 0,
3917
+ zIndex: 3,
3918
+ pointerEvents: "none",
3919
+ background: "linear-gradient(to bottom, rgba(0,0,0,0.3) 0%, transparent 30%)"
3920
+ }
3921
+ }
3922
+ ),
3923
+ showProgress && autoPlay && !isHovered && /* @__PURE__ */ import_react4.default.createElement(
3924
+ "div",
3925
+ {
3926
+ style: {
3927
+ position: "absolute",
3928
+ top: 0,
3929
+ left: 0,
3930
+ right: 0,
3931
+ height: "3px",
3932
+ background: "rgba(255,255,255,0.15)",
3933
+ zIndex: 10
3934
+ }
3935
+ },
3936
+ /* @__PURE__ */ import_react4.default.createElement(
3937
+ "div",
3938
+ {
3939
+ key: progressKey,
3940
+ style: {
3941
+ height: "100%",
3942
+ background: accentColor,
3943
+ animation: prefersReducedMotion ? "none" : `progressFill ${interval}ms linear forwards`,
3944
+ width: prefersReducedMotion ? "100%" : "0%"
3945
+ }
3946
+ }
3947
+ )
3948
+ ),
3949
+ showCaptions && caption && /* @__PURE__ */ import_react4.default.createElement(
3950
+ "div",
3951
+ {
3952
+ style: {
3953
+ position: "absolute",
3954
+ bottom: showThumbnails ? "110px" : "72px",
3955
+ left: 0,
3956
+ right: 0,
3957
+ zIndex: 10,
3958
+ padding: "0 56px 0 32px",
3959
+ transform: captionVisible ? "translateY(0)" : "translateY(16px)",
3960
+ opacity: captionVisible ? 1 : 0,
3961
+ transition: prefersReducedMotion ? "none" : "opacity 0.5s ease, transform 0.5s ease"
3962
+ }
3963
+ },
3964
+ caption.tag && /* @__PURE__ */ import_react4.default.createElement(
3965
+ "span",
3966
+ {
3967
+ style: {
3968
+ display: "inline-block",
3969
+ marginBottom: "8px",
3970
+ background: "rgba(255,255,255,0.15)",
3971
+ backdropFilter: "blur(8px)",
3972
+ border: "0.5px solid rgba(255,255,255,0.25)",
3973
+ color: "#fff",
3974
+ fontSize: "11px",
3975
+ fontWeight: 500,
3976
+ letterSpacing: "0.08em",
3977
+ textTransform: "uppercase",
3978
+ padding: "3px 10px",
3979
+ borderRadius: "100px"
3980
+ }
3981
+ },
3982
+ caption.tag
3983
+ ),
3984
+ caption.title && /* @__PURE__ */ import_react4.default.createElement(
3985
+ "h2",
3986
+ {
3987
+ style: {
3988
+ margin: "0 0 6px",
3989
+ color: "#fff",
3990
+ fontSize: "clamp(18px, 3vw, 28px)",
3991
+ fontWeight: 600,
3992
+ lineHeight: 1.2,
3993
+ textShadow: "0 2px 12px rgba(0,0,0,0.4)"
3994
+ }
3995
+ },
3996
+ caption.title
3997
+ ),
3998
+ caption.subtitle && /* @__PURE__ */ import_react4.default.createElement(
3999
+ "p",
4000
+ {
4001
+ style: {
4002
+ margin: "0 0 14px",
4003
+ color: "rgba(255,255,255,0.78)",
4004
+ fontSize: "clamp(13px, 1.8vw, 15px)",
4005
+ lineHeight: 1.5,
4006
+ textShadow: "0 1px 6px rgba(0,0,0,0.4)",
4007
+ maxWidth: "480px"
4008
+ }
4009
+ },
4010
+ caption.subtitle
4011
+ ),
4012
+ caption.cta && /* @__PURE__ */ import_react4.default.createElement(
4013
+ "button",
4014
+ {
4015
+ onClick: caption.onCta,
4016
+ style: {
4017
+ background: "rgba(255,255,255,0.18)",
4018
+ backdropFilter: "blur(12px)",
4019
+ border: "0.5px solid rgba(255,255,255,0.35)",
4020
+ color: "#fff",
4021
+ padding: "8px 20px",
4022
+ borderRadius: "100px",
4023
+ fontSize: "13px",
4024
+ fontWeight: 500,
4025
+ cursor: "pointer",
4026
+ letterSpacing: "0.02em",
4027
+ transition: "background 0.2s"
4028
+ },
4029
+ onMouseEnter: (e) => e.currentTarget.style.background = "rgba(255,255,255,0.28)",
4030
+ onMouseLeave: (e) => e.currentTarget.style.background = "rgba(255,255,255,0.18)"
4031
+ },
4032
+ caption.cta,
4033
+ " \u2192"
4034
+ )
4035
+ ),
4036
+ showThumbnails && images.length > 1 && /* @__PURE__ */ import_react4.default.createElement(
4037
+ "div",
4038
+ {
4039
+ style: {
4040
+ position: "absolute",
4041
+ bottom: "20px",
4042
+ left: "50%",
4043
+ transform: "translateX(-50%)",
4044
+ zIndex: 10,
4045
+ display: "flex",
4046
+ gap: "6px",
4047
+ maxWidth: "calc(100% - 48px)",
4048
+ overflowX: "auto",
4049
+ scrollbarWidth: "none"
4050
+ }
4051
+ },
4052
+ images.map((src, idx) => /* @__PURE__ */ import_react4.default.createElement(
4053
+ "div",
4054
+ {
4055
+ key: idx,
4056
+ onClick: (e) => {
4057
+ e.stopPropagation();
4058
+ goTo(idx);
4059
+ },
4060
+ style: {
4061
+ width: idx === currentIndex ? "64px" : "44px",
4062
+ height: "40px",
4063
+ flexShrink: 0,
4064
+ borderRadius: "6px",
4065
+ overflow: "hidden",
4066
+ border: idx === currentIndex ? `2px solid ${accentColor}` : "1.5px solid rgba(255,255,255,0.25)",
4067
+ transition: "all 0.35s ease",
4068
+ opacity: idx === currentIndex ? 1 : 0.55,
4069
+ cursor: "pointer"
4070
+ }
4071
+ },
4072
+ /* @__PURE__ */ import_react4.default.createElement(
4073
+ "img",
4074
+ {
4075
+ src,
4076
+ alt: "",
4077
+ style: {
4078
+ width: "100%",
4079
+ height: "100%",
4080
+ objectFit: "cover",
4081
+ display: "block"
4082
+ }
4083
+ }
4084
+ )
4085
+ ))
4086
+ ),
4087
+ showDots && !showThumbnails && images.length > 1 && /* @__PURE__ */ import_react4.default.createElement(
4088
+ "div",
4089
+ {
4090
+ style: {
4091
+ position: "absolute",
4092
+ bottom: "20px",
4093
+ left: "50%",
4094
+ transform: "translateX(-50%)",
4095
+ display: "flex",
4096
+ gap: "6px",
4097
+ zIndex: 10
4098
+ }
4099
+ },
4100
+ images.map((_, idx) => /* @__PURE__ */ import_react4.default.createElement(
4101
+ "div",
4102
+ {
4103
+ key: idx,
4104
+ onClick: () => goTo(idx),
4105
+ style: {
4106
+ width: idx === currentIndex ? "22px" : "7px",
4107
+ height: "7px",
4108
+ borderRadius: "4px",
4109
+ background: accentColor,
4110
+ opacity: idx === currentIndex ? 1 : 0.35,
4111
+ cursor: "pointer",
4112
+ transition: "all 0.35s ease"
4113
+ }
4114
+ }
4115
+ ))
4116
+ ),
4117
+ /* @__PURE__ */ import_react4.default.createElement(
4118
+ NavBtn,
4119
+ {
4120
+ side: "left",
4121
+ onClick: (e) => {
4122
+ e.stopPropagation();
4123
+ handlePrev();
4124
+ },
4125
+ color: accentColor
4126
+ }
4127
+ ),
4128
+ /* @__PURE__ */ import_react4.default.createElement(
4129
+ NavBtn,
4130
+ {
4131
+ side: "right",
4132
+ onClick: (e) => {
4133
+ e.stopPropagation();
4134
+ handleNext();
4135
+ },
4136
+ color: accentColor
4137
+ }
4138
+ ),
4139
+ /* @__PURE__ */ import_react4.default.createElement(
4140
+ "div",
4141
+ {
4142
+ style: {
4143
+ position: "absolute",
4144
+ top: "16px",
4145
+ right: "16px",
4146
+ zIndex: 10,
4147
+ display: "flex",
4148
+ gap: "8px",
4149
+ alignItems: "center"
4150
+ }
4151
+ },
4152
+ /* @__PURE__ */ import_react4.default.createElement(
4153
+ "div",
4154
+ {
4155
+ style: {
4156
+ display: "flex",
4157
+ background: "rgba(0,0,0,0.35)",
4158
+ backdropFilter: "blur(8px)",
4159
+ border: "0.5px solid rgba(255,255,255,0.15)",
4160
+ borderRadius: "100px",
4161
+ padding: "3px",
4162
+ gap: "2px"
4163
+ }
4164
+ },
4165
+ TRANSITION_MODES.map((m) => /* @__PURE__ */ import_react4.default.createElement(
4166
+ "button",
4167
+ {
4168
+ key: m,
4169
+ onClick: (e) => {
4170
+ e.stopPropagation();
4171
+ setActiveMode(m);
4172
+ },
4173
+ title: m,
4174
+ style: {
4175
+ background: activeMode === m ? "rgba(255,255,255,0.25)" : "transparent",
4176
+ border: "none",
4177
+ color: "#fff",
4178
+ fontSize: "10px",
4179
+ fontWeight: 500,
4180
+ padding: "3px 10px",
4181
+ borderRadius: "100px",
4182
+ cursor: "pointer",
4183
+ textTransform: "uppercase",
4184
+ letterSpacing: "0.06em",
4185
+ transition: "background 0.2s"
4186
+ }
4187
+ },
4188
+ m
4189
+ ))
4190
+ ),
4191
+ showCounter && /* @__PURE__ */ import_react4.default.createElement(
4192
+ "div",
4193
+ {
4194
+ style: {
4195
+ background: "rgba(0,0,0,0.35)",
4196
+ backdropFilter: "blur(8px)",
4197
+ border: "0.5px solid rgba(255,255,255,0.15)",
4198
+ borderRadius: "100px",
4199
+ padding: "4px 12px",
4200
+ color: "#fff",
4201
+ fontSize: "12px",
4202
+ fontWeight: 500
4203
+ }
4204
+ },
4205
+ currentIndex + 1,
4206
+ " / ",
4207
+ count
4208
+ ),
4209
+ showFullscreen && /* @__PURE__ */ import_react4.default.createElement(
4210
+ "button",
4211
+ {
4212
+ onClick: (e) => {
4213
+ e.stopPropagation();
4214
+ toggleFullscreen();
4215
+ },
4216
+ style: {
4217
+ background: "rgba(0,0,0,0.35)",
4218
+ backdropFilter: "blur(8px)",
4219
+ border: "0.5px solid rgba(255,255,255,0.15)",
4220
+ borderRadius: "50%",
4221
+ color: "#fff",
4222
+ width: "30px",
4223
+ height: "30px",
4224
+ cursor: "pointer",
4225
+ fontSize: "14px",
4226
+ display: "flex",
4227
+ alignItems: "center",
4228
+ justifyContent: "center",
4229
+ lineHeight: 1
4230
+ },
4231
+ title: "Toggle fullscreen"
4232
+ },
4233
+ isFullscreen ? "\u2921" : "\u2922"
4234
+ )
4235
+ ),
4236
+ /* @__PURE__ */ import_react4.default.createElement("style", null, `
4237
+ @keyframes progressFill {
4238
+ from { width: 0%; }
4239
+ to { width: 100%; }
4240
+ }
4241
+ `)
4242
+ );
4243
+ };
4244
+ var NavBtn = ({ side, onClick, color }) => /* @__PURE__ */ import_react4.default.createElement(
4245
+ "button",
4246
+ {
4247
+ onClick,
4248
+ style: {
4249
+ position: "absolute",
4250
+ [side]: "16px",
4251
+ top: "50%",
4252
+ transform: "translateY(-50%)",
4253
+ background: "rgba(0,0,0,0.3)",
4254
+ backdropFilter: "blur(12px)",
4255
+ border: "0.5px solid rgba(255,255,255,0.2)",
4256
+ color,
4257
+ width: "42px",
4258
+ height: "42px",
4259
+ borderRadius: "50%",
4260
+ cursor: "pointer",
4261
+ zIndex: 10,
4262
+ fontSize: "18px",
4263
+ display: "flex",
4264
+ alignItems: "center",
4265
+ justifyContent: "center",
4266
+ transition: "background 0.2s, transform 0.15s"
4267
+ },
4268
+ onMouseEnter: (e) => {
4269
+ e.currentTarget.style.background = "rgba(0,0,0,0.55)";
4270
+ e.currentTarget.style.transform = "translateY(-50%) scale(1.08)";
4271
+ },
4272
+ onMouseLeave: (e) => {
4273
+ e.currentTarget.style.background = "rgba(0,0,0,0.3)";
4274
+ e.currentTarget.style.transform = "translateY(-50%) scale(1)";
4275
+ }
4276
+ },
4277
+ side === "left" ? "\u2190" : "\u2192"
4278
+ );
3700
4279
  // Annotate the CommonJS export names for ESM import in node:
3701
4280
  0 && (module.exports = {
4281
+ Carousel,
3702
4282
  MagneticButton,
3703
4283
  Navbar,
3704
4284
  SpotlightCard
package/dist/index.mjs CHANGED
@@ -3666,7 +3666,592 @@ var SpotlightCard = ({
3666
3666
  )
3667
3667
  );
3668
3668
  };
3669
+
3670
+ // src/components/Carousel/Carousel.jsx
3671
+ import React4, {
3672
+ useState as useState4,
3673
+ useEffect as useEffect4,
3674
+ useRef as useRef4,
3675
+ useCallback as useCallback4,
3676
+ useMemo
3677
+ } from "react";
3678
+ var TRANSITION_MODES = ["slide", "fade", "zoom"];
3679
+ var KEN_BURNS = [
3680
+ { from: "scale(1.12) translate(2%, 1%)", to: "scale(1) translate(0%, 0%)" },
3681
+ { from: "scale(1.1) translate(-3%, -2%)", to: "scale(1) translate(0%, 0%)" },
3682
+ { from: "scale(1) translate(0%, 0%)", to: "scale(1.1) translate(3%, 2%)" },
3683
+ { from: "scale(1.08) translate(1%, -3%)", to: "scale(1) translate(-1%, 1%)" }
3684
+ ];
3685
+ var DEFAULT_CAPTIONS = [];
3686
+ var prefersReducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
3687
+ var Carousel = ({
3688
+ images = [],
3689
+ captions = DEFAULT_CAPTIONS,
3690
+ height = "520px",
3691
+ borderRadius = "20px",
3692
+ autoPlay = true,
3693
+ interval = 5e3,
3694
+ showDots = true,
3695
+ showThumbnails = true,
3696
+ showProgress = true,
3697
+ showCounter = true,
3698
+ showFullscreen = true,
3699
+ showCaptions = true,
3700
+ accentColor = "#ffffff",
3701
+ transitionMode = "slide",
3702
+ gap = 0
3703
+ }) => {
3704
+ const [currentIndex, setCurrentIndex] = useState4(0);
3705
+ const [prevIndex, setPrevIndex] = useState4(null);
3706
+ const [isDragging, setIsDragging] = useState4(false);
3707
+ const [startX, setStartX] = useState4(0);
3708
+ const [startTime, setStartTime] = useState4(0);
3709
+ const [dragOffset, setDragOffset] = useState4(0);
3710
+ const [isHovered, setIsHovered] = useState4(false);
3711
+ const [isFullscreen, setIsFullscreen] = useState4(false);
3712
+ const [captionVisible, setCaptionVisible] = useState4(true);
3713
+ const [loadedImages, setLoadedImages] = useState4(/* @__PURE__ */ new Set([0]));
3714
+ const [activeMode, setActiveMode] = useState4(transitionMode);
3715
+ const [progressKey, setProgressKey] = useState4(0);
3716
+ const containerRef = useRef4(null);
3717
+ const timerRef = useRef4(null);
3718
+ const count = images.length;
3719
+ const goTo = useCallback4(
3720
+ (index, direction) => {
3721
+ const next = (index % count + count) % count;
3722
+ setCaptionVisible(false);
3723
+ setPrevIndex(currentIndex);
3724
+ setTimeout(() => {
3725
+ setCurrentIndex(next);
3726
+ setProgressKey((k) => k + 1);
3727
+ setLoadedImages((prev) => {
3728
+ const s = new Set(prev);
3729
+ s.add(next);
3730
+ s.add((next + 1) % count);
3731
+ return s;
3732
+ });
3733
+ setTimeout(() => setCaptionVisible(true), 80);
3734
+ }, 40);
3735
+ },
3736
+ [currentIndex, count]
3737
+ );
3738
+ const handleNext = useCallback4(
3739
+ () => goTo(currentIndex + 1),
3740
+ [goTo, currentIndex]
3741
+ );
3742
+ const handlePrev = useCallback4(
3743
+ () => goTo(currentIndex - 1),
3744
+ [goTo, currentIndex]
3745
+ );
3746
+ useEffect4(() => {
3747
+ if (!autoPlay || isHovered || isDragging) return;
3748
+ timerRef.current = setInterval(handleNext, interval);
3749
+ return () => clearInterval(timerRef.current);
3750
+ }, [autoPlay, isHovered, isDragging, handleNext, interval, currentIndex]);
3751
+ useEffect4(() => {
3752
+ const onKey = (e) => {
3753
+ if (e.key === "ArrowRight") handleNext();
3754
+ if (e.key === "ArrowLeft") handlePrev();
3755
+ if (e.key === "Escape" && isFullscreen) exitFullscreen();
3756
+ const num = parseInt(e.key);
3757
+ if (!isNaN(num) && num >= 1 && num <= count) goTo(num - 1);
3758
+ };
3759
+ window.addEventListener("keydown", onKey);
3760
+ return () => window.removeEventListener("keydown", onKey);
3761
+ }, [handleNext, handlePrev, isFullscreen, count, goTo]);
3762
+ useEffect4(() => {
3763
+ const onFsChange = () => {
3764
+ setIsFullscreen(!!document.fullscreenElement);
3765
+ };
3766
+ document.addEventListener("fullscreenchange", onFsChange);
3767
+ return () => document.removeEventListener("fullscreenchange", onFsChange);
3768
+ }, []);
3769
+ const toggleFullscreen = () => {
3770
+ var _a;
3771
+ if (!document.fullscreenElement) {
3772
+ (_a = containerRef.current) == null ? void 0 : _a.requestFullscreen();
3773
+ } else {
3774
+ document.exitFullscreen();
3775
+ }
3776
+ };
3777
+ const exitFullscreen = () => document.exitFullscreen();
3778
+ const onStart = (e) => {
3779
+ setIsDragging(true);
3780
+ const x = e.type.includes("mouse") ? e.pageX : e.touches[0].pageX;
3781
+ setStartX(x);
3782
+ setStartTime(Date.now());
3783
+ };
3784
+ const onMove = (e) => {
3785
+ if (!isDragging) return;
3786
+ const x = e.type.includes("mouse") ? e.pageX : e.touches[0].pageX;
3787
+ setDragOffset(x - startX);
3788
+ };
3789
+ const onEnd = () => {
3790
+ if (!isDragging) return;
3791
+ const velocity = dragOffset / (Date.now() - startTime);
3792
+ const threshold = Math.abs(velocity) > 0.4 ? 30 : 80;
3793
+ if (dragOffset < -threshold) handleNext();
3794
+ else if (dragOffset > threshold) handlePrev();
3795
+ setIsDragging(false);
3796
+ setDragOffset(0);
3797
+ };
3798
+ const kb = KEN_BURNS[currentIndex % KEN_BURNS.length];
3799
+ const animDuration = prefersReducedMotion ? 0 : interval + 500;
3800
+ const getTransform = (idx) => {
3801
+ var _a;
3802
+ if (activeMode !== "slide") return "translateX(0)";
3803
+ const base = (idx - currentIndex) * 100;
3804
+ const drag = isDragging ? dragOffset / (((_a = containerRef.current) == null ? void 0 : _a.offsetWidth) || 1) * 100 : 0;
3805
+ return `translateX(calc(${base}% + ${drag}px))`;
3806
+ };
3807
+ const getOpacity = (idx) => activeMode === "slide" ? 1 : idx === currentIndex ? 1 : 0;
3808
+ const getScale = (idx) => activeMode === "zoom" && idx === currentIndex ? 1 : activeMode === "zoom" ? 0.9 : 1;
3809
+ const caption = captions[currentIndex];
3810
+ return /* @__PURE__ */ React4.createElement(
3811
+ "div",
3812
+ {
3813
+ ref: containerRef,
3814
+ onMouseEnter: () => setIsHovered(true),
3815
+ onMouseLeave: () => {
3816
+ setIsHovered(false);
3817
+ onEnd();
3818
+ },
3819
+ onMouseDown: onStart,
3820
+ onMouseMove: onMove,
3821
+ onMouseUp: onEnd,
3822
+ onTouchStart: onStart,
3823
+ onTouchMove: onMove,
3824
+ onTouchEnd: onEnd,
3825
+ style: {
3826
+ position: "relative",
3827
+ width: "100%",
3828
+ height: isFullscreen ? "100vh" : height,
3829
+ borderRadius: isFullscreen ? 0 : borderRadius,
3830
+ overflow: "hidden",
3831
+ background: "#000",
3832
+ cursor: isDragging ? "grabbing" : "grab",
3833
+ userSelect: "none",
3834
+ WebkitUserSelect: "none",
3835
+ fontFamily: "system-ui, sans-serif"
3836
+ }
3837
+ },
3838
+ images.map((src, idx) => {
3839
+ const shouldRender = loadedImages.has(idx);
3840
+ return /* @__PURE__ */ React4.createElement(
3841
+ "div",
3842
+ {
3843
+ key: idx,
3844
+ style: {
3845
+ position: "absolute",
3846
+ inset: 0,
3847
+ opacity: getOpacity(idx),
3848
+ transform: activeMode === "slide" ? getTransform(idx) : `scale(${getScale(idx)})`,
3849
+ transition: isDragging ? "none" : prefersReducedMotion ? "none" : activeMode === "slide" ? "transform 0.75s cubic-bezier(0.23, 1, 0.32, 1)" : "opacity 0.7s ease, transform 0.7s ease",
3850
+ zIndex: idx === currentIndex ? 2 : 1
3851
+ }
3852
+ },
3853
+ shouldRender && /* @__PURE__ */ React4.createElement(
3854
+ "img",
3855
+ {
3856
+ src,
3857
+ alt: `Slide ${idx + 1}`,
3858
+ draggable: false,
3859
+ style: {
3860
+ width: "100%",
3861
+ height: "100%",
3862
+ objectFit: "cover",
3863
+ pointerEvents: "none",
3864
+ transformOrigin: "center center",
3865
+ transform: idx === currentIndex ? kb.to : kb.from,
3866
+ transition: prefersReducedMotion ? "none" : `transform ${animDuration}ms ease-out`,
3867
+ willChange: "transform"
3868
+ }
3869
+ }
3870
+ )
3871
+ );
3872
+ }),
3873
+ /* @__PURE__ */ React4.createElement(
3874
+ "div",
3875
+ {
3876
+ style: {
3877
+ position: "absolute",
3878
+ inset: 0,
3879
+ zIndex: 3,
3880
+ pointerEvents: "none",
3881
+ background: "linear-gradient(to top, rgba(0,0,0,0.65) 0%, rgba(0,0,0,0.2) 40%, transparent 70%)"
3882
+ }
3883
+ }
3884
+ ),
3885
+ /* @__PURE__ */ React4.createElement(
3886
+ "div",
3887
+ {
3888
+ style: {
3889
+ position: "absolute",
3890
+ inset: 0,
3891
+ zIndex: 3,
3892
+ pointerEvents: "none",
3893
+ background: "linear-gradient(to bottom, rgba(0,0,0,0.3) 0%, transparent 30%)"
3894
+ }
3895
+ }
3896
+ ),
3897
+ showProgress && autoPlay && !isHovered && /* @__PURE__ */ React4.createElement(
3898
+ "div",
3899
+ {
3900
+ style: {
3901
+ position: "absolute",
3902
+ top: 0,
3903
+ left: 0,
3904
+ right: 0,
3905
+ height: "3px",
3906
+ background: "rgba(255,255,255,0.15)",
3907
+ zIndex: 10
3908
+ }
3909
+ },
3910
+ /* @__PURE__ */ React4.createElement(
3911
+ "div",
3912
+ {
3913
+ key: progressKey,
3914
+ style: {
3915
+ height: "100%",
3916
+ background: accentColor,
3917
+ animation: prefersReducedMotion ? "none" : `progressFill ${interval}ms linear forwards`,
3918
+ width: prefersReducedMotion ? "100%" : "0%"
3919
+ }
3920
+ }
3921
+ )
3922
+ ),
3923
+ showCaptions && caption && /* @__PURE__ */ React4.createElement(
3924
+ "div",
3925
+ {
3926
+ style: {
3927
+ position: "absolute",
3928
+ bottom: showThumbnails ? "110px" : "72px",
3929
+ left: 0,
3930
+ right: 0,
3931
+ zIndex: 10,
3932
+ padding: "0 56px 0 32px",
3933
+ transform: captionVisible ? "translateY(0)" : "translateY(16px)",
3934
+ opacity: captionVisible ? 1 : 0,
3935
+ transition: prefersReducedMotion ? "none" : "opacity 0.5s ease, transform 0.5s ease"
3936
+ }
3937
+ },
3938
+ caption.tag && /* @__PURE__ */ React4.createElement(
3939
+ "span",
3940
+ {
3941
+ style: {
3942
+ display: "inline-block",
3943
+ marginBottom: "8px",
3944
+ background: "rgba(255,255,255,0.15)",
3945
+ backdropFilter: "blur(8px)",
3946
+ border: "0.5px solid rgba(255,255,255,0.25)",
3947
+ color: "#fff",
3948
+ fontSize: "11px",
3949
+ fontWeight: 500,
3950
+ letterSpacing: "0.08em",
3951
+ textTransform: "uppercase",
3952
+ padding: "3px 10px",
3953
+ borderRadius: "100px"
3954
+ }
3955
+ },
3956
+ caption.tag
3957
+ ),
3958
+ caption.title && /* @__PURE__ */ React4.createElement(
3959
+ "h2",
3960
+ {
3961
+ style: {
3962
+ margin: "0 0 6px",
3963
+ color: "#fff",
3964
+ fontSize: "clamp(18px, 3vw, 28px)",
3965
+ fontWeight: 600,
3966
+ lineHeight: 1.2,
3967
+ textShadow: "0 2px 12px rgba(0,0,0,0.4)"
3968
+ }
3969
+ },
3970
+ caption.title
3971
+ ),
3972
+ caption.subtitle && /* @__PURE__ */ React4.createElement(
3973
+ "p",
3974
+ {
3975
+ style: {
3976
+ margin: "0 0 14px",
3977
+ color: "rgba(255,255,255,0.78)",
3978
+ fontSize: "clamp(13px, 1.8vw, 15px)",
3979
+ lineHeight: 1.5,
3980
+ textShadow: "0 1px 6px rgba(0,0,0,0.4)",
3981
+ maxWidth: "480px"
3982
+ }
3983
+ },
3984
+ caption.subtitle
3985
+ ),
3986
+ caption.cta && /* @__PURE__ */ React4.createElement(
3987
+ "button",
3988
+ {
3989
+ onClick: caption.onCta,
3990
+ style: {
3991
+ background: "rgba(255,255,255,0.18)",
3992
+ backdropFilter: "blur(12px)",
3993
+ border: "0.5px solid rgba(255,255,255,0.35)",
3994
+ color: "#fff",
3995
+ padding: "8px 20px",
3996
+ borderRadius: "100px",
3997
+ fontSize: "13px",
3998
+ fontWeight: 500,
3999
+ cursor: "pointer",
4000
+ letterSpacing: "0.02em",
4001
+ transition: "background 0.2s"
4002
+ },
4003
+ onMouseEnter: (e) => e.currentTarget.style.background = "rgba(255,255,255,0.28)",
4004
+ onMouseLeave: (e) => e.currentTarget.style.background = "rgba(255,255,255,0.18)"
4005
+ },
4006
+ caption.cta,
4007
+ " \u2192"
4008
+ )
4009
+ ),
4010
+ showThumbnails && images.length > 1 && /* @__PURE__ */ React4.createElement(
4011
+ "div",
4012
+ {
4013
+ style: {
4014
+ position: "absolute",
4015
+ bottom: "20px",
4016
+ left: "50%",
4017
+ transform: "translateX(-50%)",
4018
+ zIndex: 10,
4019
+ display: "flex",
4020
+ gap: "6px",
4021
+ maxWidth: "calc(100% - 48px)",
4022
+ overflowX: "auto",
4023
+ scrollbarWidth: "none"
4024
+ }
4025
+ },
4026
+ images.map((src, idx) => /* @__PURE__ */ React4.createElement(
4027
+ "div",
4028
+ {
4029
+ key: idx,
4030
+ onClick: (e) => {
4031
+ e.stopPropagation();
4032
+ goTo(idx);
4033
+ },
4034
+ style: {
4035
+ width: idx === currentIndex ? "64px" : "44px",
4036
+ height: "40px",
4037
+ flexShrink: 0,
4038
+ borderRadius: "6px",
4039
+ overflow: "hidden",
4040
+ border: idx === currentIndex ? `2px solid ${accentColor}` : "1.5px solid rgba(255,255,255,0.25)",
4041
+ transition: "all 0.35s ease",
4042
+ opacity: idx === currentIndex ? 1 : 0.55,
4043
+ cursor: "pointer"
4044
+ }
4045
+ },
4046
+ /* @__PURE__ */ React4.createElement(
4047
+ "img",
4048
+ {
4049
+ src,
4050
+ alt: "",
4051
+ style: {
4052
+ width: "100%",
4053
+ height: "100%",
4054
+ objectFit: "cover",
4055
+ display: "block"
4056
+ }
4057
+ }
4058
+ )
4059
+ ))
4060
+ ),
4061
+ showDots && !showThumbnails && images.length > 1 && /* @__PURE__ */ React4.createElement(
4062
+ "div",
4063
+ {
4064
+ style: {
4065
+ position: "absolute",
4066
+ bottom: "20px",
4067
+ left: "50%",
4068
+ transform: "translateX(-50%)",
4069
+ display: "flex",
4070
+ gap: "6px",
4071
+ zIndex: 10
4072
+ }
4073
+ },
4074
+ images.map((_, idx) => /* @__PURE__ */ React4.createElement(
4075
+ "div",
4076
+ {
4077
+ key: idx,
4078
+ onClick: () => goTo(idx),
4079
+ style: {
4080
+ width: idx === currentIndex ? "22px" : "7px",
4081
+ height: "7px",
4082
+ borderRadius: "4px",
4083
+ background: accentColor,
4084
+ opacity: idx === currentIndex ? 1 : 0.35,
4085
+ cursor: "pointer",
4086
+ transition: "all 0.35s ease"
4087
+ }
4088
+ }
4089
+ ))
4090
+ ),
4091
+ /* @__PURE__ */ React4.createElement(
4092
+ NavBtn,
4093
+ {
4094
+ side: "left",
4095
+ onClick: (e) => {
4096
+ e.stopPropagation();
4097
+ handlePrev();
4098
+ },
4099
+ color: accentColor
4100
+ }
4101
+ ),
4102
+ /* @__PURE__ */ React4.createElement(
4103
+ NavBtn,
4104
+ {
4105
+ side: "right",
4106
+ onClick: (e) => {
4107
+ e.stopPropagation();
4108
+ handleNext();
4109
+ },
4110
+ color: accentColor
4111
+ }
4112
+ ),
4113
+ /* @__PURE__ */ React4.createElement(
4114
+ "div",
4115
+ {
4116
+ style: {
4117
+ position: "absolute",
4118
+ top: "16px",
4119
+ right: "16px",
4120
+ zIndex: 10,
4121
+ display: "flex",
4122
+ gap: "8px",
4123
+ alignItems: "center"
4124
+ }
4125
+ },
4126
+ /* @__PURE__ */ React4.createElement(
4127
+ "div",
4128
+ {
4129
+ style: {
4130
+ display: "flex",
4131
+ background: "rgba(0,0,0,0.35)",
4132
+ backdropFilter: "blur(8px)",
4133
+ border: "0.5px solid rgba(255,255,255,0.15)",
4134
+ borderRadius: "100px",
4135
+ padding: "3px",
4136
+ gap: "2px"
4137
+ }
4138
+ },
4139
+ TRANSITION_MODES.map((m) => /* @__PURE__ */ React4.createElement(
4140
+ "button",
4141
+ {
4142
+ key: m,
4143
+ onClick: (e) => {
4144
+ e.stopPropagation();
4145
+ setActiveMode(m);
4146
+ },
4147
+ title: m,
4148
+ style: {
4149
+ background: activeMode === m ? "rgba(255,255,255,0.25)" : "transparent",
4150
+ border: "none",
4151
+ color: "#fff",
4152
+ fontSize: "10px",
4153
+ fontWeight: 500,
4154
+ padding: "3px 10px",
4155
+ borderRadius: "100px",
4156
+ cursor: "pointer",
4157
+ textTransform: "uppercase",
4158
+ letterSpacing: "0.06em",
4159
+ transition: "background 0.2s"
4160
+ }
4161
+ },
4162
+ m
4163
+ ))
4164
+ ),
4165
+ showCounter && /* @__PURE__ */ React4.createElement(
4166
+ "div",
4167
+ {
4168
+ style: {
4169
+ background: "rgba(0,0,0,0.35)",
4170
+ backdropFilter: "blur(8px)",
4171
+ border: "0.5px solid rgba(255,255,255,0.15)",
4172
+ borderRadius: "100px",
4173
+ padding: "4px 12px",
4174
+ color: "#fff",
4175
+ fontSize: "12px",
4176
+ fontWeight: 500
4177
+ }
4178
+ },
4179
+ currentIndex + 1,
4180
+ " / ",
4181
+ count
4182
+ ),
4183
+ showFullscreen && /* @__PURE__ */ React4.createElement(
4184
+ "button",
4185
+ {
4186
+ onClick: (e) => {
4187
+ e.stopPropagation();
4188
+ toggleFullscreen();
4189
+ },
4190
+ style: {
4191
+ background: "rgba(0,0,0,0.35)",
4192
+ backdropFilter: "blur(8px)",
4193
+ border: "0.5px solid rgba(255,255,255,0.15)",
4194
+ borderRadius: "50%",
4195
+ color: "#fff",
4196
+ width: "30px",
4197
+ height: "30px",
4198
+ cursor: "pointer",
4199
+ fontSize: "14px",
4200
+ display: "flex",
4201
+ alignItems: "center",
4202
+ justifyContent: "center",
4203
+ lineHeight: 1
4204
+ },
4205
+ title: "Toggle fullscreen"
4206
+ },
4207
+ isFullscreen ? "\u2921" : "\u2922"
4208
+ )
4209
+ ),
4210
+ /* @__PURE__ */ React4.createElement("style", null, `
4211
+ @keyframes progressFill {
4212
+ from { width: 0%; }
4213
+ to { width: 100%; }
4214
+ }
4215
+ `)
4216
+ );
4217
+ };
4218
+ var NavBtn = ({ side, onClick, color }) => /* @__PURE__ */ React4.createElement(
4219
+ "button",
4220
+ {
4221
+ onClick,
4222
+ style: {
4223
+ position: "absolute",
4224
+ [side]: "16px",
4225
+ top: "50%",
4226
+ transform: "translateY(-50%)",
4227
+ background: "rgba(0,0,0,0.3)",
4228
+ backdropFilter: "blur(12px)",
4229
+ border: "0.5px solid rgba(255,255,255,0.2)",
4230
+ color,
4231
+ width: "42px",
4232
+ height: "42px",
4233
+ borderRadius: "50%",
4234
+ cursor: "pointer",
4235
+ zIndex: 10,
4236
+ fontSize: "18px",
4237
+ display: "flex",
4238
+ alignItems: "center",
4239
+ justifyContent: "center",
4240
+ transition: "background 0.2s, transform 0.15s"
4241
+ },
4242
+ onMouseEnter: (e) => {
4243
+ e.currentTarget.style.background = "rgba(0,0,0,0.55)";
4244
+ e.currentTarget.style.transform = "translateY(-50%) scale(1.08)";
4245
+ },
4246
+ onMouseLeave: (e) => {
4247
+ e.currentTarget.style.background = "rgba(0,0,0,0.3)";
4248
+ e.currentTarget.style.transform = "translateY(-50%) scale(1)";
4249
+ }
4250
+ },
4251
+ side === "left" ? "\u2190" : "\u2192"
4252
+ );
3669
4253
  export {
4254
+ Carousel,
3670
4255
  MagneticButton,
3671
4256
  Navbar,
3672
4257
  SpotlightCard
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aura-ui-library",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "A modern and customizable UI library for React applications.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",