nexlide 1.1.0 โ 1.1.1
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 +76 -46
- package/dist/Carousel.d.ts +6 -6
- package/dist/index.esm.js +4 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/animationVariants.d.ts +2 -0
- package/package.json +1 -1
- package/dist/lib/animations.d.ts +0 -2
package/README.md
CHANGED
|
@@ -15,12 +15,14 @@
|
|
|
15
15
|
|
|
16
16
|
A modern, lightweight, and fully customizable React carousel component built with **Framer Motion** for smooth animations and **Tailwind CSS** for flexible styling.
|
|
17
17
|
|
|
18
|
+
---
|
|
19
|
+
|
|
18
20
|
## โจ Features
|
|
19
21
|
|
|
20
22
|
### Core
|
|
21
23
|
- **Smooth slide transitions** with 10+ animation variants (fade, slide, zoom, bounce, flip)
|
|
22
24
|
- **Independent caption animations** with customizable delay (0.5s default) and duration (0.8s default)
|
|
23
|
-
- **Full RTL support**
|
|
25
|
+
- **Full RTL support** โ mirrored navigation, reversed swipe, and proper layout for Arabic, Hebrew, Persian, and other RTL languages
|
|
24
26
|
- **Intelligent autoplay system** with direction control (`forward` | `reverse`) and smart pause behaviors
|
|
25
27
|
- **Advanced touch/swipe gestures** with Framer Motion โ inertia scrolling and elastic snap-back
|
|
26
28
|
- **Accessibility first** โ ARIA labels, keyboard navigation, visible focus rings
|
|
@@ -30,7 +32,7 @@ A modern, lightweight, and fully customizable React carousel component built wit
|
|
|
30
32
|
- **Zero CSS imports** โ uses Tailwind classes inline
|
|
31
33
|
- **Next.js App Router ready** with `'use client'` directive
|
|
32
34
|
|
|
33
|
-
### ๐ What's New in v1.1.0
|
|
35
|
+
### ๐ What's New in v1.1.0?
|
|
34
36
|
|
|
35
37
|
#### Enhanced Autoplay Control
|
|
36
38
|
- **`autoPlayDirection`** โ Choose between `"forward"` (next slide) or `"reverse"` (previous slide) for autoplay progression
|
|
@@ -41,7 +43,7 @@ A modern, lightweight, and fully customizable React carousel component built wit
|
|
|
41
43
|
- **Tab visibility awareness** โ Autoplay automatically pauses when the page/tab is hidden and resumes when visible
|
|
42
44
|
|
|
43
45
|
#### Complete RTL Support
|
|
44
|
-
|
|
46
|
+
**`rtl` prop** โ Enables full right-to-left mode with:
|
|
45
47
|
- Reversed swipe/drag direction (swipe left โ next slide)
|
|
46
48
|
- Swapped navigation arrow positions and functions
|
|
47
49
|
- Default animation switches to `slideRight` (if not overridden)
|
|
@@ -59,6 +61,8 @@ A modern, lightweight, and fully customizable React carousel component built wit
|
|
|
59
61
|
- **Touch-optimized** โ Removed legacy touch handlers for cleaner, more performant code
|
|
60
62
|
- **Visual polish** โ Improved focus outlines and pointer-events handling
|
|
61
63
|
|
|
64
|
+
---
|
|
65
|
+
|
|
62
66
|
## ๐งฉ Supports
|
|
63
67
|
|
|
64
68
|
### Navigation & Controls
|
|
@@ -125,24 +129,26 @@ A modern, lightweight, and fully customizable React carousel component built wit
|
|
|
125
129
|
| `dotClassName` | Individual pagination dots |
|
|
126
130
|
|
|
127
131
|
### Performance Optimizations
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
-
|
|
131
|
-
-
|
|
132
|
+
- **Lazy loading** โ Non-active slides use `loading="lazy"`
|
|
133
|
+
- **Image optimization** โ `decoding="async"`, `draggable=false`
|
|
134
|
+
- **Clean architecture** โ No legacy touch handlers
|
|
135
|
+
- **Smart re-renders** โ Optimized with `useCallback` and `useMemo`
|
|
132
136
|
|
|
133
137
|
### Accessibility
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
-
|
|
138
|
+
- **Visible focus ring** โ Clear keyboard navigation indicators
|
|
139
|
+
- **ARIA labels** โ Proper roles and descriptions
|
|
140
|
+
- **Full keyboard support** โ Arrow keys, tab navigation
|
|
141
|
+
- **Live regions** โ `aria-live="polite"` (off when autoplay active)
|
|
142
|
+
- **Focus management** โ Container receives focus, maintains context
|
|
139
143
|
|
|
140
144
|
### Technical Stack
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
-
|
|
145
|
-
-
|
|
145
|
+
- **React 18+** โ Modern hooks architecture
|
|
146
|
+
- **Framer Motion** โ Production-ready animations
|
|
147
|
+
- **Tailwind CSS v4** โ Utility-first styling
|
|
148
|
+
- **TypeScript** โ Full type definitions included
|
|
149
|
+
- **Next.js** โ App Router compatible with `'use client'`
|
|
150
|
+
|
|
151
|
+
---
|
|
146
152
|
|
|
147
153
|
## โ๏ธ Installation
|
|
148
154
|
|
|
@@ -154,7 +160,6 @@ yarn add nexlide
|
|
|
154
160
|
pnpm add nexlide
|
|
155
161
|
```
|
|
156
162
|
|
|
157
|
-
|
|
158
163
|
## ๐ฆ Peer Dependencies
|
|
159
164
|
|
|
160
165
|
These dependencies are usually already present in React / Next.js projects:
|
|
@@ -174,8 +179,11 @@ If you are customizing or extending the component and want to reuse this utility
|
|
|
174
179
|
|
|
175
180
|
> โ ๏ธ These are already bundled within Nexlide and **do NOT need to be installed manually** unless you plan to use the same utility pattern in your own components.
|
|
176
181
|
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## ๐ Usage
|
|
177
185
|
|
|
178
|
-
|
|
186
|
+
### Basic Example (Next.js App Router)
|
|
179
187
|
|
|
180
188
|
The component is a **Client Component** โ you **must** use it inside a file that starts with `'use client';`
|
|
181
189
|
|
|
@@ -197,13 +205,6 @@ const carouselItems = [
|
|
|
197
205
|
imageUrl: "https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?w=1200&q=75&fm=webp",
|
|
198
206
|
title: "Vibrant Night City",
|
|
199
207
|
},
|
|
200
|
-
{
|
|
201
|
-
imageUrl: "https://images.unsplash.com/photo-1757843298369-6e5503c14bfd?w=1200&q=75&fm=webp",
|
|
202
|
-
description: "Neon and motion in the city that never sleeps",
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
imageUrl: "https://images.unsplash.com/photo-1482192505345-5655af888cc4?w=1200&q=75&fm=webp",
|
|
206
|
-
},
|
|
207
208
|
// ...
|
|
208
209
|
];
|
|
209
210
|
|
|
@@ -226,8 +227,47 @@ export default function MyPage() {
|
|
|
226
227
|
}
|
|
227
228
|
```
|
|
228
229
|
|
|
229
|
-
|
|
230
|
+
### React Standard (No Next.js)
|
|
231
|
+
|
|
232
|
+
If you're using Pages Router, Create React App, or any other React setup without App Router restrictions, you can omit the `'use client';` directive.
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
import { Carousel } from 'nexlide'
|
|
236
|
+
|
|
237
|
+
// ... your component logic (same as above)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Example usage in RTL context
|
|
241
|
+
|
|
242
|
+
For right-to-left languages (Arabic, Hebrew, Persian, etc.), enable the `rtl` prop to automatically adapt the carousel's behavior and layout.
|
|
243
|
+
|
|
244
|
+
```tsx
|
|
245
|
+
'use client';
|
|
246
|
+
|
|
247
|
+
import { Carousel } from 'nexlide'
|
|
248
|
+
|
|
249
|
+
const items = [ /* ... */ ];
|
|
250
|
+
|
|
251
|
+
export default function RTLPage() {
|
|
252
|
+
return (
|
|
253
|
+
<div className="p-8" dir="rtl"> {/* Optional: Set dir on a parent */}
|
|
254
|
+
<Carousel
|
|
255
|
+
rtl={true} // Enables full RTL support
|
|
256
|
+
items={items}
|
|
257
|
+
autoPlay
|
|
258
|
+
autoPlayInterval={4000}
|
|
259
|
+
animation="slideRight" // Recommended for RTL, but optional
|
|
260
|
+
showArrows
|
|
261
|
+
showPagination
|
|
262
|
+
/>
|
|
263
|
+
</div>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Note:** If you are using a standard React setup without App Router restrictions, you can omit `'use client';`.
|
|
230
269
|
|
|
270
|
+
---
|
|
231
271
|
|
|
232
272
|
## ๐ Available Animations
|
|
233
273
|
|
|
@@ -248,6 +288,7 @@ Use `animation` for the image slide transition and `captionAnimation` for the ti
|
|
|
248
288
|
|
|
249
289
|
All animations use smooth easing curves and can be combined freely (e.g., slideLeft for image + bounce for caption). Adjust timing with `captionDelay` prop if needed.
|
|
250
290
|
|
|
291
|
+
---
|
|
251
292
|
|
|
252
293
|
## ๐ง Props
|
|
253
294
|
|
|
@@ -255,23 +296,23 @@ All animations use smooth easing curves and can be combined freely (e.g., slideL
|
|
|
255
296
|
|-------------------|-----------|-------------|-----------------------------------------------------------------------------|
|
|
256
297
|
| `items` | `CarouselItem[]` | โ **(required)** | Array of carousel items. Each item must include `imageUrl`, while `title` and `description` are optional. |
|
|
257
298
|
| `autoPlay` | `boolean` | `false` | Whether the carousel should automatically advance to the next slide. |
|
|
258
|
-
| `autoPlayInterval
|
|
259
|
-
| `autoPlayDirection
|
|
299
|
+
| `autoPlayInterval` | `number` | `3000` | Interval in milliseconds between automatic slides (only used when `autoPlay` is `true`). |
|
|
300
|
+
| `autoPlayDirection๐` | `"forward" \| "reverse"` | `"forward"` | Direction of autoplay: `"forward"` (normal) or `"reverse"` (backward). |
|
|
260
301
|
| `infiniteLoop` | `boolean` | `true` | Enable infinite looping (goes back to first slide after last). |
|
|
261
302
|
| `pauseOnHover` ๐ | `boolean` | `true` | Pause autoplay when the user hovers over the carousel. |
|
|
262
303
|
| `pauseOnFocus` ๐ | `boolean` | `true` | Pause autoplay when the carousel receives focus (improves accessibility). |
|
|
263
304
|
| `pauseOnDrag` ๐ | `boolean` | `true` | Pause autoplay while the user is actively dragging/swiping the carousel. |
|
|
264
305
|
| `showPagination` | `boolean` | `true` | Show/hide pagination dots. By default at the bottom. |
|
|
265
306
|
| `showArrows` | `boolean` | `true` | Show/hide navigation arrows on the sides. |
|
|
266
|
-
| `animation` | `AnimationType` | Animation type for slide transitions. |
|
|
307
|
+
| `animation` | `AnimationType` | `"slideLeft"` | Animation type for slide transitions. |
|
|
267
308
|
| `rtl` ๐ | `boolean` | `false` | Enable right-to-left (RTL) mode. Reverses swipe direction, arrow positions, autoplay direction (if not overridden), and default animation. Ideal for Arabic, Hebrew, etc. |
|
|
268
|
-
| `className`
|
|
309
|
+
| `className` | `string` | โ | Additional Tailwind classes for the main carousel container. |
|
|
269
310
|
| `slideClassName` | `string` | โ | Additional classes for each slide wrapper. |
|
|
270
|
-
| `captionClassName
|
|
311
|
+
| `captionClassName` | `string` | โ | Additional classes for the caption overlay container. |
|
|
271
312
|
| `arrowClassName` | `string` | โ | Additional classes for navigation arrows. |
|
|
272
313
|
| `paginationClassName` | `string` | โ | Additional classes for the pagination dots container. |
|
|
273
314
|
| `dotClassName` | `string` | โ | Additional classes for individual pagination dots. |
|
|
274
|
-
| `captionAnimation`| `AnimationType` | Animation type for the caption appearance. |
|
|
315
|
+
| `captionAnimation`| `AnimationType` | `"fade"` | Animation type for the caption appearance. |
|
|
275
316
|
| `captionDelay` | `number` | `0.5` | Delay in seconds before the caption animation starts (after slide appears). |
|
|
276
317
|
| `captionDuration` ๐ | `number` | `0.8` | Duration in seconds of the caption animation itself. | |
|
|
277
318
|
|
|
@@ -304,19 +345,7 @@ When `rtl={true}`, the carousel automatically adapts for right-to-left languages
|
|
|
304
345
|
|
|
305
346
|
- **Layout & direction**: `dir="rtl"` is applied to the root container, ensuring correct text flow, gradient direction, positioning, and CSS mirroring
|
|
306
347
|
|
|
307
|
-
|
|
308
|
-
```tsx
|
|
309
|
-
<Carousel
|
|
310
|
-
rtl={true}
|
|
311
|
-
items={items}
|
|
312
|
-
autoPlay
|
|
313
|
-
autoPlayInterval={4000}
|
|
314
|
-
animation="slideRight" // recommended, but optional
|
|
315
|
-
showArrows
|
|
316
|
-
showPagination
|
|
317
|
-
/>
|
|
318
|
-
```
|
|
319
|
-
|
|
348
|
+
---
|
|
320
349
|
|
|
321
350
|
## ๐ ๏ธ Development
|
|
322
351
|
|
|
@@ -336,6 +365,7 @@ npm pack
|
|
|
336
365
|
# Then in your test project: npm install ../nexlide/nexlide-1.0.0.tgz
|
|
337
366
|
```
|
|
338
367
|
|
|
368
|
+
---
|
|
339
369
|
|
|
340
370
|
## ๐ License
|
|
341
371
|
|
package/dist/Carousel.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { animationVariants } from "./lib/animationVariants";
|
|
3
3
|
interface CarouselItem {
|
|
4
4
|
imageUrl: string;
|
|
5
5
|
title?: string;
|
|
@@ -11,22 +11,22 @@ interface CarouselProps {
|
|
|
11
11
|
autoPlayInterval?: number;
|
|
12
12
|
autoPlayDirection?: "forward" | "reverse";
|
|
13
13
|
infiniteLoop?: boolean;
|
|
14
|
+
rtl?: boolean;
|
|
14
15
|
pauseOnHover?: boolean;
|
|
15
16
|
pauseOnFocus?: boolean;
|
|
16
17
|
pauseOnDrag?: boolean;
|
|
17
18
|
showPagination?: boolean;
|
|
18
19
|
showArrows?: boolean;
|
|
19
|
-
animation?: keyof typeof
|
|
20
|
-
|
|
20
|
+
animation?: keyof typeof animationVariants;
|
|
21
|
+
captionAnimation?: keyof typeof animationVariants;
|
|
22
|
+
captionDelay?: number;
|
|
23
|
+
captionDuration?: number;
|
|
21
24
|
className?: string;
|
|
22
25
|
slideClassName?: string;
|
|
23
26
|
arrowClassName?: string;
|
|
24
27
|
paginationClassName?: string;
|
|
25
28
|
dotClassName?: string;
|
|
26
29
|
captionClassName?: string;
|
|
27
|
-
captionAnimation?: keyof typeof slideVariants;
|
|
28
|
-
captionDelay?: number;
|
|
29
|
-
captionDuration?: number;
|
|
30
30
|
}
|
|
31
31
|
export default function Carousel(props: CarouselProps): React.ReactElement | null;
|
|
32
32
|
export {};
|
package/dist/index.esm.js
CHANGED
|
@@ -3207,7 +3207,7 @@ function cn(...inputs) {
|
|
|
3207
3207
|
return twMerge(clsx(inputs));
|
|
3208
3208
|
}
|
|
3209
3209
|
|
|
3210
|
-
const
|
|
3210
|
+
const animationVariants = {
|
|
3211
3211
|
fade: {
|
|
3212
3212
|
initial: { opacity: 0 },
|
|
3213
3213
|
animate: { opacity: 1, transition: { duration: 0.6, ease: "easeInOut" } },
|
|
@@ -3262,7 +3262,7 @@ const slideVariants = {
|
|
|
3262
3262
|
|
|
3263
3263
|
function Carousel(props) {
|
|
3264
3264
|
var _a, _b;
|
|
3265
|
-
const { items, autoPlay = false, autoPlayInterval = 3000, autoPlayDirection = "forward", infiniteLoop = true, pauseOnHover = true, pauseOnFocus = true, pauseOnDrag = true, showPagination = true, showArrows = true, animation,
|
|
3265
|
+
const { items, autoPlay = false, autoPlayInterval = 3000, autoPlayDirection = "forward", infiniteLoop = true, rtl = false, pauseOnHover = true, pauseOnFocus = true, pauseOnDrag = true, showPagination = true, showArrows = true, animation, captionAnimation = "fade", captionDelay = 0.5, captionDuration = 0.8, className, slideClassName, arrowClassName, paginationClassName, dotClassName, captionClassName, } = props;
|
|
3266
3266
|
const [currentIndex, setCurrentIndex] = React.useState(0);
|
|
3267
3267
|
const [isPaused, setIsPaused] = React.useState(false);
|
|
3268
3268
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
@@ -3410,13 +3410,13 @@ function Carousel(props) {
|
|
|
3410
3410
|
rtl ? next() : prev();
|
|
3411
3411
|
}
|
|
3412
3412
|
};
|
|
3413
|
-
return (jsxs("div", Object.assign({ ref: scope, dir: rtl ? "rtl" : "ltr", className: cn("relative overflow-hidden w-full max-w-4xl mx-auto aspect-[4/3] rounded-xl shadow-2xl bg-gray-900 outline-none focus:ring-2 focus:ring-white/50", className), tabIndex: 0, onKeyDown: handleKeyDown }, (effectivePauseOnHover && {
|
|
3413
|
+
return (jsxs("div", Object.assign({ ref: scope, "data-nexlide": "true", "data-nexlide-version": "1.1.1", dir: rtl ? "rtl" : "ltr", className: cn("nexlide-carousel relative overflow-hidden w-full max-w-4xl mx-auto aspect-[4/3] rounded-xl shadow-2xl bg-gray-900 outline-none focus:ring-2 focus:ring-white/50", className), tabIndex: 0, onKeyDown: handleKeyDown }, (effectivePauseOnHover && {
|
|
3414
3414
|
onMouseEnter: handleMouseEnter,
|
|
3415
3415
|
onMouseLeave: handleMouseLeave,
|
|
3416
3416
|
}), (effectivePauseOnFocus && {
|
|
3417
3417
|
onFocus: handleFocus,
|
|
3418
3418
|
onBlur: handleBlur,
|
|
3419
|
-
}), { role: "region", "aria-label": "Carousel showcase", "aria-roledescription": "carousel", "aria-live": autoPlay ? "off" : "polite", children: [jsx(AnimatePresence, { initial: false, mode: "wait", children: jsxs(motion.div, { drag: "x", dragConstraints: { left: 0, right: 0 }, dragElastic: 0.25, onDragStart: effectivePauseOnDrag ? handleDragStart : undefined, onDragEnd: handleDragEnd, style: { x }, className: cn("absolute inset-0", slideClassName), variants: (_a =
|
|
3419
|
+
}), { role: "region", "aria-label": "Carousel showcase", "aria-roledescription": "carousel", "aria-live": autoPlay ? "off" : "polite", children: [jsx(AnimatePresence, { initial: false, mode: "wait", children: jsxs(motion.div, { drag: "x", dragConstraints: { left: 0, right: 0 }, dragElastic: 0.25, onDragStart: effectivePauseOnDrag ? handleDragStart : undefined, onDragEnd: handleDragEnd, style: { x }, className: cn("absolute inset-0", slideClassName), variants: (_a = animationVariants[selectedAnimation]) !== null && _a !== void 0 ? _a : animationVariants.slideLeft, initial: "initial", animate: "animate", exit: "exit", children: [jsx("img", { src: currentItem.imageUrl, alt: currentItem.title || `Slide ${currentIndex + 1}`, className: "w-full h-full object-cover pointer-events-none select-none", loading: currentIndex === 0 ? "eager" : "lazy", decoding: "async", draggable: false }), hasCaption && (jsx(AnimatePresence, { children: jsxs(motion.div, { className: cn("absolute bottom-6 left-6 right-6 bg-gradient-to-t from-black/80 to-transparent p-6 rounded-b-xl", captionClassName), variants: (_b = animationVariants[selectedCaptionAnimation]) !== null && _b !== void 0 ? _b : animationVariants.fade, initial: "initial", animate: "animate", exit: "exit", transition: {
|
|
3420
3420
|
delay: captionDelay,
|
|
3421
3421
|
duration: captionDuration,
|
|
3422
3422
|
ease: "easeOut",
|