yet-another-react-lightbox 3.11.4 → 3.12.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
@@ -6,19 +6,19 @@ Modern React lightbox component. Performant, easy to use, customizable and exten
6
6
 
7
7
  [![NPM Version](https://img.shields.io/npm/v/yet-another-react-lightbox?color=blue)](https://www.npmjs.com/package/yet-another-react-lightbox)
8
8
  [![Bundle Size](https://img.shields.io/bundlephobia/minzip/yet-another-react-lightbox?color=blue)](https://bundlephobia.com/package/yet-another-react-lightbox)
9
- [![License MIT](https://img.shields.io/npm/l/yet-another-react-lightbox?color=blue)](LICENSE)
10
-
11
- - **Built for React:** works with React 18, 17 and 16.8.0+
12
- - **UX:** supports keyboard, mouse, touchpad and touchscreen navigation
13
- - **Preloading:** never displays partially downloaded images
14
- - **Performance:** preloads limited number of images without compromising performance or UX
15
- - **Responsive:** responsive images with automatic resolution switching are supported out of the box
16
- - **Video:** video slides are supported via an optional plugin
17
- - **Zoom:** image zoom is supported via an optional plugin
18
- - **Customization:** customize any UI element or add your own custom slides
19
- - **No bloat:** never bundle rarely used features; add optional features via plugins
20
- - **TypeScript:** type definitions come built-in in the package
21
- - **RTL:** compatible with RTL layout
9
+ [![License MIT](https://img.shields.io/npm/l/yet-another-react-lightbox?color=blue)](https://github.com/igordanchenko/yet-another-react-lightbox/blob/main/LICENSE)
10
+
11
+ - **Built for React:** works with React 18, 17 and 16.8.0+
12
+ - **UX:** supports keyboard, mouse, touchpad and touchscreen navigation
13
+ - **Preloading:** never displays partially downloaded images
14
+ - **Performance:** preloads limited number of images without compromising performance or UX
15
+ - **Responsive:** responsive images with automatic resolution switching are supported out of the box
16
+ - **Video:** video slides are supported via an optional plugin
17
+ - **Zoom:** image zoom is supported via an optional plugin
18
+ - **Customization:** customize any UI element or add your own custom slides
19
+ - **No bloat:** never bundle rarely used features; add optional features via plugins
20
+ - **TypeScript:** type definitions come built-in in the package
21
+ - **RTL:** compatible with RTL layout
22
22
 
23
23
  ![Yet Another React Lightbox | Example](https://yet-another-react-lightbox.com/images/example.jpg)
24
24
 
@@ -50,25 +50,21 @@ import Lightbox from "yet-another-react-lightbox";
50
50
  import "yet-another-react-lightbox/styles.css";
51
51
 
52
52
  export default function App() {
53
- const [open, setOpen] = React.useState(false);
54
-
55
- return (
56
- <>
57
- <button type="button" onClick={() => setOpen(true)}>
58
- Open Lightbox
59
- </button>
60
-
61
- <Lightbox
62
- open={open}
63
- close={() => setOpen(false)}
64
- slides={[
65
- { src: "/image1.jpg" },
66
- { src: "/image2.jpg" },
67
- { src: "/image3.jpg" },
68
- ]}
69
- />
70
- </>
71
- );
53
+ const [open, setOpen] = React.useState(false);
54
+
55
+ return (
56
+ <>
57
+ <button type="button" onClick={() => setOpen(true)}>
58
+ Open Lightbox
59
+ </button>
60
+
61
+ <Lightbox
62
+ open={open}
63
+ close={() => setOpen(false)}
64
+ slides={[{ src: "/image1.jpg" }, { src: "/image2.jpg" }, { src: "/image3.jpg" }]}
65
+ />
66
+ </>
67
+ );
72
68
  }
73
69
  ```
74
70
 
@@ -85,36 +81,36 @@ import Lightbox from "yet-another-react-lightbox";
85
81
  import "yet-another-react-lightbox/styles.css";
86
82
 
87
83
  export default function App() {
88
- const [open, setOpen] = React.useState(false);
89
-
90
- return (
91
- <>
92
- <button type="button" onClick={() => setOpen(true)}>
93
- Open Lightbox
94
- </button>
95
-
96
- <Lightbox
97
- open={open}
98
- close={() => setOpen(false)}
99
- slides={[
100
- {
101
- src: "/image1x3840.jpg",
102
- alt: "image 1",
103
- width: 3840,
104
- height: 2560,
105
- srcSet: [
106
- { src: "/image1x320.jpg", width: 320, height: 213 },
107
- { src: "/image1x640.jpg", width: 640, height: 427 },
108
- { src: "/image1x1200.jpg", width: 1200, height: 800 },
109
- { src: "/image1x2048.jpg", width: 2048, height: 1365 },
110
- { src: "/image1x3840.jpg", width: 3840, height: 2560 },
111
- ]
112
- },
113
- // ...
114
- ]}
115
- />
116
- </>
117
- );
84
+ const [open, setOpen] = React.useState(false);
85
+
86
+ return (
87
+ <>
88
+ <button type="button" onClick={() => setOpen(true)}>
89
+ Open Lightbox
90
+ </button>
91
+
92
+ <Lightbox
93
+ open={open}
94
+ close={() => setOpen(false)}
95
+ slides={[
96
+ {
97
+ src: "/image1x3840.jpg",
98
+ alt: "image 1",
99
+ width: 3840,
100
+ height: 2560,
101
+ srcSet: [
102
+ { src: "/image1x320.jpg", width: 320, height: 213 },
103
+ { src: "/image1x640.jpg", width: 640, height: 427 },
104
+ { src: "/image1x1200.jpg", width: 1200, height: 800 },
105
+ { src: "/image1x2048.jpg", width: 2048, height: 1365 },
106
+ { src: "/image1x3840.jpg", width: 3840, height: 2560 },
107
+ ],
108
+ },
109
+ // ...
110
+ ]}
111
+ />
112
+ </>
113
+ );
118
114
  }
119
115
  ```
120
116
 
@@ -127,17 +123,17 @@ Yet Another React Lightbox allows you to add optional features to your project b
127
123
 
128
124
  The following plugins are bundled in the package:
129
125
 
130
- - [Captions](https://yet-another-react-lightbox.com/plugins/captions) - adds support for slide title and
131
- description
132
- - [Counter](https://yet-another-react-lightbox.com/plugins/counter) - adds slides counter
133
- - [Download](https://yet-another-react-lightbox.com/plugins/download) - adds download button
134
- - [Fullscreen](https://yet-another-react-lightbox.com/plugins/fullscreen) - adds support for fullscreen mode
135
- - [Inline](https://yet-another-react-lightbox.com/plugins/inline) - transforms the lightbox into an image carousel
136
- - [Share](https://yet-another-react-lightbox.com/plugins/share) - adds sharing button
137
- - [Slideshow](https://yet-another-react-lightbox.com/plugins/slideshow) - adds slideshow button
138
- - [Thumbnails](https://yet-another-react-lightbox.com/plugins/thumbnails) - adds thumbnails track
139
- - [Video](https://yet-another-react-lightbox.com/plugins/video) - adds support for video slides
140
- - [Zoom](https://yet-another-react-lightbox.com/plugins/zoom) - adds image zoom feature
126
+ - [Captions](https://yet-another-react-lightbox.com/plugins/captions) - adds support for slide title and
127
+ description
128
+ - [Counter](https://yet-another-react-lightbox.com/plugins/counter) - adds slides counter
129
+ - [Download](https://yet-another-react-lightbox.com/plugins/download) - adds download button
130
+ - [Fullscreen](https://yet-another-react-lightbox.com/plugins/fullscreen) - adds support for fullscreen mode
131
+ - [Inline](https://yet-another-react-lightbox.com/plugins/inline) - transforms the lightbox into an image carousel
132
+ - [Share](https://yet-another-react-lightbox.com/plugins/share) - adds sharing button
133
+ - [Slideshow](https://yet-another-react-lightbox.com/plugins/slideshow) - adds slideshow button
134
+ - [Thumbnails](https://yet-another-react-lightbox.com/plugins/thumbnails) - adds thumbnails track
135
+ - [Video](https://yet-another-react-lightbox.com/plugins/video) - adds support for video slides
136
+ - [Zoom](https://yet-another-react-lightbox.com/plugins/zoom) - adds image zoom feature
141
137
 
142
138
  ## License
143
139
 
package/dist/index.d.ts CHANGED
@@ -194,7 +194,7 @@ type ImageSlideProps = Partial<Pick<CarouselSettings, "imageFit" | "imageProps">
194
194
  };
195
195
  declare function ImageSlide({ slide: image, offset, render, rect, imageFit, imageProps, onClick, onLoad, style, }: ImageSlideProps): React.JSX.Element;
196
196
 
197
- declare function Carousel({ carousel: { finite, preload, padding, spacing } }: ComponentProps): React.JSX.Element;
197
+ declare function Carousel({ carousel }: ComponentProps): React.JSX.Element;
198
198
  declare const CarouselModule: Module;
199
199
 
200
200
  declare enum SwipeState {
@@ -234,9 +234,10 @@ type NavigationButtonProps = {
234
234
  action: "prev" | "next";
235
235
  onClick: () => void;
236
236
  disabled?: boolean;
237
+ style?: React.CSSProperties;
237
238
  };
238
- declare function NavigationButton({ label, icon, renderIcon, action, onClick, disabled }: NavigationButtonProps): React.JSX.Element;
239
- declare function Navigation({ carousel: { finite }, animation, render: { buttonPrev, buttonNext, iconPrev, iconNext }, }: ComponentProps): React.JSX.Element;
239
+ declare function NavigationButton({ label, icon, renderIcon, action, onClick, disabled, style }: NavigationButtonProps): React.JSX.Element;
240
+ declare function Navigation({ carousel: { finite }, animation, render: { buttonPrev, buttonNext, iconPrev, iconNext }, styles, }: ComponentProps): React.JSX.Element;
240
241
  declare const NavigationModule: Module;
241
242
 
242
243
  declare function NoScroll({ children }: ComponentProps): React.JSX.Element;
@@ -248,7 +249,7 @@ declare const PortalModule: Module;
248
249
  declare function Root({ children }: ComponentProps): React.JSX.Element;
249
250
  declare const RootModule: Module;
250
251
 
251
- declare function Toolbar({ toolbar: { buttons }, render: { buttonClose, iconClose } }: ComponentProps): React.JSX.Element;
252
+ declare function Toolbar({ toolbar: { buttons }, render: { buttonClose, iconClose }, styles }: ComponentProps): React.JSX.Element;
252
253
  declare const ToolbarModule: Module;
253
254
 
254
255
  export { Augmentation, Callback, Carousel, CarouselModule, CarouselSettings, CloseIcon, Component, ComponentProps, ComputeAnimation, ContainerRect, Controller, ControllerContext, ControllerContextType, ControllerModule, ControllerRef, ErrorIcon, Event, EventCallback, EventTypes, EventsContext, EventsContextType, EventsProvider, IconButton, IconButtonProps, ImageSlide, ImageSlideProps, KeyboardEventType, Labels, LengthOrPercentage, Lightbox, LightboxDefaultProps, LightboxDispatchContext, LightboxDispatchContextType, LightboxExternalProps, LightboxProps, LightboxPropsContext, LightboxPropsContextType, LightboxPropsProvider, LightboxState, LightboxStateAction, LightboxStateContext, LightboxStateContextType, LightboxStateProvider, LightboxStateProviderProps, LightboxStateSwipeAction, LightboxStateUpdateAction, LoadingIcon, Module, Navigation, NavigationButton, NavigationButtonProps, NavigationModule, NextIcon, NoScroll, NoScrollModule, Node, Plugin, PointerEventType, Portal, PortalModule, PreviousIcon, Publish, ReactEventType, RegisterSensors, Render, RenderFunction, Root, RootModule, SensorCallback, Slide, SlideImage, Subscribe, SubscribeSensors, SupportedEventType, SwipeState, TimeoutsContext, TimeoutsContextType, TimeoutsProvider, Toolbar, ToolbarModule, ToolbarSettings, Topic, Unsubscribe, UseSensors, WheelEventType, addToolbarButton, cleanup, clsx, composePrefix, computeSlideRect, createIcon, createIconDisabled, createModule, createNode, cssClass, cssVar, Lightbox as default, devicePixelRatio, getSlide, getSlideIfPresent, getSlideIndex, hasSlides, hasWindow, isImageFitCover, isImageSlide, label, makeComposePrefix, makeUseContext, parseLengthPercentage, round, setRef, stopNavigationEventsPropagation, useAnimation, useContainerRect, useController, useDelay, useEventCallback, useEvents, useForkRef, useLayoutEffect, useLightboxDispatch, useLightboxProps, useLightboxState, useLoseFocus, useMotionPreference, usePointerSwipe, usePreventSwipeNavigation, useRTL, useSensors, useThrottle, useTimeouts, useWheelSwipe, withPlugins };
package/dist/index.js CHANGED
@@ -1174,21 +1174,22 @@ function Placeholder() {
1174
1174
  const style = useLightboxProps().styles.slide;
1175
1175
  return React.createElement("div", { className: cssClass("slide"), style: style });
1176
1176
  }
1177
- function Carousel({ carousel: { finite, preload, padding, spacing } }) {
1177
+ function Carousel({ carousel }) {
1178
1178
  const { slides, currentIndex, globalIndex } = useLightboxState();
1179
1179
  const { setCarouselRef } = useController();
1180
- const spacingValue = parseLengthPercentage(spacing);
1181
- const paddingValue = parseLengthPercentage(padding);
1180
+ const spacingValue = parseLengthPercentage(carousel.spacing);
1181
+ const paddingValue = parseLengthPercentage(carousel.padding);
1182
1182
  const items = [];
1183
- if ((slides === null || slides === void 0 ? void 0 : slides.length) > 0) {
1183
+ const preload = Math.min(carousel.preload, Math.max(Math.floor(slides.length / 2), 1));
1184
+ if (hasSlides(slides)) {
1184
1185
  for (let i = currentIndex - preload; i < currentIndex; i += 1) {
1185
1186
  const key = globalIndex + i - currentIndex;
1186
- items.push(!finite || i >= 0 ? (React.createElement(CarouselSlide, { key: key, slide: slides[(i + preload * slides.length) % slides.length], offset: i - currentIndex })) : (React.createElement(Placeholder, { key: key })));
1187
+ items.push(!carousel.finite || i >= 0 ? (React.createElement(CarouselSlide, { key: key, slide: slides[(i + preload * slides.length) % slides.length], offset: i - currentIndex })) : (React.createElement(Placeholder, { key: key })));
1187
1188
  }
1188
1189
  items.push(React.createElement(CarouselSlide, { key: globalIndex, slide: slides[currentIndex], offset: 0 }));
1189
1190
  for (let i = currentIndex + 1; i <= currentIndex + preload; i += 1) {
1190
1191
  const key = globalIndex + i - currentIndex;
1191
- items.push(!finite || i <= slides.length - 1 ? (React.createElement(CarouselSlide, { key: key, slide: slides[i % slides.length], offset: i - currentIndex })) : (React.createElement(Placeholder, { key: key })));
1192
+ items.push(!carousel.finite || i <= slides.length - 1 ? (React.createElement(CarouselSlide, { key: key, slide: slides[i % slides.length], offset: i - currentIndex })) : (React.createElement(Placeholder, { key: key })));
1192
1193
  }
1193
1194
  }
1194
1195
  return (React.createElement("div", { ref: setCarouselRef, className: clsx(cssClass(cssPrefix$2()), items.length > 0 && cssClass(cssPrefix$2("with_slides"))), style: {
@@ -1201,10 +1202,10 @@ function Carousel({ carousel: { finite, preload, padding, spacing } }) {
1201
1202
  }
1202
1203
  const CarouselModule = createModule(MODULE_CAROUSEL, Carousel);
1203
1204
 
1204
- function NavigationButton({ label, icon, renderIcon, action, onClick, disabled }) {
1205
- return (React.createElement(IconButton, { label: label, icon: icon, renderIcon: renderIcon, className: cssClass(`navigation_${action}`), disabled: disabled, onClick: onClick, ...useLoseFocus(useController().focus, disabled) }));
1205
+ function NavigationButton({ label, icon, renderIcon, action, onClick, disabled, style }) {
1206
+ return (React.createElement(IconButton, { label: label, icon: icon, renderIcon: renderIcon, className: cssClass(`navigation_${action}`), disabled: disabled, onClick: onClick, style: style, ...useLoseFocus(useController().focus, disabled) }));
1206
1207
  }
1207
- function Navigation({ carousel: { finite }, animation, render: { buttonPrev, buttonNext, iconPrev, iconNext }, }) {
1208
+ function Navigation({ carousel: { finite }, animation, render: { buttonPrev, buttonNext, iconPrev, iconNext }, styles, }) {
1208
1209
  var _a;
1209
1210
  const { slides, currentIndex } = useLightboxState();
1210
1211
  const { prev, next, subscribeSensors } = useController();
@@ -1224,8 +1225,8 @@ function Navigation({ carousel: { finite }, animation, render: { buttonPrev, but
1224
1225
  });
1225
1226
  React.useEffect(() => subscribeSensors(EVENT_ON_KEY_DOWN, handleKeyDown), [subscribeSensors, handleKeyDown]);
1226
1227
  return (React.createElement(React.Fragment, null,
1227
- buttonPrev ? (buttonPrev()) : (React.createElement(NavigationButton, { label: "Previous", action: ACTION_PREV, icon: PreviousIcon, renderIcon: iconPrev, disabled: prevDisabled, onClick: prev })),
1228
- buttonNext ? (buttonNext()) : (React.createElement(NavigationButton, { label: "Next", action: ACTION_NEXT, icon: NextIcon, renderIcon: iconNext, disabled: nextDisabled, onClick: next }))));
1228
+ buttonPrev ? (buttonPrev()) : (React.createElement(NavigationButton, { label: "Previous", action: ACTION_PREV, icon: PreviousIcon, renderIcon: iconPrev, style: styles.navigationPrev, disabled: prevDisabled, onClick: prev })),
1229
+ buttonNext ? (buttonNext()) : (React.createElement(NavigationButton, { label: "Next", action: ACTION_NEXT, icon: NextIcon, renderIcon: iconNext, style: styles.navigationNext, disabled: nextDisabled, onClick: next }))));
1229
1230
  }
1230
1231
  const NavigationModule = createModule(MODULE_NAVIGATION, Navigation);
1231
1232
 
@@ -1370,7 +1371,7 @@ const RootModule = createModule(MODULE_ROOT, Root);
1370
1371
  function cssPrefix(value) {
1371
1372
  return composePrefix(MODULE_TOOLBAR, value);
1372
1373
  }
1373
- function Toolbar({ toolbar: { buttons }, render: { buttonClose, iconClose } }) {
1374
+ function Toolbar({ toolbar: { buttons }, render: { buttonClose, iconClose }, styles }) {
1374
1375
  const { close, setToolbarWidth } = useController();
1375
1376
  const { setContainerRef, containerRect } = useContainerRect();
1376
1377
  useLayoutEffect(() => {
@@ -1381,7 +1382,7 @@ function Toolbar({ toolbar: { buttons }, render: { buttonClose, iconClose } }) {
1381
1382
  return buttonClose();
1382
1383
  return React.createElement(IconButton, { key: ACTION_CLOSE, label: "Close", icon: CloseIcon, renderIcon: iconClose, onClick: close });
1383
1384
  };
1384
- return (React.createElement("div", { ref: setContainerRef, className: cssClass(cssPrefix()), ...stopNavigationEventsPropagation() }, buttons === null || buttons === void 0 ? void 0 : buttons.map((button) => (button === ACTION_CLOSE ? renderCloseButton() : button))));
1385
+ return (React.createElement("div", { ref: setContainerRef, style: styles.toolbar, className: cssClass(cssPrefix()), ...stopNavigationEventsPropagation() }, buttons === null || buttons === void 0 ? void 0 : buttons.map((button) => (button === ACTION_CLOSE ? renderCloseButton() : button))));
1385
1386
  }
1386
1387
  const ToolbarModule = createModule(MODULE_TOOLBAR, Toolbar);
1387
1388
 
@@ -121,7 +121,7 @@ function ThumbnailsTrack({ visible, containerRef }) {
121
121
  });
122
122
  React.useEffect(() => cleanup(subscribe(ACTION_SWIPE, handleControllerSwipe)), [subscribe, handleControllerSwipe]);
123
123
  const { finite } = carousel;
124
- const preload = Math.max(Math.min(carousel.preload, slides.length - 1), 0);
124
+ const preload = Math.min(carousel.preload, Math.floor(slides.length / 2));
125
125
  const items = [];
126
126
  if (hasSlides(slides)) {
127
127
  if (offset < 0) {
@@ -129,7 +129,7 @@ function ThumbnailsTrack({ visible, containerRef }) {
129
129
  items.push({ slide: null, index: i, placeholder: true });
130
130
  }
131
131
  }
132
- for (let i = index - preload - (offset > 0 ? offset : 0); i < index; i += 1) {
132
+ for (let i = index - preload - Math.max(offset, 0); i < index; i += 1) {
133
133
  if (!(finite && i < 0)) {
134
134
  items.push({ slide: getSlide(slides, i), index: i });
135
135
  }
@@ -138,7 +138,7 @@ function ThumbnailsTrack({ visible, containerRef }) {
138
138
  }
139
139
  }
140
140
  items.push({ slide: getSlide(slides, index), index });
141
- for (let i = index + 1; i <= index + preload - (offset < 0 ? offset : 0); i += 1) {
141
+ for (let i = index + 1; i <= index + preload - Math.min(offset, 0); i += 1) {
142
142
  if (!finite || i <= slides.length - 1) {
143
143
  items.push({ slide: getSlide(slides, i), index: i });
144
144
  }
@@ -96,7 +96,7 @@ function Video({ augment }) {
96
96
  slide: ({ slide, offset, rect }) => {
97
97
  var _a;
98
98
  if (isVideoSlide(slide)) {
99
- return (React.createElement(VideoSlide, { key: `${(_a = slide.sources) === null || _a === void 0 ? void 0 : _a.map((source) => source.src).join(" ")}`, slide: slide, offset: offset }));
99
+ return (React.createElement(VideoSlide, { key: (_a = slide.sources) === null || _a === void 0 ? void 0 : _a.map((source) => source.src).join(" "), slide: slide, offset: offset }));
100
100
  }
101
101
  return renderSlide === null || renderSlide === void 0 ? void 0 : renderSlide({ slide, offset, rect });
102
102
  },
package/dist/types.d.ts CHANGED
@@ -167,6 +167,12 @@ interface SlotType {
167
167
  button: "button";
168
168
  /** lightbox icon customization slot */
169
169
  icon: "icon";
170
+ /** lightbox toolbar customization slot */
171
+ toolbar: "toolbar";
172
+ /** lightbox Prev navigation button customization slot */
173
+ navigationPrev: "navigationPrev";
174
+ /** lightbox Next navigation button customization slot */
175
+ navigationNext: "navigationNext";
170
176
  }
171
177
  /** Customization slot CSS properties */
172
178
  interface SlotCSSProperties extends React.CSSProperties {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yet-another-react-lightbox",
3
- "version": "3.11.4",
3
+ "version": "3.12.1",
4
4
  "description": "Modern React lightbox component",
5
5
  "author": "Igor Danchenko",
6
6
  "license": "MIT",