yet-another-react-lightbox 1.4.1 → 1.7.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
@@ -16,6 +16,7 @@ Modern React lightbox component. Performant, easy to use, customizable and exten
16
16
  - **Video:** video slides are supported via an optional plugin
17
17
  - **Customization:** customize any UI element or add your own custom slides
18
18
  - **No bloat:** never bundle rarely used features; add optional features via plugins
19
+ - **RTL:** compatible with RTL layout
19
20
  - **TypeScript:** type definitions come built-in in the package
20
21
 
21
22
  ## Documentation
@@ -130,6 +131,7 @@ The following plugins come bundled in the package:
130
131
  description
131
132
  - [Fullscreen](https://yet-another-react-lightbox.vercel.app/plugins/fullscreen) - adds support for fullscreen mode
132
133
  - [Inline](https://yet-another-react-lightbox.vercel.app/plugins/inline) - adds support for inline rendering mode
134
+ - [Slideshow](https://yet-another-react-lightbox.vercel.app/plugins/slideshow) - adds slideshow autoplay feature
133
135
  - [Video](https://yet-another-react-lightbox.vercel.app/plugins/video) - adds support for video slides
134
136
 
135
137
  ## License
@@ -1,8 +1,4 @@
1
- /// <reference types="react" />
2
- import { LightboxProps } from "./types.js";
3
- declare type DeepPartial<T, K extends keyof T> = Omit<T, K> & {
4
- [P in keyof Pick<T, K>]?: Partial<Pick<T, K>[P]>;
5
- };
6
- /** Modern React lightbox component */
7
- export declare const Lightbox: (props: DeepPartial<Partial<LightboxProps>, "carousel" | "animation" | "render" | "toolbar" | "controller" | "on">) => JSX.Element;
8
- export {};
1
+ import * as React from "react";
2
+ import { LightboxExternalProps } from "./types.js";
3
+ /** Lightbox component */
4
+ export declare const Lightbox: React.FC<LightboxExternalProps>;
package/dist/Lightbox.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { LightboxDefaultProps, LightboxPropTypes } from "./types.js";
2
+ import { LightboxDefaultProps } from "./types.js";
3
3
  import { CarouselModule, ControllerModule, CoreModule, createNode, NavigationModule, NoScrollModule, PortalModule, ToolbarModule, withPlugins, } from "./core/index.js";
4
4
  const renderNode = (node, props) => {
5
5
  var _a;
@@ -23,7 +23,6 @@ const LightboxComponent = (props) => {
23
23
  return null;
24
24
  return React.createElement(React.Fragment, null, renderNode(createNode(CoreModule, config), augmentedProps));
25
25
  };
26
- LightboxComponent.propTypes = LightboxPropTypes;
27
26
  export const Lightbox = (props) => {
28
27
  const { carousel, animation, render, toolbar, controller, on, ...restProps } = props;
29
28
  const { carousel: defaultCarousel, animation: defaultAnimation, render: defaultRender, toolbar: defaultToolbar, controller: defaultController, on: defaultOn, ...restDefaultProps } = LightboxDefaultProps;
@@ -3,7 +3,8 @@ import { Render, SlideImage } from "../../types.js";
3
3
  import { ContainerRect } from "../hooks/index.js";
4
4
  export declare type ImageSlideProps = {
5
5
  slide: SlideImage;
6
+ offset: number;
6
7
  render?: Render;
7
8
  rect?: ContainerRect;
8
9
  };
9
- export declare const ImageSlide: ({ slide: image, render, rect }: ImageSlideProps) => JSX.Element;
10
+ export declare const ImageSlide: ({ slide: image, offset, render, rect }: ImageSlideProps) => JSX.Element;
@@ -1,14 +1,24 @@
1
1
  import * as React from "react";
2
2
  import { adjustDevicePixelRatio, clsx, cssClass, hasWindow } from "../utils.js";
3
3
  import { useLatest } from "../hooks/index.js";
4
+ import { useEvents } from "../contexts/index.js";
4
5
  import { ErrorIcon, LoadingIcon } from "./Icons.js";
5
- export const ImageSlide = ({ slide: image, render, rect }) => {
6
+ import { activeSlideStatus, SLIDE_STATUS_COMPLETE, SLIDE_STATUS_ERROR, SLIDE_STATUS_LOADING } from "../consts.js";
7
+ import { useController } from "../modules/Controller.js";
8
+ export const ImageSlide = ({ slide: image, offset, render, rect }) => {
6
9
  var _a;
7
- const [state, setState] = React.useState("loading");
8
- const latestState = useLatest(state);
10
+ const [status, setStatus] = React.useState(SLIDE_STATUS_LOADING);
11
+ const latestStatus = useLatest(status);
12
+ const { latestProps } = useController();
13
+ const { publish } = useEvents();
9
14
  const imageRef = React.useRef(null);
15
+ React.useEffect(() => {
16
+ if (offset === 0) {
17
+ publish(activeSlideStatus(status));
18
+ }
19
+ }, [offset, status, publish]);
10
20
  const handleLoading = React.useCallback((img) => {
11
- if (latestState.current === "complete") {
21
+ if (latestStatus.current === SLIDE_STATUS_COMPLETE) {
12
22
  return;
13
23
  }
14
24
  ("decode" in img ? img.decode() : Promise.resolve())
@@ -17,9 +27,9 @@ export const ImageSlide = ({ slide: image, render, rect }) => {
17
27
  if (!img.parentNode) {
18
28
  return;
19
29
  }
20
- setState("complete");
30
+ setStatus(SLIDE_STATUS_COMPLETE);
21
31
  });
22
- }, [latestState]);
32
+ }, [latestStatus]);
23
33
  const setImageRef = React.useCallback((img) => {
24
34
  imageRef.current = img;
25
35
  if (img === null || img === void 0 ? void 0 : img.complete) {
@@ -30,10 +40,12 @@ export const ImageSlide = ({ slide: image, render, rect }) => {
30
40
  handleLoading(event.currentTarget);
31
41
  }, [handleLoading]);
32
42
  const onError = React.useCallback(() => {
33
- setState("error");
43
+ setStatus(SLIDE_STATUS_ERROR);
34
44
  }, []);
35
45
  return (React.createElement(React.Fragment, null,
36
- React.createElement("img", { ref: setImageRef, onLoad: onLoad, onError: onError, className: clsx(cssClass("slide_image"), state !== "complete" && cssClass("slide_image_loading")), draggable: false, alt: image.alt, ...(image.srcSet
46
+ React.createElement("img", { ref: setImageRef, onLoad: onLoad, onError: onError, className: clsx(cssClass("slide_image"), (image.imageFit === "cover" ||
47
+ (image.imageFit !== "contain" && latestProps.current.carousel.imageFit === "cover")) &&
48
+ cssClass("slide_image_cover"), status !== SLIDE_STATUS_COMPLETE && cssClass("slide_image_loading")), draggable: false, alt: image.alt, ...(image.srcSet
37
49
  ? {
38
50
  ...(rect && hasWindow()
39
51
  ? {
@@ -57,9 +69,9 @@ export const ImageSlide = ({ slide: image, render, rect }) => {
57
69
  }
58
70
  : undefined,
59
71
  }), src: image.src }),
60
- state !== "complete" && (React.createElement("div", { className: cssClass("slide_placeholder") },
61
- state === "loading" &&
72
+ status !== SLIDE_STATUS_COMPLETE && (React.createElement("div", { className: cssClass("slide_placeholder") },
73
+ status === SLIDE_STATUS_LOADING &&
62
74
  ((render === null || render === void 0 ? void 0 : render.iconLoading) ? (render.iconLoading()) : (React.createElement(LoadingIcon, { className: clsx(cssClass("icon"), cssClass("slide_loading")) }))),
63
- state === "error" &&
75
+ status === SLIDE_STATUS_ERROR &&
64
76
  ((render === null || render === void 0 ? void 0 : render.iconError) ? (render.iconError()) : (React.createElement(ErrorIcon, { className: clsx(cssClass("icon"), cssClass("slide_error")) })))))));
65
77
  };
@@ -0,0 +1,10 @@
1
+ export declare const SLIDE_STATUS_LOADING = "loading";
2
+ export declare const SLIDE_STATUS_PLAYING = "playing";
3
+ export declare const SLIDE_STATUS_ERROR = "error";
4
+ export declare const SLIDE_STATUS_COMPLETE = "complete";
5
+ export declare type SlideStatus = typeof SLIDE_STATUS_LOADING | typeof SLIDE_STATUS_PLAYING | typeof SLIDE_STATUS_ERROR | typeof SLIDE_STATUS_COMPLETE;
6
+ export declare const activeSlideStatus: (status: SlideStatus) => string;
7
+ export declare const ACTIVE_SLIDE_LOADING: string;
8
+ export declare const ACTIVE_SLIDE_PLAYING: string;
9
+ export declare const ACTIVE_SLIDE_ERROR: string;
10
+ export declare const ACTIVE_SLIDE_COMPLETE: string;
@@ -0,0 +1,9 @@
1
+ export const SLIDE_STATUS_LOADING = "loading";
2
+ export const SLIDE_STATUS_PLAYING = "playing";
3
+ export const SLIDE_STATUS_ERROR = "error";
4
+ export const SLIDE_STATUS_COMPLETE = "complete";
5
+ export const activeSlideStatus = (status) => `active-slide-${status}`;
6
+ export const ACTIVE_SLIDE_LOADING = activeSlideStatus(SLIDE_STATUS_LOADING);
7
+ export const ACTIVE_SLIDE_PLAYING = activeSlideStatus(SLIDE_STATUS_PLAYING);
8
+ export const ACTIVE_SLIDE_ERROR = activeSlideStatus(SLIDE_STATUS_ERROR);
9
+ export const ACTIVE_SLIDE_COMPLETE = activeSlideStatus(SLIDE_STATUS_COMPLETE);
@@ -1,3 +1,4 @@
1
+ export * from "./consts.js";
1
2
  export * from "./utils.js";
2
3
  export * from "./config.js";
3
4
  export * from "./hooks/index.js";
@@ -1,3 +1,4 @@
1
+ export * from "./consts.js";
1
2
  export * from "./utils.js";
2
3
  export * from "./config.js";
3
4
  export * from "./hooks/index.js";
@@ -13,7 +13,7 @@ const CarouselSlide = ({ slide, offset }) => {
13
13
  var _a, _b, _c, _d;
14
14
  let rendered = (_a = render.slide) === null || _a === void 0 ? void 0 : _a.call(render, slide, offset, rect);
15
15
  if (!rendered && "src" in slide) {
16
- rendered = React.createElement(ImageSlide, { slide: slide, render: render, rect: rect });
16
+ rendered = React.createElement(ImageSlide, { slide: slide, offset: offset, render: render, rect: rect });
17
17
  }
18
18
  return rendered ? (React.createElement(React.Fragment, null, (_b = render.slideHeader) === null || _b === void 0 ? void 0 :
19
19
  _b.call(render, slide),
@@ -1,13 +1,17 @@
1
1
  import * as React from "react";
2
2
  import { Component, ComponentProps } from "../../types.js";
3
3
  import { SubscribeSensors } from "../hooks/index.js";
4
- export declare type ControllerContextType = {
5
- latestProps: React.MutableRefObject<ComponentProps>;
6
- containerRef: React.RefObject<HTMLDivElement>;
4
+ declare type ControllerState = {
7
5
  currentIndex: number;
8
6
  globalIndex: number;
7
+ isRTL: boolean;
8
+ };
9
+ export declare type ControllerContextType = ControllerState & {
10
+ latestProps: React.MutableRefObject<ComponentProps>;
11
+ containerRef: React.RefObject<HTMLDivElement>;
9
12
  subscribeSensors: SubscribeSensors<HTMLDivElement>;
10
13
  };
11
14
  export declare const useController: () => ControllerContextType;
12
15
  export declare const Controller: Component;
13
16
  export declare const ControllerModule: import("../../types.js").Module;
17
+ export {};
@@ -15,6 +15,7 @@ export const Controller = ({ children, ...props }) => {
15
15
  const [state, setState] = React.useState({
16
16
  currentIndex: props.index,
17
17
  globalIndex: props.index,
18
+ isRTL: false,
18
19
  });
19
20
  const latestProps = useLatest(props);
20
21
  const refs = React.useRef({
@@ -29,7 +30,11 @@ export const Controller = ({ children, ...props }) => {
29
30
  refs.current.state = state;
30
31
  refs.current.props = props;
31
32
  useEnhancedEffect(() => {
32
- const preventDefault = (event) => event.preventDefault();
33
+ const preventDefault = (event) => {
34
+ if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) {
35
+ event.preventDefault();
36
+ }
37
+ };
33
38
  const node = containerRef.current;
34
39
  if (node) {
35
40
  node.addEventListener("wheel", preventDefault, { passive: false });
@@ -40,6 +45,12 @@ export const Controller = ({ children, ...props }) => {
40
45
  }
41
46
  };
42
47
  }, [containerRef]);
48
+ useEnhancedEffect(() => {
49
+ const node = containerRef.current;
50
+ if (node) {
51
+ setState((prev) => ({ ...prev, isRTL: window.getComputedStyle(node).direction === "rtl" }));
52
+ }
53
+ }, [containerRef]);
43
54
  React.useEffect(() => {
44
55
  var _a;
45
56
  if (refs.current.props.controller.focus) {
@@ -76,11 +87,12 @@ export const Controller = ({ children, ...props }) => {
76
87
  clearTimeout(current.swipeIntentCleanup);
77
88
  current.swipeIntentCleanup = undefined;
78
89
  }, [clearTimeout]);
90
+ const rtl = React.useCallback((value) => (refs.current.state.isRTL ? -1 : 1) * (typeof value === "number" ? value : 1), [refs]);
79
91
  const isSwipeValid = React.useCallback((offset) => {
80
92
  const { state: { currentIndex }, props: { carousel, slides }, } = refs.current;
81
93
  return !(carousel.finite &&
82
- ((offset > 0 && currentIndex === 0) || (offset < 0 && currentIndex === slides.length - 1)));
83
- }, []);
94
+ ((rtl(offset) > 0 && currentIndex === 0) || (rtl(offset) < 0 && currentIndex === slides.length - 1)));
95
+ }, [rtl]);
84
96
  const swipe = React.useCallback((direction) => {
85
97
  var _a;
86
98
  const { current } = refs;
@@ -105,7 +117,7 @@ export const Controller = ({ children, ...props }) => {
105
117
  newSwipeAnimationDuration =
106
118
  (newSwipeAnimationDuration / expectedTime) * Math.max(elapsedTime, expectedTime / 5);
107
119
  }
108
- direction = swipeOffset > 0 ? "prev" : "next";
120
+ direction = rtl(swipeOffset) > 0 ? "prev" : "next";
109
121
  }
110
122
  else {
111
123
  newSwipeAnimationDuration = swipeAnimationDuration / 2;
@@ -113,7 +125,7 @@ export const Controller = ({ children, ...props }) => {
113
125
  }
114
126
  const newState = {};
115
127
  if (direction === "prev") {
116
- if (isSwipeValid(1)) {
128
+ if (isSwipeValid(rtl(1))) {
117
129
  newState.currentIndex = (currentIndex - 1 + slidesCount) % slidesCount;
118
130
  newState.globalIndex = globalIndex - 1;
119
131
  }
@@ -123,7 +135,7 @@ export const Controller = ({ children, ...props }) => {
123
135
  }
124
136
  }
125
137
  else if (direction === "next") {
126
- if (isSwipeValid(-1)) {
138
+ if (isSwipeValid(rtl(-1))) {
127
139
  newState.currentIndex = (currentIndex + 1) % slidesCount;
128
140
  newState.globalIndex = globalIndex + 1;
129
141
  }
@@ -143,7 +155,7 @@ export const Controller = ({ children, ...props }) => {
143
155
  }, newSwipeAnimationDuration);
144
156
  }
145
157
  setState((prev) => ({ ...prev, ...newState }));
146
- }, [setTimeout, resetSwipe, isSwipeValid, rerender, containerRef]);
158
+ }, [setTimeout, resetSwipe, isSwipeValid, rerender, containerRef, rtl]);
147
159
  React.useEffect(() => cleanup(subscribe("prev", () => swipe("prev")), subscribe("next", () => swipe("next"))), [subscribe, swipe]);
148
160
  React.useEffect(() => subscribeSensors("onKeyUp", (event) => {
149
161
  if (event.code === "Escape") {
@@ -266,8 +278,9 @@ export const Controller = ({ children, ...props }) => {
266
278
  containerRef,
267
279
  currentIndex: state.currentIndex,
268
280
  globalIndex: state.globalIndex,
281
+ isRTL: state.isRTL,
269
282
  subscribeSensors,
270
- }), [latestProps, containerRef, state.currentIndex, state.globalIndex, subscribeSensors]);
283
+ }), [latestProps, containerRef, state.currentIndex, state.globalIndex, state.isRTL, subscribeSensors]);
271
284
  return (React.createElement("div", { ref: setContainerRef, className: clsx(cssClass("container"), refs.current.swipeState === "swipe" && cssClass("container_swipe")), style: refs.current.swipeAnimationDuration !== LightboxDefaultProps.animation.swipe
272
285
  ? {
273
286
  [cssVar("swipe_animation_duration")]: `${Math.round(refs.current.swipeAnimationDuration)}ms`,
@@ -8,16 +8,16 @@ export const NavigationButton = ({ publish, labels, label, icon, renderIcon, act
8
8
  publish(action);
9
9
  } }));
10
10
  export const Navigation = ({ slides, carousel: { finite }, labels, render: { buttonPrev, buttonNext, iconPrev, iconNext }, }) => {
11
- const { currentIndex, subscribeSensors } = useController();
11
+ const { currentIndex, subscribeSensors, isRTL } = useController();
12
12
  const { publish } = useEvents();
13
13
  React.useEffect(() => subscribeSensors("onKeyUp", (event) => {
14
14
  if (event.code === "ArrowLeft") {
15
- publish("prev");
15
+ publish(isRTL ? "next" : "prev");
16
16
  }
17
17
  else if (event.code === "ArrowRight") {
18
- publish("next");
18
+ publish(isRTL ? "prev" : "next");
19
19
  }
20
- }), [subscribeSensors, publish]);
20
+ }), [subscribeSensors, publish, isRTL]);
21
21
  return (React.createElement(React.Fragment, null,
22
22
  buttonPrev ? (buttonPrev()) : (React.createElement(NavigationButton, { label: "Previous", action: "prev", icon: PreviousIcon, renderIcon: iconPrev, disabled: finite && currentIndex === 0, labels: labels, publish: publish })),
23
23
  buttonNext ? (buttonNext()) : (React.createElement(NavigationButton, { label: "Next", action: "next", icon: NextIcon, renderIcon: iconNext, disabled: finite && currentIndex === slides.length - 1, labels: labels, publish: publish }))));
@@ -0,0 +1,31 @@
1
+ import * as React from "react";
2
+ import { Plugin } from "../types.js";
3
+ declare module "../types.js" {
4
+ interface LightboxProps {
5
+ /** Slideshow plugin settings */
6
+ slideshow?: {
7
+ /** if `true`, slideshow is turned on automatically when the lightbox opens */
8
+ autoplay?: boolean;
9
+ /** slideshow delay in milliseconds */
10
+ delay?: number;
11
+ };
12
+ }
13
+ interface Render {
14
+ /** render custom Slideshow Play icon */
15
+ iconSlideshowPlay?: () => React.ReactNode;
16
+ /** render custom Slideshow Pause icon */
17
+ iconSlideshowPause?: () => React.ReactNode;
18
+ /** render custom Slideshow button */
19
+ buttonSlideshow?: ({ playing, togglePlaying, disabled, }: {
20
+ /** current slideshow autoplay status */
21
+ playing: boolean;
22
+ /** toggle slideshow autoplay status */
23
+ togglePlaying: () => void;
24
+ /** if `true`, the button is disabled */
25
+ disabled: boolean;
26
+ }) => React.ReactNode;
27
+ }
28
+ }
29
+ /** Slideshow plugin */
30
+ export declare const Slideshow: Plugin;
31
+ export default Slideshow;
@@ -0,0 +1,88 @@
1
+ import * as React from "react";
2
+ import { ACTIVE_SLIDE_COMPLETE, ACTIVE_SLIDE_ERROR, ACTIVE_SLIDE_LOADING, ACTIVE_SLIDE_PLAYING, cleanup, createIcon, IconButton, label, SLIDE_STATUS_COMPLETE, SLIDE_STATUS_ERROR, SLIDE_STATUS_LOADING, SLIDE_STATUS_PLAYING, useController, useEvents, useLatest, useTimeouts, } from "../core/index.js";
3
+ const defaultSlideshowProps = {
4
+ autoplay: false,
5
+ delay: 3000,
6
+ };
7
+ const PlayIcon = createIcon("Play", React.createElement("path", { d: "M8 5v14l11-7z" }));
8
+ const PauseIcon = createIcon("Pause", React.createElement("path", { d: "M6 19h4V5H6v14zm8-14v14h4V5h-4z" }));
9
+ const SlideshowButton = () => {
10
+ const { currentIndex, latestProps } = useController();
11
+ const { setTimeout, clearTimeout } = useTimeouts();
12
+ const { publish, subscribe } = useEvents();
13
+ const slideshow = {
14
+ ...defaultSlideshowProps,
15
+ ...latestProps.current.slideshow,
16
+ };
17
+ const [playing, setPlaying] = React.useState(slideshow.autoplay);
18
+ const scheduler = React.useRef();
19
+ const refs = useLatest({
20
+ playing,
21
+ delay: slideshow.delay,
22
+ currentIndex,
23
+ finite: latestProps.current.carousel.finite,
24
+ slidesCount: latestProps.current.slides.length,
25
+ });
26
+ const slideStatus = React.useRef();
27
+ const cancelScheduler = React.useCallback(() => {
28
+ clearTimeout(scheduler.current);
29
+ scheduler.current = undefined;
30
+ }, [clearTimeout]);
31
+ const reachedLastSlide = React.useCallback(() => refs.current.finite && refs.current.currentIndex === refs.current.slidesCount - 1, [refs]);
32
+ const scheduleNextSlide = React.useCallback(() => {
33
+ cancelScheduler();
34
+ if (!refs.current.playing ||
35
+ reachedLastSlide() ||
36
+ slideStatus.current === SLIDE_STATUS_LOADING ||
37
+ slideStatus.current === SLIDE_STATUS_PLAYING) {
38
+ return;
39
+ }
40
+ scheduler.current = setTimeout(() => {
41
+ if (refs.current.playing) {
42
+ slideStatus.current = undefined;
43
+ publish("next");
44
+ }
45
+ }, refs.current.delay);
46
+ }, [publish, setTimeout, cancelScheduler, refs, reachedLastSlide]);
47
+ const togglePlaying = React.useCallback(() => {
48
+ setPlaying((prev) => !prev);
49
+ }, []);
50
+ React.useEffect(() => {
51
+ scheduleNextSlide();
52
+ }, [currentIndex, playing, scheduleNextSlide]);
53
+ React.useEffect(() => {
54
+ if (playing && reachedLastSlide()) {
55
+ setPlaying(false);
56
+ }
57
+ }, [currentIndex, playing, reachedLastSlide]);
58
+ React.useEffect(() => cleanup(subscribe(ACTIVE_SLIDE_LOADING, () => {
59
+ slideStatus.current = SLIDE_STATUS_LOADING;
60
+ cancelScheduler();
61
+ }), subscribe(ACTIVE_SLIDE_PLAYING, () => {
62
+ slideStatus.current = SLIDE_STATUS_PLAYING;
63
+ cancelScheduler();
64
+ }), subscribe(ACTIVE_SLIDE_ERROR, () => {
65
+ slideStatus.current = SLIDE_STATUS_ERROR;
66
+ scheduleNextSlide();
67
+ }), subscribe(ACTIVE_SLIDE_COMPLETE, () => {
68
+ slideStatus.current = SLIDE_STATUS_COMPLETE;
69
+ scheduleNextSlide();
70
+ })), [subscribe, cancelScheduler, scheduleNextSlide]);
71
+ const { render, labels } = latestProps.current;
72
+ const disabled = reachedLastSlide();
73
+ return render.buttonSlideshow ? (React.createElement(React.Fragment, null, render.buttonSlideshow({ playing, togglePlaying, disabled }))) : (React.createElement(IconButton, { label: playing ? label(labels, "Pause") : label(labels, "Play"), icon: playing ? PauseIcon : PlayIcon, renderIcon: playing ? render.iconSlideshowPause : render.iconSlideshowPlay, onClick: togglePlaying, disabled: disabled, "aria-disabled": disabled }));
74
+ };
75
+ export const Slideshow = ({ augment }) => {
76
+ augment(({ slideshow: originalSlideshow, toolbar: { buttons, ...restToolbar }, ...restProps }) => ({
77
+ toolbar: {
78
+ buttons: [React.createElement(SlideshowButton, { key: "slideshow" }), ...buttons],
79
+ ...restToolbar,
80
+ },
81
+ slideshow: {
82
+ ...defaultSlideshowProps,
83
+ ...originalSlideshow,
84
+ },
85
+ ...restProps,
86
+ }));
87
+ };
88
+ export default Slideshow;
@@ -1,4 +1,4 @@
1
- /// <reference types="react" />
1
+ import * as React from "react";
2
2
  import { Plugin } from "../types.js";
3
3
  /** Video slide attributes */
4
4
  export interface SlideVideo {
@@ -10,6 +10,26 @@ export interface SlideVideo {
10
10
  width?: number;
11
11
  /** video height in pixels */
12
12
  height?: number;
13
+ /** if `true`, the video automatically begins to play */
14
+ autoPlay?: boolean;
15
+ /** if `true`, the browser will offer controls to allow the user to control video playback */
16
+ controls?: boolean;
17
+ /** indicates what controls to show */
18
+ controlsList?: string;
19
+ /** indicates whether to use CORS to fetch the related video */
20
+ crossOrigin?: string;
21
+ /** video preload setting */
22
+ preload?: string;
23
+ /** if `true`, the browser will automatically seek back to the start upon reaching the end of the video */
24
+ loop?: boolean;
25
+ /** the default setting of the audio contained in the video */
26
+ muted?: boolean;
27
+ /** if `true`, the video is to be played "inline", that is within the element's playback area */
28
+ playsInline?: boolean;
29
+ /** prevents the browser from suggesting a Picture-in-Picture context menu */
30
+ disablePictureInPicture?: boolean;
31
+ /** disables the capability of remote playback */
32
+ disableRemotePlayback?: boolean;
13
33
  /** an array of video files */
14
34
  sources?: {
15
35
  /** video source URL */
@@ -23,11 +43,17 @@ declare module "../types.js" {
23
43
  /** video slide type */
24
44
  SlideVideo: SlideVideo;
25
45
  }
46
+ interface LightboxProps {
47
+ /** video plugin settings */
48
+ video?: Pick<SlideVideo, "autoPlay" | "controls" | "controlsList" | "crossOrigin" | "preload" | "loop" | "muted" | "playsInline" | "disablePictureInPicture" | "disableRemotePlayback">;
49
+ }
26
50
  }
27
- /** Video slide */
28
- export declare const VideoSlide: ({ slide: { sources, poster, width, height } }: {
51
+ declare type VideoSlideProps = {
29
52
  slide: SlideVideo;
30
- }) => JSX.Element;
53
+ offset: number;
54
+ };
55
+ /** Video slide */
56
+ export declare const VideoSlide: React.FC<VideoSlideProps>;
31
57
  /** Video plugin */
32
58
  export declare const Video: Plugin;
33
59
  export default Video;
@@ -1,19 +1,40 @@
1
1
  import * as React from "react";
2
- import PropTypes from "prop-types";
3
- import { SlideTypesPropTypes } from "../types.js";
4
- import { clsx, cssClass, useContainerRect } from "../core/index.js";
5
- SlideTypesPropTypes.push(PropTypes.shape({
6
- type: PropTypes.oneOf(["video"]).isRequired,
7
- poster: PropTypes.string,
8
- width: PropTypes.number,
9
- height: PropTypes.number,
10
- sources: PropTypes.arrayOf(PropTypes.shape({
11
- src: PropTypes.string.isRequired,
12
- type: PropTypes.string.isRequired,
13
- }).isRequired),
14
- }));
15
- export const VideoSlide = ({ slide: { sources, poster, width, height } }) => {
2
+ import { ACTIVE_SLIDE_COMPLETE, ACTIVE_SLIDE_LOADING, ACTIVE_SLIDE_PLAYING, clsx, cssClass, useContainerRect, useController, useEvents, useLatest, } from "../core/index.js";
3
+ const defaultVideoProps = {
4
+ controls: true,
5
+ playsInline: true,
6
+ };
7
+ export const VideoSlide = ({ slide, offset }) => {
8
+ var _a;
9
+ const { latestProps } = useController();
10
+ const { publish } = useEvents();
16
11
  const { setContainerRef, containerRect } = useContainerRect();
12
+ const videoRef = React.useRef(null);
13
+ const video = (_a = latestProps.current.video) !== null && _a !== void 0 ? _a : defaultVideoProps;
14
+ React.useEffect(() => {
15
+ if (offset !== 0 && videoRef.current && !videoRef.current.paused) {
16
+ videoRef.current.pause();
17
+ }
18
+ }, [offset]);
19
+ React.useEffect(() => {
20
+ if (offset === 0 && videoRef.current && (slide.autoPlay || video.autoPlay)) {
21
+ publish(ACTIVE_SLIDE_LOADING);
22
+ videoRef.current.play().catch(() => { });
23
+ }
24
+ }, [offset, video.autoPlay, slide.autoPlay, publish]);
25
+ const latestOffset = useLatest(offset);
26
+ const latestVideoAutoPlay = useLatest(video.autoPlay);
27
+ const latestSlideAutoPlay = useLatest(slide.autoPlay);
28
+ const setVideoRef = React.useCallback((el) => {
29
+ videoRef.current = el;
30
+ if (el &&
31
+ latestOffset.current === 0 &&
32
+ (latestVideoAutoPlay.current || latestSlideAutoPlay.current) &&
33
+ el.paused) {
34
+ el.play().catch(() => { });
35
+ }
36
+ }, [latestOffset, latestVideoAutoPlay, latestSlideAutoPlay]);
37
+ const { width, height, poster, sources } = slide;
17
38
  const scaleWidthAndHeight = () => {
18
39
  if (!width || !height || !containerRect)
19
40
  return null;
@@ -23,23 +44,48 @@ export const VideoSlide = ({ slide: { sources, poster, width, height } }) => {
23
44
  height: !widthBound ? containerRect.height : Math.round((containerRect.width / width) * height),
24
45
  };
25
46
  };
47
+ const resolveBoolean = (attr) => {
48
+ if (slide[attr] === false)
49
+ return null;
50
+ if (slide[attr] === true)
51
+ return { [attr]: true };
52
+ if (video[attr] === false)
53
+ return null;
54
+ if (video[attr] === true)
55
+ return { [attr]: true };
56
+ return null;
57
+ };
58
+ const resolveString = (attr) => {
59
+ if (video[attr] || slide[attr]) {
60
+ return { [attr]: slide[attr] || video[attr] };
61
+ }
62
+ return null;
63
+ };
26
64
  return (React.createElement(React.Fragment, null, sources && (React.createElement("div", { ref: setContainerRef, style: {
27
65
  width: "100%",
28
66
  height: "100%",
29
67
  ...(width ? { maxWidth: `${width}px` } : null),
30
- }, className: clsx(cssClass("video_container"), cssClass("flex_center")) }, containerRect && (React.createElement("video", { controls: true, playsInline: true, poster: poster, ...scaleWidthAndHeight() }, sources.map(({ src, type }, index) => (React.createElement("source", { key: index, src: src, type: type })))))))));
68
+ }, className: clsx(cssClass("video_container"), cssClass("flex_center")) }, containerRect && (React.createElement("video", { ref: setVideoRef, poster: poster, ...scaleWidthAndHeight(), ...resolveBoolean("controls"), ...resolveBoolean("playsInline"), ...resolveBoolean("loop"), ...resolveBoolean("muted"), ...resolveBoolean("playsInline"), ...resolveBoolean("disablePictureInPicture"), ...resolveBoolean("disableRemotePlayback"), ...resolveString("controlsList"), ...resolveString("crossOrigin"), ...resolveString("preload"), onPlay: () => {
69
+ publish(ACTIVE_SLIDE_PLAYING);
70
+ }, onEnded: () => {
71
+ publish(ACTIVE_SLIDE_COMPLETE);
72
+ } }, sources.map(({ src, type }, index) => (React.createElement("source", { key: index, src: src, type: type })))))))));
31
73
  };
32
74
  export const Video = ({ augment }) => {
33
- augment(({ render: { slide: renderSlide, ...restRender }, ...restProps }) => ({
75
+ augment(({ render: { slide: renderSlide, ...restRender }, video: originalVideo, ...restProps }) => ({
34
76
  render: {
35
77
  slide: (slide, offset, rect) => {
36
78
  if ("type" in slide && slide.type === "video") {
37
- return React.createElement(VideoSlide, { slide: slide });
79
+ return React.createElement(VideoSlide, { slide: slide, offset: offset });
38
80
  }
39
81
  return renderSlide === null || renderSlide === void 0 ? void 0 : renderSlide(slide, offset, rect);
40
82
  },
41
83
  ...restRender,
42
84
  },
85
+ video: {
86
+ ...defaultVideoProps,
87
+ ...originalVideo,
88
+ },
43
89
  ...restProps,
44
90
  }));
45
91
  };
@@ -1,4 +1,5 @@
1
1
  export * from "./Captions.js";
2
2
  export * from "./Fullscreen.js";
3
3
  export * from "./Inline.js";
4
+ export * from "./Slideshow.js";
4
5
  export * from "./Video.js";
@@ -1,4 +1,5 @@
1
1
  export * from "./Captions.js";
2
2
  export * from "./Fullscreen.js";
3
3
  export * from "./Inline.js";
4
+ export * from "./Slideshow.js";
4
5
  export * from "./Video.js";
package/dist/styles.css CHANGED
@@ -14,7 +14,7 @@
14
14
  -moz-user-select: none;
15
15
  -ms-user-select: none;
16
16
  user-select: none;
17
- touch-action: none;
17
+ touch-action: pan-y;
18
18
  }
19
19
  .yarl__container {
20
20
  width: 100%;
@@ -41,15 +41,18 @@
41
41
  overflow: hidden;
42
42
  inset: 0;
43
43
  padding: var(--yarl__carousel_padding, 16px);
44
- -webkit-transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%))), 0, 0);
45
- transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%))), 0, 0);
44
+ -webkit-transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%)) * var(--yarl__direction, 1)), 0, 0);
45
+ transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%)) * var(--yarl__direction, 1)), 0, 0);
46
46
  transition: -webkit-transform var(--yarl__swipe_animation_duration, 500ms) ease-out;
47
47
  transition: transform var(--yarl__swipe_animation_duration, 500ms) ease-out;
48
48
  transition: transform var(--yarl__swipe_animation_duration, 500ms) ease-out, -webkit-transform var(--yarl__swipe_animation_duration, 500ms) ease-out;
49
49
  }
50
+ [dir=rtl] .yarl__slide {
51
+ --yarl__direction: -1;
52
+ }
50
53
  .yarl__container_swipe .yarl__slide {
51
- -webkit-transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%))), 0, 0) translate3d(var(--yarl__swipe_offset, 0px), 0, 0);
52
- transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%))), 0, 0) translate3d(var(--yarl__swipe_offset, 0px), 0, 0);
54
+ -webkit-transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%)) * var(--yarl__direction, 1)), 0, 0) translate3d(var(--yarl__swipe_offset, 0px), 0, 0);
55
+ transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%)) * var(--yarl__direction, 1)), 0, 0) translate3d(var(--yarl__swipe_offset, 0px), 0, 0);
53
56
  transition: unset;
54
57
  }
55
58
  .yarl__slide_image {
@@ -62,6 +65,12 @@
62
65
  user-select: none;
63
66
  -webkit-user-select: none;
64
67
  -webkit-touch-callout: none;
68
+ -webkit-transform: translate3d(0, 0, 0);
69
+ transform: translate3d(0, 0, 0);
70
+ }
71
+ .yarl__slide_image_cover {
72
+ -o-object-fit: cover;
73
+ object-fit: cover;
65
74
  }
66
75
  .yarl__slide_image_loading {
67
76
  opacity: 0;
@@ -137,6 +146,9 @@
137
146
  padding: 8px;
138
147
  gap: 8px;
139
148
  }
149
+ [dir=rtl] .yarl__toolbar {
150
+ inset: 0 auto auto 0;
151
+ }
140
152
  .yarl__icon {
141
153
  width: 32px;
142
154
  height: 32px;
@@ -185,9 +197,21 @@
185
197
  .yarl__navigation_prev {
186
198
  left: 0;
187
199
  }
200
+ [dir=rtl] .yarl__navigation_prev {
201
+ left: unset;
202
+ right: 0;
203
+ -webkit-transform: translateY(-50%) rotate(180deg);
204
+ transform: translateY(-50%) rotate(180deg);
205
+ }
188
206
  .yarl__navigation_next {
189
207
  right: 0;
190
208
  }
209
+ [dir=rtl] .yarl__navigation_next {
210
+ left: 0;
211
+ right: unset;
212
+ -webkit-transform: translateY(-50%) rotate(180deg);
213
+ transform: translateY(-50%) rotate(180deg);
214
+ }
191
215
  .yarl__no_scroll {
192
216
  height: 100%;
193
217
  overflow: hidden;
@@ -195,6 +219,10 @@
195
219
  .yarl__pad_scrollbar {
196
220
  padding-right: var(--yarl__scrollbar_padding, 17px);
197
221
  }
222
+ [dir=rtl] .yarl__pad_scrollbar {
223
+ padding-right: unset;
224
+ padding-left: var(--yarl__scrollbar_padding, 17px);
225
+ }
198
226
 
199
227
  @-webkit-keyframes yarl__delayed_fadein {
200
228
  0% {
package/dist/types.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
- import PropTypes from "prop-types";
3
2
  import { ContainerRect } from "./core/hooks/useContainerRect.js";
3
+ /** Image fit setting */
4
+ export declare type ImageFit = "contain" | "cover";
4
5
  /** Image slide properties */
5
6
  export interface SlideImage {
6
7
  /** image URL */
@@ -9,6 +10,8 @@ export interface SlideImage {
9
10
  alt?: string;
10
11
  /** image aspect ratio */
11
12
  aspectRatio?: number;
13
+ /** `object-fit` setting */
14
+ imageFit?: ImageFit;
12
15
  /** alternative images to be passed to the 'srcSet' */
13
16
  srcSet?: {
14
17
  /** image URL */
@@ -34,6 +37,8 @@ export interface CarouselSettings {
34
37
  padding: string | number;
35
38
  /** spacing between slides (e.g., "100px", "50%" or 0) */
36
39
  spacing: string | number;
40
+ /** `object-fit` setting for image slides */
41
+ imageFit: ImageFit;
37
42
  }
38
43
  /** Animation settings */
39
44
  export interface AnimationSettings {
@@ -44,7 +49,7 @@ export interface AnimationSettings {
44
49
  }
45
50
  /** Controller settings */
46
51
  export interface ControllerSettings {
47
- /** if true, the lightbox captures focus when it opens v */
52
+ /** if true, the lightbox captures focus when it opens */
48
53
  focus: boolean;
49
54
  }
50
55
  /** Custom render functions. */
@@ -123,61 +128,6 @@ export interface LightboxProps {
123
128
  /** lifecycle callbacks */
124
129
  on: Callbacks;
125
130
  }
126
- export declare const ImageSlidePropTypes: PropTypes.Requireable<PropTypes.InferProps<{
127
- src: PropTypes.Requireable<string>;
128
- alt: PropTypes.Requireable<string>;
129
- aspectRatio: PropTypes.Requireable<number>;
130
- srcSet: PropTypes.Requireable<PropTypes.InferProps<{
131
- src: PropTypes.Validator<string>;
132
- width: PropTypes.Validator<number>;
133
- }>[]>;
134
- }>>;
135
- export declare const SlideTypesPropTypes: PropTypes.Validator<any>[];
136
- export declare const LightboxPropTypes: {
137
- open: PropTypes.Validator<boolean>;
138
- close: PropTypes.Validator<(...args: any[]) => any>;
139
- index: PropTypes.Validator<number>;
140
- slides: PropTypes.Validator<any[]>;
141
- render: PropTypes.Validator<PropTypes.InferProps<{
142
- slide: PropTypes.Requireable<(...args: any[]) => any>;
143
- slideHeader: PropTypes.Requireable<(...args: any[]) => any>;
144
- slideFooter: PropTypes.Requireable<(...args: any[]) => any>;
145
- slideContainer: PropTypes.Requireable<(...args: any[]) => any>;
146
- iconPrev: PropTypes.Requireable<(...args: any[]) => any>;
147
- iconNext: PropTypes.Requireable<(...args: any[]) => any>;
148
- iconClose: PropTypes.Requireable<(...args: any[]) => any>;
149
- iconLoading: PropTypes.Requireable<(...args: any[]) => any>;
150
- iconError: PropTypes.Requireable<(...args: any[]) => any>;
151
- buttonPrev: PropTypes.Requireable<(...args: any[]) => any>;
152
- buttonNext: PropTypes.Requireable<(...args: any[]) => any>;
153
- buttonClose: PropTypes.Requireable<(...args: any[]) => any>;
154
- }>>;
155
- plugins: PropTypes.Validator<((...args: any[]) => any)[]>;
156
- toolbar: PropTypes.Validator<PropTypes.InferProps<{
157
- buttons: PropTypes.Validator<(string | number | boolean | PropTypes.ReactElementLike | PropTypes.ReactNodeArray | null | undefined)[]>;
158
- }>>;
159
- labels: PropTypes.Validator<PropTypes.InferProps<{}>>;
160
- carousel: PropTypes.Validator<PropTypes.InferProps<{
161
- finite: PropTypes.Validator<boolean>;
162
- preload: PropTypes.Validator<number>;
163
- padding: PropTypes.Validator<string | number>;
164
- spacing: PropTypes.Validator<string | number>;
165
- }>>;
166
- animation: PropTypes.Validator<PropTypes.InferProps<{
167
- fade: PropTypes.Validator<number>;
168
- swipe: PropTypes.Validator<number>;
169
- }>>;
170
- controller: PropTypes.Validator<PropTypes.InferProps<{
171
- focus: PropTypes.Validator<boolean>;
172
- }>>;
173
- on: PropTypes.Validator<PropTypes.InferProps<{
174
- view: PropTypes.Requireable<(...args: any[]) => any>;
175
- entering: PropTypes.Requireable<(...args: any[]) => any>;
176
- entered: PropTypes.Requireable<(...args: any[]) => any>;
177
- exiting: PropTypes.Requireable<(...args: any[]) => any>;
178
- exited: PropTypes.Requireable<(...args: any[]) => any>;
179
- }>>;
180
- };
181
131
  export declare const LightboxDefaultProps: {
182
132
  open: boolean;
183
133
  close: () => void;
@@ -238,3 +188,9 @@ export declare type PluginMethods = {
238
188
  };
239
189
  /** Lightbox plugin */
240
190
  export declare type Plugin = ({ addParent, addChild, addSibling, replace, remove, augment }: PluginMethods) => void;
191
+ /** Deep partial utility type */
192
+ export declare type DeepPartial<T, K extends keyof T> = Omit<T, K> & {
193
+ [P in keyof Pick<T, K>]?: Partial<Pick<T, K>[P]>;
194
+ };
195
+ /** Lightbox external props */
196
+ export declare type LightboxExternalProps = DeepPartial<Partial<LightboxProps>, "carousel" | "animation" | "render" | "toolbar" | "controller" | "on">;
package/dist/types.js CHANGED
@@ -1,59 +1,3 @@
1
- import PropTypes from "prop-types";
2
- export const ImageSlidePropTypes = PropTypes.shape({
3
- src: PropTypes.string,
4
- alt: PropTypes.string,
5
- aspectRatio: PropTypes.number,
6
- srcSet: PropTypes.arrayOf(PropTypes.shape({
7
- src: PropTypes.string.isRequired,
8
- width: PropTypes.number.isRequired,
9
- }).isRequired),
10
- });
11
- export const SlideTypesPropTypes = [ImageSlidePropTypes];
12
- export const LightboxPropTypes = {
13
- open: PropTypes.bool.isRequired,
14
- close: PropTypes.func.isRequired,
15
- index: PropTypes.number.isRequired,
16
- slides: PropTypes.arrayOf(PropTypes.oneOfType(SlideTypesPropTypes).isRequired).isRequired,
17
- render: PropTypes.shape({
18
- slide: PropTypes.func,
19
- slideHeader: PropTypes.func,
20
- slideFooter: PropTypes.func,
21
- slideContainer: PropTypes.func,
22
- iconPrev: PropTypes.func,
23
- iconNext: PropTypes.func,
24
- iconClose: PropTypes.func,
25
- iconLoading: PropTypes.func,
26
- iconError: PropTypes.func,
27
- buttonPrev: PropTypes.func,
28
- buttonNext: PropTypes.func,
29
- buttonClose: PropTypes.func,
30
- }).isRequired,
31
- plugins: PropTypes.arrayOf(PropTypes.func.isRequired).isRequired,
32
- toolbar: PropTypes.shape({
33
- buttons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.oneOf(["close"]), PropTypes.node])).isRequired,
34
- }).isRequired,
35
- labels: PropTypes.shape({}).isRequired,
36
- carousel: PropTypes.shape({
37
- finite: PropTypes.bool.isRequired,
38
- preload: PropTypes.number.isRequired,
39
- padding: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
40
- spacing: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
41
- }).isRequired,
42
- animation: PropTypes.shape({
43
- fade: PropTypes.number.isRequired,
44
- swipe: PropTypes.number.isRequired,
45
- }).isRequired,
46
- controller: PropTypes.shape({
47
- focus: PropTypes.bool.isRequired,
48
- }).isRequired,
49
- on: PropTypes.shape({
50
- view: PropTypes.func,
51
- entering: PropTypes.func,
52
- entered: PropTypes.func,
53
- exiting: PropTypes.func,
54
- exited: PropTypes.func,
55
- }).isRequired,
56
- };
57
1
  export const LightboxDefaultProps = {
58
2
  open: false,
59
3
  close: () => { },
@@ -72,6 +16,7 @@ export const LightboxDefaultProps = {
72
16
  preload: 2,
73
17
  padding: "16px",
74
18
  spacing: "30%",
19
+ imageFit: "contain",
75
20
  },
76
21
  controller: {
77
22
  focus: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yet-another-react-lightbox",
3
- "version": "1.4.1",
3
+ "version": "1.7.0",
4
4
  "description": "Modern React lightbox component",
5
5
  "author": "Igor Danchenko",
6
6
  "license": "MIT",
@@ -14,6 +14,7 @@
14
14
  "./plugins/captions.css": "./dist/plugins/captions.css",
15
15
  "./plugins/fullscreen": "./dist/plugins/Fullscreen.js",
16
16
  "./plugins/inline": "./dist/plugins/Inline.js",
17
+ "./plugins/slideshow": "./dist/plugins/Slideshow.js",
17
18
  "./plugins/video": "./dist/plugins/Video.js",
18
19
  "./styles.css": "./dist/styles.css"
19
20
  },
@@ -38,6 +39,9 @@
38
39
  "plugins/inline": [
39
40
  "dist/plugins/Inline.d.ts"
40
41
  ],
42
+ "plugins/slideshow": [
43
+ "dist/plugins/Slideshow.d.ts"
44
+ ],
41
45
  "plugins/video": [
42
46
  "dist/plugins/Video.d.ts"
43
47
  ]
@@ -70,9 +74,6 @@
70
74
  "lint": "eslint .",
71
75
  "test": "jest"
72
76
  },
73
- "dependencies": {
74
- "prop-types": "^15.5.7"
75
- },
76
77
  "peerDependencies": {
77
78
  "react": ">=16.8.0",
78
79
  "react-dom": ">=16.8.0"
@@ -88,8 +89,8 @@
88
89
  "@types/jest": "^28.1.1",
89
90
  "@types/react": "^18.0.12",
90
91
  "@types/react-dom": "^18.0.5",
91
- "@typescript-eslint/eslint-plugin": "^5.27.1",
92
- "@typescript-eslint/parser": "^5.27.1",
92
+ "@typescript-eslint/eslint-plugin": "^5.28.0",
93
+ "@typescript-eslint/parser": "^5.28.0",
93
94
  "autoprefixer": "^10.4.7",
94
95
  "eslint": "^8.17.0",
95
96
  "eslint-config-airbnb": "^19.0.4",
@@ -99,7 +100,7 @@
99
100
  "eslint-plugin-jsx-a11y": "^6.5.1",
100
101
  "eslint-plugin-prettier": "^4.0.0",
101
102
  "eslint-plugin-react": "^7.30.0",
102
- "eslint-plugin-react-hooks": "^4.5.0",
103
+ "eslint-plugin-react-hooks": "^4.6.0",
103
104
  "husky": "^8.0.1",
104
105
  "jest": "^28.1.1",
105
106
  "jest-environment-jsdom": "^28.1.1",
@@ -107,12 +108,12 @@
107
108
  "npm-run-all": "^4.1.5",
108
109
  "postcss": "^8.4.14",
109
110
  "postcss-cli": "^9.1.0",
110
- "prettier": "^2.6.2",
111
- "react": "^18.1.0",
112
- "react-dom": "^18.1.0",
111
+ "prettier": "^2.7.0",
112
+ "react": "^18.2.0",
113
+ "react-dom": "^18.2.0",
113
114
  "rimraf": "^3.0.2",
114
115
  "sass": "^1.52.3",
115
- "ts-jest": "^28.0.4",
116
+ "ts-jest": "^28.0.5",
116
117
  "typescript": "^4.7.3"
117
118
  },
118
119
  "keywords": [