yet-another-react-lightbox 3.17.5 → 3.19.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/README.md CHANGED
@@ -76,11 +76,12 @@ export default function App() {
76
76
 
77
77
  ## Recommended Setup
78
78
 
79
- Unlike many other lightbox libraries, Yet Another React Lightbox doesn't have a
80
- concept of "thumbnail" or "original" (or "full size") images. We use responsive
81
- images instead and recommend you provide multiple files of different resolutions
82
- for each image. Yet Another React Lightbox automatically populates `srcset` /
83
- `sizes` attributes and lets the browser decide which image is more appropriate
79
+ Unlike many other lightbox libraries, Yet Another React Lightbox is not limited
80
+ to just two images per slide ("thumbnail" and "original" / "full size").
81
+ Instead, we favor responsive images with automatic resolution switching and
82
+ recommend you provide multiple files of different resolutions for each image
83
+ slide. Yet Another React Lightbox automatically populates `srcset` / `sizes`
84
+ attributes and lets the user's browser decide which image is more appropriate
84
85
  for its viewport size.
85
86
 
86
87
  ```jsx
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { LightboxExternalProps, LightboxProps, Labels, Slide, SlideImage, LengthOrPercentage, ContainerRect, ToolbarSettings, CarouselSettings, Component, Module, Node, Plugin, Augmentation, EventTypes, ComponentProps, LightboxStateSwipeAction, LightboxStateUpdateAction, LightboxState, Render, ControllerSettings, ControllerRef, Callback, RenderFunction } from './types.js';
2
+ import { LightboxExternalProps, LightboxProps, Labels, Slide, SlideImage, LengthOrPercentage, ContainerRect, ToolbarSettings, CarouselSettings, Component, Module, Node as Node$1, Plugin, Augmentation, EventTypes, ComponentProps, LightboxStateSwipeAction, LightboxStateUpdateAction, LightboxState, Render, ControllerSettings, ControllerRef, Callback, RenderFunction } from './types.js';
3
3
  export { ACTION_CLOSE, ACTION_NEXT, ACTION_PREV, ACTION_SWIPE, ACTIVE_SLIDE_COMPLETE, ACTIVE_SLIDE_ERROR, ACTIVE_SLIDE_LOADING, ACTIVE_SLIDE_PLAYING, AnimationSettings, CLASS_FLEX_CENTER, CLASS_FULLSIZE, CLASS_NO_SCROLL, CLASS_NO_SCROLL_PADDING, CLASS_SLIDE_WRAPPER, Callbacks, ClickCallbackProps, DeepPartial, DeepPartialValue, ELEMENT_BUTTON, ELEMENT_ICON, EVENT_ON_KEY_DOWN, EVENT_ON_KEY_UP, EVENT_ON_POINTER_CANCEL, EVENT_ON_POINTER_DOWN, EVENT_ON_POINTER_LEAVE, EVENT_ON_POINTER_MOVE, EVENT_ON_POINTER_UP, EVENT_ON_WHEEL, GenericSlide, IMAGE_FIT_CONTAIN, IMAGE_FIT_COVER, ImageFit, ImageSource, MODULE_CAROUSEL, MODULE_CONTROLLER, MODULE_NAVIGATION, MODULE_NO_SCROLL, MODULE_PORTAL, MODULE_ROOT, MODULE_TOOLBAR, NavigationAction, NoScrollSettings, PLUGIN_CAPTIONS, PLUGIN_COUNTER, PLUGIN_DOWNLOAD, PLUGIN_FULLSCREEN, PLUGIN_INLINE, PLUGIN_SHARE, PLUGIN_SLIDESHOW, PLUGIN_THUMBNAILS, PLUGIN_ZOOM, PluginProps, PortalSettings, RenderSlideContainerProps, RenderSlideFooterProps, RenderSlideHeaderProps, RenderSlideProps, SLIDE_STATUS_COMPLETE, SLIDE_STATUS_ERROR, SLIDE_STATUS_LOADING, SLIDE_STATUS_PLACEHOLDER, SLIDE_STATUS_PLAYING, SlideStatus, SlideTypeKey, SlideTypes, Slot, SlotStyles, SlotType, ToolbarButtonKey, ToolbarButtonKeys, UNKNOWN_ACTION_TYPE, VK_ARROW_LEFT, VK_ARROW_RIGHT, VK_ESCAPE, ViewCallbackProps, activeSlideStatus } from './types.js';
4
4
 
5
5
  /** Lightbox component */
@@ -46,9 +46,9 @@ declare function stopNavigationEventsPropagation(): {
46
46
  declare function calculatePreload(carousel: CarouselSettings, slides: Slide[], minimum?: number): number;
47
47
 
48
48
  declare function createModule(name: string, component: Component): Module;
49
- declare function createNode(module: Module, children?: Node[]): Node;
50
- declare function withPlugins(root: Node[], plugins?: Plugin[], augmentations?: Augmentation[]): {
51
- config: Node[];
49
+ declare function createNode(module: Module, children?: Node$1[]): Node$1;
50
+ declare function withPlugins(root: Node$1[], plugins?: Plugin[], augmentations?: Augmentation[]): {
51
+ config: Node$1[];
52
52
  augmentation: Augmentation;
53
53
  };
54
54
 
@@ -107,6 +107,17 @@ declare function useSensors<T extends Element>(): UseSensors<T>;
107
107
 
108
108
  declare function useThrottle(callback: (...args: any[]) => void, delay: number): (...args: any[]) => void;
109
109
 
110
+ type DocumentContextType = {
111
+ getOwnerDocument: (node?: Node | null) => Document;
112
+ getOwnerWindow: (node?: Node | null) => Window;
113
+ };
114
+ declare const DocumentContext: React.Context<DocumentContextType | null>;
115
+ declare const useDocumentContext: () => DocumentContextType;
116
+ type DocumentContextProviderProps = React.PropsWithChildren & {
117
+ nodeRef: React.RefObject<Node>;
118
+ };
119
+ declare function DocumentContextProvider({ nodeRef, children }: DocumentContextProviderProps): React.JSX.Element;
120
+
110
121
  type Topic = keyof EventTypes;
111
122
  type Event<T extends Topic> = EventTypes[T];
112
123
  type EventCallback<T extends Topic> = (...args: Event<T> extends void ? [] : [event: Event<T>]) => void;
@@ -197,6 +208,8 @@ type ImageSlideProps = Partial<Pick<CarouselSettings, "imageFit" | "imageProps">
197
208
  };
198
209
  declare function ImageSlide({ slide: image, offset, render, rect, imageFit, imageProps, onClick, onLoad, style, }: ImageSlideProps): React.JSX.Element;
199
210
 
211
+ declare const LightboxRoot: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
212
+
200
213
  declare function Carousel({ carousel }: ComponentProps): React.JSX.Element;
201
214
  declare const CarouselModule: Module;
202
215
 
@@ -266,4 +279,4 @@ declare const RootModule: Module;
266
279
  declare function Toolbar({ toolbar: { buttons }, render: { buttonClose, iconClose }, styles }: ComponentProps): React.JSX.Element;
267
280
  declare const ToolbarModule: Module;
268
281
 
269
- export { Augmentation, Callback, Carousel, CarouselModule, CarouselSettings, CloseIcon, Component, ComponentProps, type ComputeAnimation, ContainerRect, Controller, ControllerContext, type ControllerContextType, ControllerModule, ControllerRef, ControllerSettings, ErrorIcon, type Event, type EventCallback, EventTypes, EventsContext, type EventsContextType, EventsProvider, IconButton, type IconButtonProps, ImageSlide, type ImageSlideProps, type KeyboardEventType, Labels, LengthOrPercentage, Lightbox, LightboxDefaultProps, LightboxDispatchContext, type LightboxDispatchContextType, LightboxExternalProps, LightboxProps, LightboxPropsContext, type LightboxPropsContextType, LightboxPropsProvider, LightboxState, type LightboxStateAction, LightboxStateContext, type LightboxStateContextType, LightboxStateProvider, type LightboxStateProviderProps, LightboxStateSwipeAction, LightboxStateUpdateAction, LoadingIcon, Module, Navigation, NavigationButton, type NavigationButtonProps, NavigationModule, NextIcon, NoScroll, NoScrollModule, Node, Plugin, type PointerEventType, Portal, PortalModule, PreviousIcon, type Publish, type ReactEventType, type RegisterSensors, Render, RenderFunction, Root, RootModule, type SensorCallback, Slide, SlideImage, type Subscribe, type SubscribeSensors, type SupportedEventType, SwipeState, TimeoutsContext, type TimeoutsContextType, TimeoutsProvider, Toolbar, ToolbarModule, ToolbarSettings, type Topic, type Unsubscribe, type UseSensors, type WheelEventType, addToolbarButton, calculatePreload, cleanup, clsx, composePrefix, computeSlideRect, createIcon, createIconDisabled, createModule, createNode, cssClass, cssVar, Lightbox as default, devicePixelRatio, getSlide, getSlideIfPresent, getSlideIndex, getSlideKey, hasSlides, hasWindow, isImageFitCover, isImageSlide, label, makeComposePrefix, makeUseContext, parseInt, parseLengthPercentage, round, setRef, stopNavigationEventsPropagation, useAnimation, useContainerRect, useController, useDelay, useEventCallback, useEvents, useForkRef, useKeyboardNavigation, useLayoutEffect, useLightboxDispatch, useLightboxProps, useLightboxState, useLoseFocus, useMotionPreference, useNavigationState, usePointerSwipe, usePreventWheelDefaults, useRTL, useSensors, useThrottle, useTimeouts, useWheelSwipe, withPlugins };
282
+ export { Augmentation, Callback, Carousel, CarouselModule, CarouselSettings, CloseIcon, Component, ComponentProps, type ComputeAnimation, ContainerRect, Controller, ControllerContext, type ControllerContextType, ControllerModule, ControllerRef, ControllerSettings, DocumentContext, DocumentContextProvider, type DocumentContextProviderProps, type DocumentContextType, ErrorIcon, type Event, type EventCallback, EventTypes, EventsContext, type EventsContextType, EventsProvider, IconButton, type IconButtonProps, ImageSlide, type ImageSlideProps, type KeyboardEventType, Labels, LengthOrPercentage, Lightbox, LightboxDefaultProps, LightboxDispatchContext, type LightboxDispatchContextType, LightboxExternalProps, LightboxProps, LightboxPropsContext, type LightboxPropsContextType, LightboxPropsProvider, LightboxRoot, LightboxState, type LightboxStateAction, LightboxStateContext, type LightboxStateContextType, LightboxStateProvider, type LightboxStateProviderProps, LightboxStateSwipeAction, LightboxStateUpdateAction, LoadingIcon, Module, Navigation, NavigationButton, type NavigationButtonProps, NavigationModule, NextIcon, NoScroll, NoScrollModule, Node$1 as Node, Plugin, type PointerEventType, Portal, PortalModule, PreviousIcon, type Publish, type ReactEventType, type RegisterSensors, Render, RenderFunction, Root, RootModule, type SensorCallback, Slide, SlideImage, type Subscribe, type SubscribeSensors, type SupportedEventType, SwipeState, TimeoutsContext, type TimeoutsContextType, TimeoutsProvider, Toolbar, ToolbarModule, ToolbarSettings, type Topic, type Unsubscribe, type UseSensors, type WheelEventType, addToolbarButton, calculatePreload, cleanup, clsx, composePrefix, computeSlideRect, createIcon, createIconDisabled, createModule, createNode, cssClass, cssVar, Lightbox as default, devicePixelRatio, getSlide, getSlideIfPresent, getSlideIndex, getSlideKey, hasSlides, hasWindow, isImageFitCover, isImageSlide, label, makeComposePrefix, makeUseContext, parseInt, parseLengthPercentage, round, setRef, stopNavigationEventsPropagation, useAnimation, useContainerRect, useController, useDelay, useDocumentContext, useEventCallback, useEvents, useForkRef, useKeyboardNavigation, useLayoutEffect, useLightboxDispatch, useLightboxProps, useLightboxState, useLoseFocus, useMotionPreference, useNavigationState, usePointerSwipe, usePreventWheelDefaults, useRTL, useSensors, useThrottle, useTimeouts, useWheelSwipe, withPlugins };
package/dist/index.js CHANGED
@@ -254,6 +254,17 @@ function withPlugins(root, plugins = [], augmentations = []) {
254
254
  };
255
255
  }
256
256
 
257
+ const DocumentContext = React.createContext(null);
258
+ const useDocumentContext = makeUseContext("useDocument", "DocumentContext", DocumentContext);
259
+ function DocumentContextProvider({ nodeRef, children }) {
260
+ const context = React.useMemo(() => {
261
+ const getOwnerDocument = (node) => { var _a; return ((_a = (node || nodeRef.current)) === null || _a === void 0 ? void 0 : _a.ownerDocument) || document; };
262
+ const getOwnerWindow = (node) => { var _a; return ((_a = getOwnerDocument(node)) === null || _a === void 0 ? void 0 : _a.defaultView) || window; };
263
+ return { getOwnerDocument, getOwnerWindow };
264
+ }, [nodeRef]);
265
+ return React.createElement(DocumentContext.Provider, { value: context }, children);
266
+ }
267
+
257
268
  const EventsContext = React.createContext(null);
258
269
  const useEvents = makeUseContext("useEvents", "EventsContext", EventsContext);
259
270
  function EventsProvider({ children }) {
@@ -674,6 +685,12 @@ function ImageSlide({ slide: image, offset, render, rect, imageFit, imageProps,
674
685
  ((render === null || render === void 0 ? void 0 : render.iconError) ? (render.iconError()) : (React.createElement(ErrorIcon, { className: clsx(cssClass(ELEMENT_ICON), cssClass(slidePrefix(SLIDE_STATUS_ERROR))) })))))));
675
686
  }
676
687
 
688
+ const LightboxRoot = React.forwardRef(function LightboxRoot({ className, children, ...rest }, ref) {
689
+ const nodeRef = React.useRef(null);
690
+ return (React.createElement(DocumentContextProvider, { nodeRef: nodeRef },
691
+ React.createElement("div", { ref: useForkRef(ref, nodeRef), className: clsx(cssClass("root"), className), ...rest }, children)));
692
+ });
693
+
677
694
  var SwipeState;
678
695
  (function (SwipeState) {
679
696
  SwipeState[SwipeState["NONE"] = 0] = "NONE";
@@ -921,6 +938,7 @@ function Controller({ children, ...props }) {
921
938
  const handleContainerRef = useForkRef(usePreventWheelDefaults({ preventDefaultWheelX, preventDefaultWheelY }), setContainerRef);
922
939
  const carouselRef = React.useRef(null);
923
940
  const setCarouselRef = useForkRef(carouselRef, undefined);
941
+ const { getOwnerDocument } = useDocumentContext();
924
942
  const isRTL = useRTL();
925
943
  const rtl = (value) => (isRTL ? -1 : 1) * (typeof value === "number" ? value : 1);
926
944
  const focus = useEventCallback(() => { var _a; return (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.focus(); });
@@ -1111,10 +1129,9 @@ function Controller({ children, ...props }) {
1111
1129
  usePointerSwipe(...swipeParams, closeOnPullUp, closeOnPullDown, ...pullParams);
1112
1130
  useWheelSwipe(swipeState, ...swipeParams);
1113
1131
  const focusOnMount = useEventCallback(() => {
1114
- if (controller.focus) {
1115
- if (document.querySelector(`.${cssClass(MODULE_PORTAL)} .${cssClass(cssContainerPrefix())}`)) {
1116
- focus();
1117
- }
1132
+ if (controller.focus &&
1133
+ getOwnerDocument().querySelector(`.${cssClass(MODULE_PORTAL)} .${cssClass(cssContainerPrefix())}`)) {
1134
+ focus();
1118
1135
  }
1119
1136
  });
1120
1137
  React.useEffect(focusOnMount, [focusOnMount]);
@@ -1317,19 +1334,21 @@ function padScrollbar(element, padding, rtl) {
1317
1334
  }
1318
1335
  function NoScroll({ noScroll: { disabled }, children }) {
1319
1336
  const rtl = useRTL();
1320
- useLayoutEffect(() => {
1337
+ const { getOwnerDocument, getOwnerWindow } = useDocumentContext();
1338
+ React.useEffect(() => {
1321
1339
  if (disabled)
1322
1340
  return () => { };
1323
1341
  const cleanup = [];
1324
- const { body, documentElement } = document;
1325
- const scrollbar = Math.round(window.innerWidth - documentElement.clientWidth);
1342
+ const ownerWindow = getOwnerWindow();
1343
+ const { body, documentElement } = getOwnerDocument();
1344
+ const scrollbar = Math.round(ownerWindow.innerWidth - documentElement.clientWidth);
1326
1345
  if (scrollbar > 0) {
1327
1346
  cleanup.push(padScrollbar(body, scrollbar, rtl));
1328
1347
  const elements = body.getElementsByTagName("*");
1329
1348
  for (let i = 0; i < elements.length; i += 1) {
1330
1349
  const element = elements[i];
1331
1350
  if (isHTMLElement(element) &&
1332
- window.getComputedStyle(element).getPropertyValue("position") === "fixed" &&
1351
+ ownerWindow.getComputedStyle(element).getPropertyValue("position") === "fixed" &&
1333
1352
  !element.classList.contains(noScrollPadding)) {
1334
1353
  cleanup.push(padScrollbar(element, scrollbar, rtl));
1335
1354
  }
@@ -1340,7 +1359,7 @@ function NoScroll({ noScroll: { disabled }, children }) {
1340
1359
  body.classList.remove(noScroll);
1341
1360
  cleanup.forEach((clean) => clean());
1342
1361
  };
1343
- }, [rtl, disabled]);
1362
+ }, [rtl, disabled, getOwnerDocument, getOwnerWindow]);
1344
1363
  return React.createElement(React.Fragment, null, children);
1345
1364
  }
1346
1365
  const NoScrollModule = createModule(MODULE_NO_SCROLL, NoScroll);
@@ -1423,7 +1442,7 @@ function Portal({ children, animation, styles, className, on, portal, close }) {
1423
1442
  }
1424
1443
  }, [handleEnter, handleCleanup]);
1425
1444
  return mounted
1426
- ? createPortal(React.createElement("div", { ref: handleRef, className: clsx(className, cssClass("root"), cssClass(cssPrefix$1()), cssClass(CLASS_NO_SCROLL_PADDING), visible && cssClass(cssPrefix$1("open"))), role: "presentation", "aria-live": "polite", style: {
1445
+ ? createPortal(React.createElement(LightboxRoot, { ref: handleRef, className: clsx(className, cssClass(cssPrefix$1()), cssClass(CLASS_NO_SCROLL_PADDING), visible && cssClass(cssPrefix$1("open"))), role: "presentation", "aria-live": "polite", style: {
1427
1446
  ...(animation.fade !== LightboxDefaultProps.animation.fade
1428
1447
  ? { [cssVar("fade_animation_duration")]: `${animationDuration}ms` }
1429
1448
  : null),
@@ -1508,4 +1527,4 @@ function Lightbox({ carousel, animation, render, toolbar, controller, noScroll,
1508
1527
  React.createElement(EventsProvider, null, renderNode(createNode(RootModule, config), props))))));
1509
1528
  }
1510
1529
 
1511
- export { ACTION_CLOSE, ACTION_NEXT, ACTION_PREV, ACTION_SWIPE, CLASS_FLEX_CENTER, CLASS_NO_SCROLL, CLASS_NO_SCROLL_PADDING, CLASS_SLIDE_WRAPPER, Carousel, CarouselModule, CloseIcon, Controller, ControllerContext, ControllerModule, ELEMENT_BUTTON, ELEMENT_ICON, EVENT_ON_KEY_DOWN, EVENT_ON_KEY_UP, EVENT_ON_POINTER_CANCEL, EVENT_ON_POINTER_DOWN, EVENT_ON_POINTER_LEAVE, EVENT_ON_POINTER_MOVE, EVENT_ON_POINTER_UP, EVENT_ON_WHEEL, ErrorIcon, EventsContext, EventsProvider, IMAGE_FIT_CONTAIN, IMAGE_FIT_COVER, IconButton, ImageSlide, Lightbox, LightboxDefaultProps, LightboxDispatchContext, LightboxPropsContext, LightboxPropsProvider, LightboxStateContext, LightboxStateProvider, LoadingIcon, MODULE_CAROUSEL, MODULE_CONTROLLER, MODULE_NAVIGATION, MODULE_NO_SCROLL, MODULE_PORTAL, MODULE_ROOT, MODULE_TOOLBAR, Navigation, NavigationButton, NavigationModule, NextIcon, NoScroll, NoScrollModule, Portal, PortalModule, PreviousIcon, Root, RootModule, SLIDE_STATUS_COMPLETE, SLIDE_STATUS_ERROR, SLIDE_STATUS_LOADING, SLIDE_STATUS_PLACEHOLDER, SwipeState, TimeoutsContext, TimeoutsProvider, Toolbar, ToolbarModule, UNKNOWN_ACTION_TYPE, VK_ARROW_LEFT, VK_ARROW_RIGHT, VK_ESCAPE, activeSlideStatus, addToolbarButton, calculatePreload, cleanup, clsx, composePrefix, computeSlideRect, createIcon, createIconDisabled, createModule, createNode, cssClass, cssVar, Lightbox as default, devicePixelRatio, getSlide, getSlideIfPresent, getSlideIndex, getSlideKey, hasSlides, hasWindow, isImageFitCover, isImageSlide, label, makeComposePrefix, makeUseContext, parseInt, parseLengthPercentage, round, setRef, stopNavigationEventsPropagation, useAnimation, useContainerRect, useController, useDelay, useEventCallback, useEvents, useForkRef, useKeyboardNavigation, useLayoutEffect, useLightboxDispatch, useLightboxProps, useLightboxState, useLoseFocus, useMotionPreference, useNavigationState, usePointerEvents, usePointerSwipe, usePreventWheelDefaults, useRTL, useSensors, useThrottle, useTimeouts, useWheelSwipe, withPlugins };
1530
+ export { ACTION_CLOSE, ACTION_NEXT, ACTION_PREV, ACTION_SWIPE, CLASS_FLEX_CENTER, CLASS_NO_SCROLL, CLASS_NO_SCROLL_PADDING, CLASS_SLIDE_WRAPPER, Carousel, CarouselModule, CloseIcon, Controller, ControllerContext, ControllerModule, DocumentContext, DocumentContextProvider, ELEMENT_BUTTON, ELEMENT_ICON, EVENT_ON_KEY_DOWN, EVENT_ON_KEY_UP, EVENT_ON_POINTER_CANCEL, EVENT_ON_POINTER_DOWN, EVENT_ON_POINTER_LEAVE, EVENT_ON_POINTER_MOVE, EVENT_ON_POINTER_UP, EVENT_ON_WHEEL, ErrorIcon, EventsContext, EventsProvider, IMAGE_FIT_CONTAIN, IMAGE_FIT_COVER, IconButton, ImageSlide, Lightbox, LightboxDefaultProps, LightboxDispatchContext, LightboxPropsContext, LightboxPropsProvider, LightboxRoot, LightboxStateContext, LightboxStateProvider, LoadingIcon, MODULE_CAROUSEL, MODULE_CONTROLLER, MODULE_NAVIGATION, MODULE_NO_SCROLL, MODULE_PORTAL, MODULE_ROOT, MODULE_TOOLBAR, Navigation, NavigationButton, NavigationModule, NextIcon, NoScroll, NoScrollModule, Portal, PortalModule, PreviousIcon, Root, RootModule, SLIDE_STATUS_COMPLETE, SLIDE_STATUS_ERROR, SLIDE_STATUS_LOADING, SLIDE_STATUS_PLACEHOLDER, SwipeState, TimeoutsContext, TimeoutsProvider, Toolbar, ToolbarModule, UNKNOWN_ACTION_TYPE, VK_ARROW_LEFT, VK_ARROW_RIGHT, VK_ESCAPE, activeSlideStatus, addToolbarButton, calculatePreload, cleanup, clsx, composePrefix, computeSlideRect, createIcon, createIconDisabled, createModule, createNode, cssClass, cssVar, Lightbox as default, devicePixelRatio, getSlide, getSlideIfPresent, getSlideIndex, getSlideKey, hasSlides, hasWindow, isImageFitCover, isImageSlide, label, makeComposePrefix, makeUseContext, parseInt, parseLengthPercentage, round, setRef, stopNavigationEventsPropagation, useAnimation, useContainerRect, useController, useDelay, useDocumentContext, useEventCallback, useEvents, useForkRef, useKeyboardNavigation, useLayoutEffect, useLightboxDispatch, useLightboxProps, useLightboxState, useLoseFocus, useMotionPreference, useNavigationState, usePointerEvents, usePointerSwipe, usePreventWheelDefaults, useRTL, useSensors, useThrottle, useTimeouts, useWheelSwipe, withPlugins };
@@ -1,4 +1,4 @@
1
- import { makeUseContext, useLayoutEffect, useEventCallback, clsx, cssClass, createIcon, useLightboxProps, IconButton, addToolbarButton, createModule } from '../../index.js';
1
+ import { makeUseContext, useDocumentContext, useLayoutEffect, cleanup, useEventCallback, clsx, cssClass, createIcon, useLightboxProps, IconButton, addToolbarButton, createModule } from '../../index.js';
2
2
  import * as React from 'react';
3
3
  import { PLUGIN_FULLSCREEN, CLASS_FULLSIZE, PLUGIN_THUMBNAILS, MODULE_CONTROLLER } from '../../types.js';
4
4
 
@@ -19,69 +19,71 @@ function FullscreenContextProvider({ fullscreen: fullscreenProps, on, children }
19
19
  const [disabled, setDisabled] = React.useState();
20
20
  const [fullscreen, setFullscreen] = React.useState(false);
21
21
  const wasFullscreen = React.useRef(false);
22
+ const { getOwnerDocument } = useDocumentContext();
22
23
  useLayoutEffect(() => {
23
24
  var _a, _b, _c, _d;
24
- setDisabled(!((_d = (_c = (_b = (_a = document.fullscreenEnabled) !== null && _a !== void 0 ? _a : document.webkitFullscreenEnabled) !== null && _b !== void 0 ? _b : document.mozFullScreenEnabled) !== null && _c !== void 0 ? _c : document.msFullscreenEnabled) !== null && _d !== void 0 ? _d : false));
25
- }, []);
25
+ const ownerDocument = getOwnerDocument();
26
+ setDisabled(!((_d = (_c = (_b = (_a = ownerDocument.fullscreenEnabled) !== null && _a !== void 0 ? _a : ownerDocument.webkitFullscreenEnabled) !== null && _b !== void 0 ? _b : ownerDocument.mozFullScreenEnabled) !== null && _c !== void 0 ? _c : ownerDocument.msFullscreenEnabled) !== null && _d !== void 0 ? _d : false));
27
+ }, [getOwnerDocument]);
26
28
  const getFullscreenElement = React.useCallback(() => {
27
- var _a, _b, _c;
28
- return (_c = (_b = (_a = document.fullscreenElement) !== null && _a !== void 0 ? _a : document.webkitFullscreenElement) !== null && _b !== void 0 ? _b : document.mozFullScreenElement) !== null && _c !== void 0 ? _c : document.msFullscreenElement;
29
- }, []);
29
+ var _a;
30
+ const ownerDocument = getOwnerDocument();
31
+ const fullscreenElement = ownerDocument.fullscreenElement ||
32
+ ownerDocument.webkitFullscreenElement ||
33
+ ownerDocument.mozFullScreenElement ||
34
+ ownerDocument.msFullscreenElement;
35
+ return ((_a = fullscreenElement === null || fullscreenElement === void 0 ? void 0 : fullscreenElement.shadowRoot) === null || _a === void 0 ? void 0 : _a.fullscreenElement) || fullscreenElement;
36
+ }, [getOwnerDocument]);
30
37
  const enter = React.useCallback(() => {
31
38
  const container = containerRef.current;
32
- if (container) {
33
- try {
34
- if (container.requestFullscreen) {
35
- container.requestFullscreen().catch(() => { });
36
- }
37
- else if (container.webkitRequestFullscreen) {
38
- container.webkitRequestFullscreen();
39
- }
40
- else if (container.mozRequestFullScreen) {
41
- container.mozRequestFullScreen();
42
- }
43
- else if (container.msRequestFullscreen) {
44
- container.msRequestFullscreen();
45
- }
39
+ try {
40
+ if (container.requestFullscreen) {
41
+ container.requestFullscreen().catch(() => { });
42
+ }
43
+ else if (container.webkitRequestFullscreen) {
44
+ container.webkitRequestFullscreen();
46
45
  }
47
- catch (err) {
46
+ else if (container.mozRequestFullScreen) {
47
+ container.mozRequestFullScreen();
48
48
  }
49
+ else if (container.msRequestFullscreen) {
50
+ container.msRequestFullscreen();
51
+ }
52
+ }
53
+ catch (err) {
49
54
  }
50
55
  }, []);
51
56
  const exit = React.useCallback(() => {
52
- if (getFullscreenElement()) {
53
- try {
54
- if (document.exitFullscreen) {
55
- document.exitFullscreen().catch(() => { });
56
- }
57
- else if (document.webkitExitFullscreen) {
58
- document.webkitExitFullscreen();
59
- }
60
- else if (document.mozCancelFullScreen) {
61
- document.mozCancelFullScreen();
62
- }
63
- else if (document.msExitFullscreen) {
64
- document.msExitFullscreen();
65
- }
57
+ if (!getFullscreenElement())
58
+ return;
59
+ const ownerDocument = getOwnerDocument();
60
+ try {
61
+ if (ownerDocument.exitFullscreen) {
62
+ ownerDocument.exitFullscreen().catch(() => { });
66
63
  }
67
- catch (err) {
64
+ else if (ownerDocument.webkitExitFullscreen) {
65
+ ownerDocument.webkitExitFullscreen();
68
66
  }
67
+ else if (ownerDocument.mozCancelFullScreen) {
68
+ ownerDocument.mozCancelFullScreen();
69
+ }
70
+ else if (ownerDocument.msExitFullscreen) {
71
+ ownerDocument.msExitFullscreen();
72
+ }
73
+ }
74
+ catch (err) {
69
75
  }
70
- }, [getFullscreenElement]);
76
+ }, [getFullscreenElement, getOwnerDocument]);
71
77
  React.useEffect(() => {
72
- const events = ["fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "MSFullscreenChange"];
73
- const fullscreenChangeListener = () => {
78
+ const ownerDocument = getOwnerDocument();
79
+ const listener = () => {
74
80
  setFullscreen(getFullscreenElement() === containerRef.current);
75
81
  };
76
- events.forEach((event) => {
77
- document.addEventListener(event, fullscreenChangeListener);
78
- });
79
- return () => {
80
- events.forEach((event) => {
81
- document.removeEventListener(event, fullscreenChangeListener);
82
- });
83
- };
84
- }, [getFullscreenElement]);
82
+ return cleanup(...["fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "MSFullscreenChange"].map((event) => {
83
+ ownerDocument.addEventListener(event, listener);
84
+ return () => ownerDocument.removeEventListener(event, listener);
85
+ }));
86
+ }, [getFullscreenElement, getOwnerDocument]);
85
87
  const onEnterFullscreen = useEventCallback(() => { var _a; return (_a = on.enterFullscreen) === null || _a === void 0 ? void 0 : _a.call(on); });
86
88
  const onExitFullscreen = useEventCallback(() => { var _a; return (_a = on.exitFullscreen) === null || _a === void 0 ? void 0 : _a.call(on); });
87
89
  React.useEffect(() => {
@@ -92,17 +94,13 @@ function FullscreenContextProvider({ fullscreen: fullscreenProps, on, children }
92
94
  (fullscreen ? onEnterFullscreen : onExitFullscreen)();
93
95
  }
94
96
  }, [fullscreen, onEnterFullscreen, onExitFullscreen]);
95
- const handleAutoFullscreen = useEventCallback(() => { var _a; return (_a = (auto ? enter : null)) === null || _a === void 0 ? void 0 : _a(); });
96
- React.useEffect(() => {
97
- handleAutoFullscreen();
98
- return () => exit();
99
- }, [handleAutoFullscreen, exit]);
100
- const context = React.useMemo(() => ({
101
- fullscreen,
102
- disabled,
103
- enter,
104
- exit,
105
- }), [fullscreen, disabled, enter, exit]);
97
+ const handleAutoFullscreen = useEventCallback(() => {
98
+ var _a;
99
+ (_a = (auto ? enter : null)) === null || _a === void 0 ? void 0 : _a();
100
+ return exit;
101
+ });
102
+ React.useEffect(handleAutoFullscreen, [handleAutoFullscreen]);
103
+ const context = React.useMemo(() => ({ fullscreen, disabled, enter, exit }), [fullscreen, disabled, enter, exit]);
106
104
  React.useImperativeHandle(ref, () => context, [context]);
107
105
  return (React.createElement("div", { ref: containerRef, className: clsx(cssClass(PLUGIN_FULLSCREEN), cssClass(CLASS_FULLSIZE)) },
108
106
  React.createElement(FullscreenContext.Provider, { value: context }, children)));
@@ -1,9 +1,9 @@
1
- import { clsx, cssClass, cssVar, createModule } from '../../index.js';
1
+ import { LightboxRoot, clsx, cssClass, cssVar, createModule } from '../../index.js';
2
2
  import * as React from 'react';
3
3
  import { ACTION_CLOSE, MODULE_NO_SCROLL, MODULE_PORTAL, PLUGIN_INLINE } from '../../types.js';
4
4
 
5
5
  function InlineContainer({ inline: { className, style, ...rest } = {}, styles, children }) {
6
- return (React.createElement("div", { className: clsx(cssClass("root"), cssClass("relative"), className), style: { [cssVar("controller_overscroll_behavior")]: "contain auto", ...styles.root, ...style }, ...rest }, children));
6
+ return (React.createElement(LightboxRoot, { className: clsx(cssClass("relative"), className), style: { [cssVar("controller_overscroll_behavior")]: "contain auto", ...styles.root, ...style }, ...rest }, children));
7
7
  }
8
8
 
9
9
  function Inline({ augment, replace, remove }) {
@@ -1,10 +1,14 @@
1
1
  import * as React from 'react';
2
- import { PluginProps, PLUGIN_THUMBNAILS, Callback, ContainerRect, ImageFit, RenderFunction, Slide } from '../../types.js';
2
+ import { PluginProps, PLUGIN_THUMBNAILS, Callback, RenderFunction } from '../../types.js';
3
3
 
4
4
  /** Thumbnails plugin */
5
5
  declare function Thumbnails({ augment, contains, append, addParent }: PluginProps): void;
6
6
 
7
7
  declare module "yet-another-react-lightbox" {
8
+ interface GenericSlide {
9
+ /** thumbnail image */
10
+ thumbnail?: string;
11
+ }
8
12
  interface LightboxProps {
9
13
  /** Thumbnails plugin settings */
10
14
  thumbnails?: {
@@ -1,4 +1,4 @@
1
- import { useLightboxProps, composePrefix, createIcon, cssClass, isImageSlide, ImageSlide, makeComposePrefix, useEventCallback, clsx, cssVar, useRTL, useEvents, useLightboxState, useSensors, useKeyboardNavigation, useAnimation, cleanup, calculatePreload, hasSlides, getSlide, getSlideKey, makeUseContext, LightboxPropsProvider, createIconDisabled, IconButton, addToolbarButton, createModule } from '../../index.js';
1
+ import { useLightboxProps, composePrefix, createIcon, ImageSlide, isImageSlide, cssClass, makeComposePrefix, useDocumentContext, useEventCallback, clsx, cssVar, getSlideKey, useRTL, useEvents, useLightboxState, useSensors, useKeyboardNavigation, useAnimation, cleanup, calculatePreload, hasSlides, getSlide, makeUseContext, LightboxPropsProvider, createIconDisabled, IconButton, addToolbarButton, createModule } from '../../index.js';
2
2
  import * as React from 'react';
3
3
  import { PLUGIN_THUMBNAILS, ELEMENT_ICON, CLASS_FLEX_CENTER, ACTION_SWIPE, ACTION_NEXT, ACTION_PREV, PLUGIN_FULLSCREEN, MODULE_CONTROLLER } from '../../types.js';
4
4
 
@@ -34,13 +34,17 @@ function renderThumbnail({ slide, render, rect, imageFit }) {
34
34
  if (customThumbnail) {
35
35
  return customThumbnail;
36
36
  }
37
- const thumbnailIconClass = cssClass(cssThumbnailPrefix(ELEMENT_ICON));
37
+ const imageSlideProps = { render, rect, imageFit };
38
+ if (slide.thumbnail) {
39
+ return React.createElement(ImageSlide, { slide: { src: slide.thumbnail }, ...imageSlideProps });
40
+ }
38
41
  if (isImageSlide(slide)) {
39
- return React.createElement(ImageSlide, { slide: slide, render: render, rect: rect, imageFit: imageFit });
42
+ return React.createElement(ImageSlide, { slide: slide, ...imageSlideProps });
40
43
  }
44
+ const thumbnailIconClass = cssClass(cssThumbnailPrefix(ELEMENT_ICON));
41
45
  if (slide.type === "video") {
42
46
  return (React.createElement(React.Fragment, null,
43
- slide.poster && (React.createElement(ImageSlide, { key: slide.poster, slide: { src: slide.poster }, render: render, rect: rect, imageFit: imageFit })),
47
+ slide.poster && React.createElement(ImageSlide, { slide: { src: slide.poster }, ...imageSlideProps }),
44
48
  React.createElement(VideoThumbnailIcon, { className: thumbnailIconClass })));
45
49
  }
46
50
  return React.createElement(UnknownThumbnailIcon, { className: thumbnailIconClass });
@@ -54,14 +58,15 @@ const DURATION = "duration";
54
58
  function Thumbnail({ slide, onClick, active, fadeIn, fadeOut, placeholder, onLoseFocus }) {
55
59
  const ref = React.useRef(null);
56
60
  const { render, styles } = useLightboxProps();
61
+ const { getOwnerDocument } = useDocumentContext();
57
62
  const { width, height, imageFit } = useThumbnailsProps();
58
63
  const rect = { width, height };
59
64
  const onLoseFocusCallback = useEventCallback(onLoseFocus);
60
65
  React.useEffect(() => {
61
- if (fadeOut && document.activeElement === ref.current) {
66
+ if (fadeOut && getOwnerDocument().activeElement === ref.current) {
62
67
  onLoseFocusCallback();
63
68
  }
64
- }, [fadeOut, onLoseFocusCallback]);
69
+ }, [fadeOut, onLoseFocusCallback, getOwnerDocument]);
65
70
  return (React.createElement("button", { ref: ref, type: "button", className: clsx(cssClass(CLASS_FLEX_CENTER), cssClass(cssThumbnailPrefix()), active && cssClass(cssThumbnailPrefix(activePrefix())), fadeIn && cssClass(cssThumbnailPrefix(fadeInPrefix())), fadeOut && cssClass(cssThumbnailPrefix(fadeOutPrefix())), placeholder && cssClass(cssThumbnailPrefix(placeholderPrefix()))), style: {
66
71
  ...(fadeIn
67
72
  ? {
@@ -85,6 +90,13 @@ function isHorizontal(position) {
85
90
  function boxSize(thumbnails, dimension) {
86
91
  return dimension + 2 * (thumbnails.border + thumbnails.padding) + thumbnails.gap;
87
92
  }
93
+ function getThumbnailKey(slide) {
94
+ const { thumbnail, poster } = slide || { thumbnail: "placeholder" };
95
+ return ((typeof thumbnail === "string" && thumbnail) ||
96
+ (typeof poster === "string" && poster) ||
97
+ (slide && getSlideKey(slide)) ||
98
+ undefined);
99
+ }
88
100
  function ThumbnailsTrack({ visible, containerRef }) {
89
101
  const track = React.useRef(null);
90
102
  const isRTL = useRTL();
@@ -134,7 +146,7 @@ function ThumbnailsTrack({ visible, containerRef }) {
134
146
  (offset < 0 && index < globalIndex - preload) ||
135
147
  (offset > 0 && index > globalIndex + preload);
136
148
  const slide = !placeholder ? getSlide(slides, index) : null;
137
- const key = [`${index}`, slide ? getSlideKey(slide) : "placeholder"].filter(Boolean).join("|");
149
+ const key = [`${index}`, getThumbnailKey(slide)].filter(Boolean).join("|");
138
150
  items.push({ key, index, slide });
139
151
  }
140
152
  }
@@ -1,4 +1,4 @@
1
- import { PluginProps, GenericSlide } from '../../types.js';
1
+ import { PluginProps } from '../../types.js';
2
2
 
3
3
  /** Video plugin */
4
4
  declare function Video({ augment }: PluginProps): void;
@@ -44,6 +44,8 @@ declare module "yet-another-react-lightbox" {
44
44
  src: string;
45
45
  /** video source type (e.g., `video/mp4`) */
46
46
  type: string;
47
+ /** media query for the resource's intended media (e.g., `(min-width: 800px)`) */
48
+ media?: string;
47
49
  }[];
48
50
  }
49
51
  interface LightboxProps {
@@ -82,7 +82,7 @@ function VideoSlide({ slide, offset }) {
82
82
  publish(ACTIVE_SLIDE_PLAYING);
83
83
  }, onEnded: () => {
84
84
  publish(ACTIVE_SLIDE_COMPLETE);
85
- } }, sources.map(({ src, type }) => (React.createElement("source", { key: [src, type].join("|"), src: src, type: type })))))))));
85
+ } }, sources.map(({ src, type, media }) => (React.createElement("source", { key: [src, type, media].filter(Boolean).join("|"), src: src, type: type, media: media })))))))));
86
86
  }
87
87
 
88
88
  function isVideoSlide(slide) {
@@ -1,4 +1,4 @@
1
- import { useLightboxProps, useMotionPreference, useEventCallback, useLayoutEffect, useLightboxState, isImageSlide, isImageFitCover, round, useController, usePointerEvents, cleanup, makeUseContext, createIcon, IconButton, devicePixelRatio, ImageSlide, clsx, cssClass, addToolbarButton, createModule } from '../../index.js';
1
+ import { useLightboxProps, useMotionPreference, useEventCallback, useLayoutEffect, useLightboxState, isImageSlide, isImageFitCover, round, useDocumentContext, useController, usePointerEvents, cleanup, makeUseContext, createIcon, IconButton, devicePixelRatio, ImageSlide, clsx, cssClass, addToolbarButton, createModule } from '../../index.js';
2
2
  import * as React from 'react';
3
3
  import { EVENT_ON_KEY_DOWN, EVENT_ON_WHEEL, UNKNOWN_ACTION_TYPE, CLASS_FULLSIZE, CLASS_FLEX_CENTER, CLASS_SLIDE_WRAPPER, PLUGIN_ZOOM } from '../../types.js';
4
4
 
@@ -120,17 +120,18 @@ function useZoomSensors(zoom, maxZoom, disabled, changeZoom, changeOffsets, zoom
120
120
  const lastPointerDown = React.useRef(0);
121
121
  const pinchZoomDistance = React.useRef();
122
122
  const { globalIndex } = useLightboxState();
123
+ const { getOwnerWindow } = useDocumentContext();
123
124
  const { containerRef, subscribeSensors } = useController();
124
125
  const { keyboardMoveDistance, zoomInMultiplier, wheelZoomDistanceFactor, scrollToZoom, doubleTapDelay, doubleClickDelay, doubleClickMaxStops, pinchZoomDistanceFactor, } = useZoomProps();
125
126
  const translateCoordinates = React.useCallback((event) => {
126
127
  if (containerRef.current) {
127
128
  const { pageX, pageY } = event;
128
- const { scrollX, scrollY } = window;
129
+ const { scrollX, scrollY } = getOwnerWindow();
129
130
  const { left, top, width, height } = containerRef.current.getBoundingClientRect();
130
131
  return [pageX - left - scrollX - width / 2, pageY - top - scrollY - height / 2];
131
132
  }
132
133
  return [];
133
- }, [containerRef]);
134
+ }, [containerRef, getOwnerWindow]);
134
135
  const onKeyDown = useEventCallback((event) => {
135
136
  const preventDefault = () => {
136
137
  event.preventDefault();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yet-another-react-lightbox",
3
- "version": "3.17.5",
3
+ "version": "3.19.0",
4
4
  "description": "Modern React lightbox component",
5
5
  "author": "Igor Danchenko",
6
6
  "license": "MIT",