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 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** ๐ŸŒ โ€” mirrored navigation, reversed swipe, and proper layout for Arabic, Hebrew, Persian, and other RTL languages
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
- - **`rtl` prop** โ€” Enables full right-to-left mode with:
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
- - โšก **Lazy loading** โ€” Non-active slides use `loading="lazy"`
129
- - ๐Ÿ–ผ๏ธ **Image optimization** โ€” `decoding="async"`, `draggable=false`
130
- - ๐Ÿงน **Clean architecture** โ€” No legacy touch handlers
131
- - ๐Ÿ”„ **Smart re-renders** โ€” Optimized with `useCallback` and `useMemo`
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
- - ๐Ÿ” **Visible focus ring** โ€” Clear keyboard navigation indicators
135
- - ๐Ÿท๏ธ **ARIA labels** โ€” Proper roles and descriptions
136
- - โŒจ๏ธ **Full keyboard support** โ€” Arrow keys, tab navigation
137
- - ๐Ÿ“ข **Live regions** โ€” `aria-live="polite"` (off when autoplay active)
138
- - ๐ŸŽฏ **Focus management** โ€” Container receives focus, maintains context
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
- - โš›๏ธ **React 18+** โ€” Modern hooks architecture
142
- - ๐ŸŽญ **Framer Motion** โ€” Production-ready animations
143
- - ๐ŸŒฌ๏ธ **Tailwind CSS v4** โ€” Utility-first styling
144
- - ๐Ÿ“ฆ **TypeScript** โ€” Full type definitions included
145
- - ๐Ÿ”ผ **Next.js** โ€” App Router compatible with `'use client'`
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
- ## ๐Ÿš€ Usage (Next.js App Router)
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
- **Note:** If you're using Pages Router or a different React setup without App Router restrictions, you can omit `'use client';`.
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`| `number` | `3000` | Interval in milliseconds between automatic slides (only used when `autoPlay` is `true`). |
259
- | `autoPlayDirection` | `"forward" \| "reverse"` | `"forward"` | Direction of autoplay: `"forward"` (normal) or `"reverse"` (backward). |
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` | `string` | โ€” | Additional Tailwind classes for the main carousel container. |
309
+ | `className` | `string` | โ€” | Additional Tailwind classes for the main carousel container. |
269
310
  | `slideClassName` | `string` | โ€” | Additional classes for each slide wrapper. |
270
- | `captionClassName`| `string` | โ€” | Additional classes for the caption overlay container. |
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
- **Example usage in RTL context**:
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
 
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { slideVariants } from "./lib/animations";
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 slideVariants;
20
- rtl?: boolean;
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 slideVariants = {
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, rtl = false, className, slideClassName, arrowClassName, paginationClassName, dotClassName, captionClassName, captionAnimation = "fade", captionDelay = 0.5, captionDuration = 0.8, } = props;
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 = slideVariants[selectedAnimation]) !== null && _a !== void 0 ? _a : slideVariants.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 = slideVariants[selectedCaptionAnimation]) !== null && _b !== void 0 ? _b : slideVariants.fade, initial: "initial", animate: "animate", exit: "exit", transition: {
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",