yet-another-react-lightbox 2.4.2 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Lightbox.js CHANGED
@@ -5,6 +5,11 @@ const renderNode = (node, props) => {
5
5
  var _a;
6
6
  return React.createElement(node.module.component, { key: node.module.name, ...props }, (_a = node.children) === null || _a === void 0 ? void 0 : _a.map((child) => renderNode(child, props)));
7
7
  };
8
+ const fixupIndex = ({ index, slides, ...rest }) => ({
9
+ index: index >= 0 && index < slides.length ? index : 0,
10
+ slides,
11
+ ...rest,
12
+ });
8
13
  export const Lightbox = (props) => {
9
14
  const { carousel, animation, render, toolbar, controller, on, plugins, ...restProps } = props;
10
15
  const { carousel: defaultCarousel, animation: defaultAnimation, render: defaultRender, toolbar: defaultToolbar, controller: defaultController, on: defaultOn, ...restDefaultProps } = LightboxDefaultProps;
@@ -18,7 +23,7 @@ export const Lightbox = (props) => {
18
23
  ]),
19
24
  ]),
20
25
  ]),
21
- ], plugins);
26
+ ], plugins, [fixupIndex]);
22
27
  const augmentedProps = augmentation({
23
28
  carousel: { ...defaultCarousel, ...carousel },
24
29
  animation: { ...defaultAnimation, ...animation },
@@ -1,7 +1,7 @@
1
1
  import { Augmentation, Component, Module, Node, Plugin } from "../types.js";
2
2
  export declare const createModule: (name: string, component: Component) => Module;
3
3
  export declare const createNode: (module: Module, children?: Node[]) => Node;
4
- export declare const withPlugins: (root: Node[], plugins?: Plugin[]) => {
4
+ export declare const withPlugins: (root: Node[], plugins?: Plugin[], augmentations?: Augmentation[]) => {
5
5
  config: Node[];
6
6
  augmentation: Augmentation;
7
7
  };
@@ -18,9 +18,8 @@ const traverseNode = (node, target, apply) => {
18
18
  return [node];
19
19
  };
20
20
  const traverse = (nodes, target, apply) => nodes.flatMap((node) => { var _a; return (_a = traverseNode(node, target, apply)) !== null && _a !== void 0 ? _a : []; });
21
- export const withPlugins = (root, plugins) => {
21
+ export const withPlugins = (root, plugins = [], augmentations = []) => {
22
22
  let config = root;
23
- const augmentations = [];
24
23
  const contains = (target) => {
25
24
  const nodes = [...config];
26
25
  while (nodes.length > 0) {
@@ -70,7 +69,7 @@ export const withPlugins = (root, plugins) => {
70
69
  const augment = (augmentation) => {
71
70
  augmentations.push(augmentation);
72
71
  };
73
- plugins === null || plugins === void 0 ? void 0 : plugins.forEach((plugin) => {
72
+ plugins.forEach((plugin) => {
74
73
  plugin({
75
74
  contains,
76
75
  addParent,
@@ -1 +1 @@
1
- export declare const useDelay: () => (callback: (...args: any[]) => void, delay: number) => void;
1
+ export declare const useDelay: () => (callback: () => void, delay: number) => void;
@@ -3,10 +3,14 @@ import { Component, ComponentProps, ContainerRect } from "../../types.js";
3
3
  import { SubscribeSensors } from "../hooks/index.js";
4
4
  import { LightboxStateAction } from "../contexts/index.js";
5
5
  import { ACTION_CLOSE, ACTION_NEXT, ACTION_PREV, ACTION_SWIPE, YARL_EVENT_BACKDROP_CLICK } from "../consts.js";
6
+ export type NavigationAction = {
7
+ count?: number;
8
+ animationDuration?: number;
9
+ };
6
10
  declare module "../" {
7
11
  interface EventTypes {
8
- [ACTION_PREV]: number;
9
- [ACTION_NEXT]: number;
12
+ [ACTION_PREV]: NavigationAction;
13
+ [ACTION_NEXT]: NavigationAction;
10
14
  [ACTION_SWIPE]: LightboxStateAction;
11
15
  [ACTION_CLOSE]: void;
12
16
  [YARL_EVENT_BACKDROP_CLICK]: void;
@@ -53,11 +53,11 @@ export const Controller = ({ children, ...props }) => {
53
53
  return undefined;
54
54
  });
55
55
  const swipe = useEventCallback((action) => {
56
- var _a;
57
- const swipeDuration = animation.swipe;
56
+ var _a, _b;
57
+ const swipeDuration = (_a = action.animationDuration) !== null && _a !== void 0 ? _a : animation.swipe;
58
58
  const currentSwipeOffset = action.offset || 0;
59
59
  let { direction } = action;
60
- const count = (_a = action.count) !== null && _a !== void 0 ? _a : 1;
60
+ const count = (_b = action.count) !== null && _b !== void 0 ? _b : 1;
61
61
  let newSwipeState = SwipeState.ANIMATION;
62
62
  let newSwipeAnimationDuration = swipeDuration * count;
63
63
  if (!direction) {
@@ -146,7 +146,7 @@ export const Controller = ({ children, ...props }) => {
146
146
  (_a = on.view) === null || _a === void 0 ? void 0 : _a.call(on, state.currentIndex);
147
147
  });
148
148
  React.useEffect(handleIndexChange, [state.currentIndex, handleIndexChange]);
149
- React.useEffect(() => cleanup(subscribe(ACTION_PREV, (count) => swipe({ direction: ACTION_PREV, count })), subscribe(ACTION_NEXT, (count) => swipe({ direction: ACTION_NEXT, count })), subscribe(ACTION_SWIPE, (action) => dispatch(action))), [subscribe, swipe, dispatch]);
149
+ React.useEffect(() => cleanup(subscribe(ACTION_PREV, (action) => swipe({ direction: ACTION_PREV, ...action })), subscribe(ACTION_NEXT, (action) => swipe({ direction: ACTION_NEXT, ...action })), subscribe(ACTION_SWIPE, (action) => dispatch(action))), [subscribe, swipe, dispatch]);
150
150
  React.useEffect(() => subscribeSensors(EVENT_ON_KEY_UP, (event) => {
151
151
  if (event.code === VK_ESCAPE) {
152
152
  publish(ACTION_CLOSE);
@@ -1,15 +1,14 @@
1
1
  import * as React from "react";
2
2
  import { Component, Labels } from "../../types.js";
3
- import { Publish } from "../contexts/index.js";
4
3
  export type NavigationButtonProps = {
5
- publish: Publish;
6
4
  labels?: Labels;
7
5
  label: string;
8
6
  icon: React.ElementType;
9
7
  renderIcon?: () => React.ReactNode;
10
8
  action: "prev" | "next";
9
+ onClick: () => void;
11
10
  disabled?: boolean;
12
11
  };
13
- export declare const NavigationButton: ({ publish, labels, label, icon, renderIcon, action, disabled, }: NavigationButtonProps) => JSX.Element;
12
+ export declare const NavigationButton: ({ labels, label, icon, renderIcon, action, onClick, disabled, }: NavigationButtonProps) => JSX.Element;
14
13
  export declare const Navigation: Component;
15
14
  export declare const NavigationModule: import("../../types.js").Module;
@@ -6,15 +6,18 @@ import { IconButton, NextIcon, PreviousIcon } from "../components/index.js";
6
6
  import { useEvents, useLightboxState } from "../contexts/index.js";
7
7
  import { useController } from "./Controller.js";
8
8
  import { ACTION_NEXT, ACTION_PREV, EVENT_ON_KEY_DOWN, MODULE_NAVIGATION, VK_ARROW_LEFT, VK_ARROW_RIGHT, } from "../consts.js";
9
- export const NavigationButton = ({ publish, labels, label, icon, renderIcon, action, disabled, }) => (React.createElement(IconButton, { label: translateLabel(labels, label), icon: icon, renderIcon: renderIcon, className: cssClass(`navigation_${action}`), disabled: disabled, onClick: () => publish(action), ...useLoseFocus(disabled) }));
10
- export const Navigation = ({ slides, carousel: { finite }, animation: { swipe }, labels, render: { buttonPrev, buttonNext, iconPrev, iconNext }, }) => {
9
+ export const NavigationButton = ({ labels, label, icon, renderIcon, action, onClick, disabled, }) => (React.createElement(IconButton, { label: translateLabel(labels, label), icon: icon, renderIcon: renderIcon, className: cssClass(`navigation_${action}`), disabled: disabled, onClick: onClick, ...useLoseFocus(disabled) }));
10
+ export const Navigation = ({ slides, carousel: { finite }, animation: { swipe, navigation }, labels, render: { buttonPrev, buttonNext, iconPrev, iconNext }, }) => {
11
11
  const { currentIndex } = useLightboxState().state;
12
12
  const { subscribeSensors } = useController();
13
13
  const { publish } = useEvents();
14
14
  const isRTL = useRTL();
15
15
  const prevDisabled = slides.length === 0 || (finite && currentIndex === 0);
16
16
  const nextDisabled = slides.length === 0 || (finite && currentIndex === slides.length - 1);
17
- const publishThrottled = useThrottle((action) => publish(action), swipe / 2);
17
+ const navigate = (action) => {
18
+ publish(action, { animationDuration: navigation });
19
+ };
20
+ const publishThrottled = useThrottle((action) => navigate(action), (navigation !== null && navigation !== void 0 ? navigation : swipe) / 2);
18
21
  const handleKeyDown = useEventCallback((event) => {
19
22
  if (event.key === VK_ARROW_LEFT && !(isRTL ? nextDisabled : prevDisabled)) {
20
23
  publishThrottled(isRTL ? ACTION_NEXT : ACTION_PREV);
@@ -25,7 +28,7 @@ export const Navigation = ({ slides, carousel: { finite }, animation: { swipe },
25
28
  });
26
29
  React.useEffect(() => subscribeSensors(EVENT_ON_KEY_DOWN, handleKeyDown), [subscribeSensors, handleKeyDown]);
27
30
  return (React.createElement(React.Fragment, null,
28
- buttonPrev ? (buttonPrev()) : (React.createElement(NavigationButton, { label: "Previous", action: ACTION_PREV, icon: PreviousIcon, renderIcon: iconPrev, disabled: prevDisabled, labels: labels, publish: publish })),
29
- buttonNext ? (buttonNext()) : (React.createElement(NavigationButton, { label: "Next", action: ACTION_NEXT, icon: NextIcon, renderIcon: iconNext, disabled: nextDisabled, labels: labels, publish: publish }))));
31
+ buttonPrev ? (buttonPrev()) : (React.createElement(NavigationButton, { label: "Previous", action: ACTION_PREV, icon: PreviousIcon, renderIcon: iconPrev, disabled: prevDisabled, labels: labels, onClick: () => navigate(ACTION_PREV) })),
32
+ buttonNext ? (buttonNext()) : (React.createElement(NavigationButton, { label: "Next", action: ACTION_NEXT, icon: NextIcon, renderIcon: iconNext, disabled: nextDisabled, labels: labels, onClick: () => navigate(ACTION_NEXT) }))));
30
33
  };
31
34
  export const NavigationModule = createModule(MODULE_NAVIGATION, Navigation);
@@ -5,14 +5,14 @@ import { Thumbnail } from "./Thumbnail.js";
5
5
  import { defaultThumbnailsProps } from "./Thumbnails.js";
6
6
  const isHorizontal = (position) => ["top", "bottom"].includes(position);
7
7
  const boxSize = (thumbnails, dimension, includeGap) => dimension + 2 * (thumbnails.border + thumbnails.padding) + (includeGap ? thumbnails.gap : 0);
8
- export const ThumbnailsTrack = ({ container, slides, carousel, render, thumbnails, thumbnailRect, styles, }) => {
8
+ export const ThumbnailsTrack = ({ container, slides, carousel, render, thumbnails, thumbnailRect, styles, animation: { navigation }, }) => {
9
9
  const track = React.useRef(null);
10
10
  const { globalIndex, animation } = useLightboxState().state;
11
11
  const { publish, subscribe } = useEvents();
12
12
  const isRTL = useRTL();
13
13
  const index = globalIndex;
14
- const offset = (animation === null || animation === void 0 ? void 0 : animation.increment) || 0;
15
14
  const animationDuration = (animation === null || animation === void 0 ? void 0 : animation.duration) || 0;
15
+ const offset = (animationDuration > 0 && (animation === null || animation === void 0 ? void 0 : animation.increment)) || 0;
16
16
  const animate = useAnimation(track, (snapshot) => ({
17
17
  keyframes: isHorizontal(thumbnails.position)
18
18
  ? [
@@ -78,10 +78,10 @@ export const ThumbnailsTrack = ({ container, slides, carousel, render, thumbnail
78
78
  }
79
79
  const handleClick = (slideIndex) => () => {
80
80
  if (slideIndex > index) {
81
- publish(ACTION_NEXT, slideIndex - index);
81
+ publish(ACTION_NEXT, { count: slideIndex - index, animationDuration: navigation });
82
82
  }
83
83
  else if (slideIndex < index) {
84
- publish(ACTION_PREV, index - slideIndex);
84
+ publish(ACTION_PREV, { count: index - slideIndex, animationDuration: navigation });
85
85
  }
86
86
  };
87
87
  const { width, height, border, borderRadius, padding, gap, imageFit, vignette } = thumbnails;
@@ -31,13 +31,12 @@ export const ResponsiveImage = (props) => {
31
31
  });
32
32
  const style = {
33
33
  WebkitTransform: "translateZ(0)",
34
- ...(rect.width / rect.height < width / height
35
- ? {
36
- width: "100%",
37
- height: "auto",
38
- }
39
- : { width: "auto", height: "100%" }),
40
34
  };
35
+ if (!cover) {
36
+ Object.assign(style, rect.width / rect.height < width / height
37
+ ? { width: "100%", height: "auto" }
38
+ : { width: "auto", height: "100%" });
39
+ }
41
40
  return (React.createElement(React.Fragment, null,
42
41
  preload && preload !== current && (React.createElement(ImageSlide, { key: "preload", ...props, slide: { ...image, src: preload, srcSet: undefined }, style: { position: "absolute", visibility: "hidden", ...style }, onLoad: () => handlePreload(preload), render: {
43
42
  ...render,
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { CLASS_FLEX_CENTER, CLASS_FULLSIZE, cleanup, clsx, cssClass, EVENT_ON_KEY_DOWN, EVENT_ON_POINTER_CANCEL, EVENT_ON_POINTER_DOWN, EVENT_ON_POINTER_LEAVE, EVENT_ON_POINTER_MOVE, EVENT_ON_POINTER_UP, EVENT_ON_WHEEL, ImageSlide, isImageSlide, round, useContainerRect, useController, useEventCallback, useEvents, useLayoutEffect, useLightboxState, useMotionPreference, } from "../../core/index.js";
2
+ import { CLASS_FLEX_CENTER, CLASS_FULLSIZE, cleanup, clsx, cssClass, EVENT_ON_KEY_DOWN, EVENT_ON_POINTER_CANCEL, EVENT_ON_POINTER_DOWN, EVENT_ON_POINTER_LEAVE, EVENT_ON_POINTER_MOVE, EVENT_ON_POINTER_UP, EVENT_ON_WHEEL, IMAGE_FIT_COVER, ImageSlide, isImageSlide, round, useContainerRect, useController, useEventCallback, useEvents, useLayoutEffect, useLightboxState, useMotionPreference, } from "../../core/index.js";
3
3
  import { useZoom } from "./ZoomContext.js";
4
4
  import { defaultZoomProps } from "./Zoom.js";
5
5
  import { ACTION_ZOOM_IN, ACTION_ZOOM_OUT } from "./index.js";
@@ -24,12 +24,12 @@ const getSlideRects = (slide, cover, maxZoomPixelRatio, rect) => {
24
24
  };
25
25
  slideRect = cover
26
26
  ? {
27
- width: Math.min(rect.width, maxSlideRect.width),
28
- height: Math.min(rect.height, maxSlideRect.height),
27
+ width: Math.min(rect.width, maxSlideRect.width, width),
28
+ height: Math.min(rect.height, maxSlideRect.height, height),
29
29
  }
30
30
  : {
31
- width: Math.round(Math.min(rect.width, (rect.height / height) * width)),
32
- height: Math.round(Math.min(rect.height, (rect.width / width) * height)),
31
+ width: Math.round(Math.min(rect.width, (rect.height / height) * width, width)),
32
+ height: Math.round(Math.min(rect.height, (rect.width / width) * height, height)),
33
33
  };
34
34
  }
35
35
  }
@@ -54,8 +54,8 @@ export const ZoomContainer = ({ slide, offset, rect, render, carousel, animation
54
54
  const { subscribeSensors, containerRef: controllerRef, containerRect: controllerRect } = useController();
55
55
  const { subscribe } = useEvents();
56
56
  const reduceMotion = useMotionPreference();
57
- const { slideRect, maxSlideRect: currentMaxSlideRect } = getSlideRects({ ...slide, ...imageDimensions }, carousel.imageFit === "cover" || ("imageFit" in slide && slide.imageFit === "cover"), zoomProps.maxZoomPixelRatio, containerRect);
58
- const maxZoom = slideRect.width ? Math.max(round(currentMaxSlideRect.width / slideRect.width, 5), 1) : 1;
57
+ const { slideRect, maxSlideRect } = getSlideRects({ ...slide, ...imageDimensions }, carousel.imageFit === IMAGE_FIT_COVER || ("imageFit" in slide && slide.imageFit === IMAGE_FIT_COVER), zoomProps.maxZoomPixelRatio, containerRect);
58
+ const maxZoom = slideRect.width ? Math.max(round(maxSlideRect.width / slideRect.width, 5), 1) : 1;
59
59
  const changeOffsets = useEventCallback((dx, dy, targetZoom) => {
60
60
  const newZoom = targetZoom || zoom;
61
61
  const newOffsetX = offsetX - (dx || 0);
package/dist/types.d.ts CHANGED
@@ -82,6 +82,8 @@ export interface AnimationSettings {
82
82
  fade: number;
83
83
  /** swipe animation duration */
84
84
  swipe: number;
85
+ /** override for `swipe` animation duration when using keyboard navigation or navigation buttons */
86
+ navigation?: number;
85
87
  }
86
88
  /** Controller settings */
87
89
  export interface ControllerSettings {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yet-another-react-lightbox",
3
- "version": "2.4.2",
3
+ "version": "2.5.0",
4
4
  "description": "Modern React lightbox component",
5
5
  "author": "Igor Danchenko",
6
6
  "license": "MIT",