yet-another-react-lightbox 1.11.1 → 1.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,4 +4,4 @@ export declare type IconButtonProps = Omit<React.DetailedHTMLProps<React.ButtonH
4
4
  icon: React.ElementType;
5
5
  renderIcon?: () => React.ReactNode;
6
6
  };
7
- export declare const IconButton: React.ForwardRefExoticComponent<Pick<IconButtonProps, "value" | "children" | "onPointerDown" | "onPointerMove" | "onPointerUp" | "onPointerLeave" | "onPointerCancel" | "onTouchStart" | "onTouchMove" | "onTouchEnd" | "onTouchCancel" | "onKeyDown" | "onKeyUp" | "onWheel" | "key" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "slot" | "spellCheck" | "style" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancelCapture" | "onTouchEndCapture" | "onTouchMoveCapture" | "onTouchStartCapture" | "onPointerDownCapture" | "onPointerMoveCapture" | "onPointerUpCapture" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "form" | "label" | "autoFocus" | "disabled" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "name" | "icon" | "renderIcon"> & React.RefAttributes<HTMLButtonElement>>;
7
+ export declare const IconButton: React.ForwardRefExoticComponent<Pick<IconButtonProps, "icon" | "className" | "value" | "children" | "onPointerDown" | "onPointerMove" | "onPointerUp" | "onPointerLeave" | "onPointerCancel" | "onTouchStart" | "onTouchMove" | "onTouchEnd" | "onTouchCancel" | "onKeyDown" | "onKeyUp" | "onWheel" | "key" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "slot" | "spellCheck" | "style" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancelCapture" | "onTouchEndCapture" | "onTouchMoveCapture" | "onTouchStartCapture" | "onPointerDownCapture" | "onPointerMoveCapture" | "onPointerUpCapture" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "form" | "label" | "disabled" | "autoFocus" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "name" | "renderIcon"> & React.RefAttributes<HTMLButtonElement>>;
@@ -1,4 +1,8 @@
1
1
  import * as React from "react";
2
2
  import { clsx, cssClass } from "../utils.js";
3
- export const IconButton = React.forwardRef(({ label, className, icon: Icon, renderIcon, onClick, ...rest }, ref) => (React.createElement("button", { ref: ref, type: "button", "aria-label": label, className: clsx(cssClass("button"), className), onClick: onClick, ...rest }, renderIcon ? renderIcon() : React.createElement(Icon, { className: cssClass("icon") }))));
3
+ import { useController } from "../modules/Controller.js";
4
+ export const IconButton = React.forwardRef(({ label, className, icon: Icon, renderIcon, onClick, style, ...rest }, ref) => {
5
+ const { latestProps: { current: { styles }, }, } = useController();
6
+ return (React.createElement("button", { ref: ref, type: "button", "aria-label": label, className: clsx(cssClass("button"), className), onClick: onClick, style: { ...style, ...styles.button }, ...rest }, renderIcon ? renderIcon() : React.createElement(Icon, { className: cssClass("icon"), style: styles.icon })));
7
+ });
4
8
  IconButton.displayName = "IconButton";
@@ -44,7 +44,12 @@ export const ImageSlide = ({ slide: image, offset, render, rect, imageFit, onCli
44
44
  const nonInfinite = (value, fallback) => (Number.isFinite(value) ? value : fallback);
45
45
  const maxWidth = nonInfinite(Math.max(...((_b = (_a = image.srcSet) === null || _a === void 0 ? void 0 : _a.map((x) => x.width)) !== null && _b !== void 0 ? _b : []).concat(image.width ? [image.width] : [])), ((_c = imageRef.current) === null || _c === void 0 ? void 0 : _c.naturalWidth) || 0);
46
46
  const maxHeight = nonInfinite(Math.max(...((_e = (_d = image.srcSet) === null || _d === void 0 ? void 0 : _d.map((x) => x.height).filter((x) => Boolean(x))) !== null && _e !== void 0 ? _e : []).concat(image.height ? [image.height] : [])), (image.aspectRatio && maxWidth ? maxWidth / image.aspectRatio : (_f = imageRef.current) === null || _f === void 0 ? void 0 : _f.naturalHeight) || 0);
47
- const style = maxWidth && maxHeight ? { maxWidth, maxHeight } : undefined;
47
+ const style = maxWidth && maxHeight
48
+ ? {
49
+ maxWidth: `min(${maxWidth}px, 100%)`,
50
+ maxHeight: `min(${maxHeight}px, 100%)`,
51
+ }
52
+ : undefined;
48
53
  const srcSet = (_g = image.srcSet) === null || _g === void 0 ? void 0 : _g.sort((a, b) => a.width - b.width).map((item) => `${item.src} ${item.width}w`).join(", ");
49
54
  const estimateActualWidth = () => {
50
55
  if (rect && !cover) {
@@ -61,7 +66,7 @@ export const ImageSlide = ({ slide: image, offset, render, rect, imageFit, onCli
61
66
  ? `${Math.ceil((Math.min(estimateActualWidth(), rect.width) / window.innerWidth) * 100)}vw`
62
67
  : undefined;
63
68
  return (React.createElement(React.Fragment, null,
64
- React.createElement("img", { ref: setImageRef, onLoad: onLoad, onError: onError, onClick: onClick, className: clsx(cssClass("slide_image"), cssClass("fullsize"), cover && cssClass("slide_image_cover"), status !== SLIDE_STATUS_COMPLETE && cssClass("slide_image_loading")), draggable: false, alt: image.alt, style: style, sizes: sizes, srcSet: srcSet, src: image.src }),
69
+ React.createElement("img", { ref: setImageRef, onLoad: onLoad, onError: onError, onClick: onClick, className: clsx(cssClass("slide_image"), cover && cssClass("slide_image_cover"), status !== SLIDE_STATUS_COMPLETE && cssClass("slide_image_loading")), draggable: false, alt: image.alt, style: style, sizes: sizes, srcSet: srcSet, src: image.src }),
65
70
  status !== SLIDE_STATUS_COMPLETE && (React.createElement("div", { className: cssClass("slide_placeholder") },
66
71
  status === SLIDE_STATUS_LOADING &&
67
72
  ((render === null || render === void 0 ? void 0 : render.iconLoading) ? (render.iconLoading()) : (React.createElement(LoadingIcon, { className: clsx(cssClass("icon"), cssClass("slide_loading")) }))),
@@ -8,3 +8,4 @@ export declare const ACTIVE_SLIDE_LOADING: string;
8
8
  export declare const ACTIVE_SLIDE_PLAYING: string;
9
9
  export declare const ACTIVE_SLIDE_ERROR: string;
10
10
  export declare const ACTIVE_SLIDE_COMPLETE: string;
11
+ export declare const YARL_EVENT_BACKDROP_CLICK = "backdrop_click";
@@ -7,3 +7,4 @@ export const ACTIVE_SLIDE_LOADING = activeSlideStatus(SLIDE_STATUS_LOADING);
7
7
  export const ACTIVE_SLIDE_PLAYING = activeSlideStatus(SLIDE_STATUS_PLAYING);
8
8
  export const ACTIVE_SLIDE_ERROR = activeSlideStatus(SLIDE_STATUS_ERROR);
9
9
  export const ACTIVE_SLIDE_COMPLETE = activeSlideStatus(SLIDE_STATUS_COMPLETE);
10
+ export const YARL_EVENT_BACKDROP_CLICK = "backdrop_click";
@@ -1,12 +1,15 @@
1
1
  import * as React from "react";
2
+ import { YARL_EVENT_BACKDROP_CLICK } from "../consts.js";
2
3
  import { LightboxDefaultProps } from "../../types.js";
3
4
  import { useContainerRect } from "../hooks/index.js";
4
5
  import { createModule } from "../config.js";
5
6
  import { clsx, cssClass, cssVar } from "../utils.js";
6
7
  import { ImageSlide } from "../components/index.js";
7
8
  import { useController } from "./Controller.js";
9
+ import { useEvents } from "../contexts/Events.js";
8
10
  const CarouselSlide = ({ slide, offset }) => {
9
- const { setContainerRef, containerRect } = useContainerRect();
11
+ const { setContainerRef, containerRect, containerRef } = useContainerRect();
12
+ const { publish } = useEvents();
10
13
  const { latestProps, currentIndex } = useController();
11
14
  const { render } = latestProps.current;
12
15
  const renderSlide = (rect) => {
@@ -25,7 +28,18 @@ const CarouselSlide = ({ slide, offset }) => {
25
28
  ((_c = render.slideContainer) !== null && _c !== void 0 ? _c : ((_, x) => x))(slide, rendered), (_d = render.slideFooter) === null || _d === void 0 ? void 0 :
26
29
  _d.call(render, slide))) : null;
27
30
  };
28
- return (React.createElement("div", { ref: setContainerRef, className: clsx(cssClass("slide"), cssClass("flex_center")), style: { [cssVar("slide_offset")]: offset } }, containerRect && renderSlide(containerRect)));
31
+ const handleBackdropClick = (event) => {
32
+ const container = containerRef.current;
33
+ const target = event.target instanceof HTMLElement ? event.target : undefined;
34
+ if (target &&
35
+ container &&
36
+ (target === container ||
37
+ (Array.from(container.children).find((x) => x === target) &&
38
+ target.classList.contains(cssClass("fullsize"))))) {
39
+ publish(YARL_EVENT_BACKDROP_CLICK);
40
+ }
41
+ };
42
+ return (React.createElement("div", { ref: setContainerRef, className: clsx(cssClass("slide"), cssClass("flex_center")), style: { [cssVar("slide_offset")]: offset }, onClick: handleBackdropClick }, containerRect && renderSlide(containerRect)));
29
43
  };
30
44
  export const Carousel = ({ slides, carousel: { finite, preload, padding, spacing } }) => {
31
45
  const { currentIndex, globalIndex } = useController();
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import { YARL_EVENT_BACKDROP_CLICK } from "../consts.js";
2
3
  import { LightboxDefaultProps } from "../../types.js";
3
4
  import { cleanup, clsx, cssClass, cssVar, makeUseContext } from "../utils.js";
4
5
  import { createModule } from "../config.js";
@@ -158,6 +159,9 @@ export const Controller = ({ children, ...props }) => {
158
159
  publish("close");
159
160
  }
160
161
  }), [subscribeSensors, publish]);
162
+ React.useEffect(() => props.controller.closeOnBackdropClick
163
+ ? subscribe(YARL_EVENT_BACKDROP_CLICK, () => publish("close"))
164
+ : () => { }, [props.controller.closeOnBackdropClick, publish, subscribe]);
161
165
  const clearPointer = React.useCallback((event) => {
162
166
  const { current } = refs;
163
167
  if (current.activePointer === event.pointerId) {
@@ -298,6 +302,7 @@ export const Controller = ({ children, ...props }) => {
298
302
  [cssVar("controller_touch_action")]: props.controller.touchAction,
299
303
  }
300
304
  : null),
305
+ ...props.styles.container,
301
306
  }, ...(props.controller.aria ? { role: "presentation", "aria-live": "polite" } : null), tabIndex: -1, ...registerSensors }, containerRect && (React.createElement(ControllerContext.Provider, { value: context }, children))));
302
307
  };
303
308
  export const ControllerModule = createModule("controller", Controller);
@@ -27,9 +27,7 @@ export const Portal = ({ children, ...props }) => {
27
27
  const { subscribe } = useEvents();
28
28
  React.useEffect(() => {
29
29
  setMounted(true);
30
- return () => {
31
- setMounted(false);
32
- };
30
+ return () => setMounted(false);
33
31
  }, []);
34
32
  React.useEffect(() => subscribe("close", () => {
35
33
  var _a, _b;
@@ -66,13 +64,14 @@ export const Portal = ({ children, ...props }) => {
66
64
  }
67
65
  }, [setTimeout, latestProps, latestAnimationDuration]);
68
66
  return mounted
69
- ? ReactDOM.createPortal(React.createElement("div", { ref: handlePortalRef, className: clsx(cssClass("portal"), cssClass("no_scroll_padding"), visible && cssClass("portal_open")), role: "presentation", "aria-live": "polite", ...(props.animation.fade !== LightboxDefaultProps.animation.fade
70
- ? {
71
- style: {
67
+ ? ReactDOM.createPortal(React.createElement("div", { ref: handlePortalRef, className: clsx(props.className, cssClass("root"), cssClass("portal"), cssClass("no_scroll_padding"), visible && cssClass("portal_open")), role: "presentation", "aria-live": "polite", style: {
68
+ ...(props.animation.fade !== LightboxDefaultProps.animation.fade
69
+ ? {
72
70
  [cssVar("fade_animation_duration")]: `${Math.round(props.animation.fade)}ms`,
73
- },
74
- }
75
- : null) }, children), document.body)
71
+ }
72
+ : null),
73
+ ...props.styles.root,
74
+ } }, children), document.body)
76
75
  : null;
77
76
  };
78
77
  export const PortalModule = createModule("portal", Portal);
@@ -16,6 +16,16 @@ declare module "../types.js" {
16
16
  descriptionMaxLines?: number;
17
17
  };
18
18
  }
19
+ interface SlotType {
20
+ /** captions title customization slot */
21
+ captionsTitle: "captionsTitle";
22
+ /** captions title container customization slot */
23
+ captionsTitleContainer: "captionsTitleContainer";
24
+ /** captions description customization slot */
25
+ captionsDescription: "captionsDescription";
26
+ /** captions description container customization slot */
27
+ captionsDescriptionContainer: "captionsDescriptionContainer";
28
+ }
19
29
  }
20
30
  /** Captions plugin context holder */
21
31
  export declare const CaptionsComponent: Component;
@@ -1,28 +1,31 @@
1
1
  import * as React from "react";
2
- import { cssClass, cssVar, isDefined, makeUseContext } from "../core/utils.js";
2
+ import { clsx, cssClass, cssVar, isDefined, makeUseContext } from "../core/utils.js";
3
3
  import { useEvents } from "../core/contexts/Events.js";
4
4
  import { createModule } from "../core/index.js";
5
5
  const defaultTextAlign = "start";
6
6
  const defaultMaxLines = 3;
7
- const cls = (className) => cssClass(`slide_${className}`);
7
+ const cssPrefix = (className) => cssClass(`slide_${className}`);
8
8
  const hasTitle = (slide) => "title" in slide ? typeof slide.title === "string" : false;
9
9
  const hasDescription = (slide) => "description" in slide ? typeof slide.description === "string" : false;
10
10
  const CaptionsContext = React.createContext(null);
11
11
  const useCaptions = makeUseContext("useCaptions", "CaptionsContext", CaptionsContext);
12
- const Title = ({ title }) => {
12
+ const Title = ({ title, styles }) => {
13
13
  const { toolbarWidth } = useCaptions();
14
- return (React.createElement("div", { className: cls(`title_container`) },
15
- React.createElement("div", { className: cls("title"), ...(toolbarWidth ? { style: { [cssVar("toolbar_width")]: `${toolbarWidth}px` } } : null) }, title)));
14
+ return (React.createElement("div", { style: styles.captionsTitleContainer, className: clsx(cssPrefix("captions_container"), cssPrefix("title_container")) },
15
+ React.createElement("div", { style: styles.captionsTitle, className: cssPrefix("title"), ...(toolbarWidth ? { style: { [cssVar("toolbar_width")]: `${toolbarWidth}px` } } : null) }, title)));
16
16
  };
17
- const Description = ({ description, align, maxLines }) => (React.createElement("div", { className: cls("description_container") },
18
- React.createElement("div", { className: cls("description"), ...(align !== defaultTextAlign || maxLines !== defaultMaxLines
19
- ? {
20
- style: {
21
- [cssVar("slide_description_text_align")]: align,
22
- [cssVar("slide_description_max_lines")]: maxLines,
23
- },
24
- }
25
- : null) }, description.split("\n").flatMap((line, index) => [...(index > 0 ? [React.createElement("br", { key: index })] : []), line]))));
17
+ const Description = ({ description, align, maxLines, styles }) => (React.createElement("div", { style: styles.captionsDescriptionContainer, className: clsx(cssPrefix("captions_container"), cssPrefix("description_container")) },
18
+ React.createElement("div", { className: cssPrefix("description"), style: {
19
+ ...(align !== defaultTextAlign || maxLines !== defaultMaxLines
20
+ ? {
21
+ style: {
22
+ [cssVar("slide_description_text_align")]: align,
23
+ [cssVar("slide_description_max_lines")]: maxLines,
24
+ },
25
+ }
26
+ : null),
27
+ ...styles.captionsDescription,
28
+ } }, description.split("\n").flatMap((line, index) => [...(index > 0 ? [React.createElement("br", { key: index })] : []), line]))));
26
29
  export const CaptionsComponent = ({ children }) => {
27
30
  const { subscribe } = useEvents();
28
31
  const [toolbarWidth, setToolbarWidth] = React.useState();
@@ -37,17 +40,18 @@ export const CaptionsComponent = ({ children }) => {
37
40
  export const CaptionsModule = createModule("captions", CaptionsComponent);
38
41
  export const Captions = ({ augment, addParent }) => {
39
42
  addParent("controller", CaptionsModule);
40
- augment(({ render: { slideFooter: renderFooter, ...restRender }, captions, ...restProps }) => ({
43
+ augment(({ render: { slideFooter: renderFooter, ...restRender }, captions, styles, ...restProps }) => ({
41
44
  render: {
42
45
  slideFooter: (slide) => {
43
46
  var _a, _b;
44
47
  return (React.createElement(React.Fragment, null, renderFooter === null || renderFooter === void 0 ? void 0 :
45
48
  renderFooter(slide),
46
- hasTitle(slide) && React.createElement(Title, { title: slide.title }),
47
- hasDescription(slide) && (React.createElement(Description, { description: slide.description, align: (_a = captions === null || captions === void 0 ? void 0 : captions.descriptionTextAlign) !== null && _a !== void 0 ? _a : defaultTextAlign, maxLines: (_b = captions === null || captions === void 0 ? void 0 : captions.descriptionMaxLines) !== null && _b !== void 0 ? _b : defaultMaxLines }))));
49
+ hasTitle(slide) && React.createElement(Title, { styles: styles, title: slide.title }),
50
+ hasDescription(slide) && (React.createElement(Description, { styles: styles, description: slide.description, align: (_a = captions === null || captions === void 0 ? void 0 : captions.descriptionTextAlign) !== null && _a !== void 0 ? _a : defaultTextAlign, maxLines: (_b = captions === null || captions === void 0 ? void 0 : captions.descriptionMaxLines) !== null && _b !== void 0 ? _b : defaultMaxLines }))));
48
51
  },
49
52
  ...restRender,
50
53
  },
54
+ styles,
51
55
  ...restProps,
52
56
  }));
53
57
  };
@@ -1,17 +1,18 @@
1
1
  import * as React from "react";
2
- import { createModule } from "../core/index.js";
3
- export const InlineContainer = ({ inline, children }) => React.createElement("div", { ...inline }, children);
2
+ import { clsx, createModule, cssClass } from "../core/index.js";
3
+ export const InlineContainer = ({ inline: { className, ...rest } = {}, children }) => (React.createElement("div", { className: clsx(cssClass("root"), className), ...rest }, children));
4
4
  export const InlineModule = createModule("inline", InlineContainer);
5
5
  export const Inline = ({ augment, replace, remove }) => {
6
- augment(({ toolbar: { buttons, ...restToolbar }, open, close, controller: { focus, aria, touchAction, ...restController }, ...restProps }) => ({
6
+ augment(({ toolbar: { buttons, ...restToolbar }, open, close, controller: { focus, aria, touchAction, ...restController }, className, ...restProps }) => ({
7
7
  open: true,
8
8
  close: () => { },
9
9
  toolbar: {
10
10
  buttons: buttons.filter((button) => button !== "close"),
11
11
  ...restToolbar,
12
12
  },
13
- inline: { style: { width: "100%", height: "100%" } },
13
+ inline: { style: { width: "100%", height: "100%" }, className },
14
14
  controller: { focus: false, aria: true, touchAction: "pan-y", ...restController },
15
+ className,
15
16
  ...restProps,
16
17
  }));
17
18
  remove("no-scroll");
@@ -32,9 +32,17 @@ declare module "../types.js" {
32
32
  imageFit: ImageFit;
33
33
  }) => React.ReactNode;
34
34
  }
35
+ interface SlotType {
36
+ /** thumbnail customization slot */
37
+ thumbnail: "thumbnail";
38
+ /** thumbnails track customization slot */
39
+ thumbnailsTrack: "thumbnailsTrack";
40
+ /** thumbnails container customization slot */
41
+ thumbnailsContainer: "thumbnailsContainer";
42
+ }
35
43
  }
36
44
  declare type ThumbnailsInternal = DeepNonNullable<LightboxProps["thumbnails"]>;
37
- declare type ThumbnailsTrackProps = Pick<LightboxProps, "slides" | "carousel" | "animation" | "render"> & {
45
+ declare type ThumbnailsTrackProps = Pick<LightboxProps, "slides" | "carousel" | "animation" | "render" | "styles"> & {
38
46
  container: React.RefObject<HTMLDivElement>;
39
47
  thumbnails: ThumbnailsInternal;
40
48
  startingIndex: number;
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { clsx, createIcon, createModule, cssClass, cssVar, ImageSlide, useLayoutEffect, useEvents, useLatest, useMotionPreference, useRTL, } from "../core/index.js";
2
+ import { clsx, createIcon, createModule, cssClass, cssVar, ImageSlide, useEvents, useLatest, useLayoutEffect, useMotionPreference, useRTL, } from "../core/index.js";
3
3
  const defaultThumbnailsProps = {
4
4
  position: "bottom",
5
5
  width: 120,
@@ -36,7 +36,7 @@ const renderThumbnail = ({ slide, render, rect, imageFit }) => {
36
36
  }
37
37
  return React.createElement(UnknownThumbnailIcon, { className: thumbnailIconClass });
38
38
  };
39
- const Thumbnail = ({ rect, slide, onClick, active, fadeIn, fadeOut, placeholder, render, imageFit, }) => (React.createElement("button", { type: "button", className: clsx(cssClass(cssThumbnailPrefix()), active && cssClass(cssThumbnailPrefix("active")), fadeIn && cssClass(cssThumbnailPrefix("fadein")), fadeOut && cssClass(cssThumbnailPrefix("fadeout")), placeholder && cssClass(cssThumbnailPrefix("placeholder"))), style: {
39
+ const Thumbnail = ({ rect, slide, onClick, active, fadeIn, fadeOut, placeholder, render, imageFit, style, }) => (React.createElement("button", { type: "button", className: clsx(cssClass("flex_center"), cssClass(cssThumbnailPrefix()), active && cssClass(cssThumbnailPrefix("active")), fadeIn && cssClass(cssThumbnailPrefix("fadein")), fadeOut && cssClass(cssThumbnailPrefix("fadeout")), placeholder && cssClass(cssThumbnailPrefix("placeholder"))), style: {
40
40
  ...(fadeIn
41
41
  ? {
42
42
  [cssVar(cssThumbnailPrefix("fadein_duration"))]: `${fadeIn.duration}ms`,
@@ -49,8 +49,9 @@ const Thumbnail = ({ rect, slide, onClick, active, fadeIn, fadeOut, placeholder,
49
49
  [cssVar(cssThumbnailPrefix("fadeout_delay"))]: `${fadeOut.delay}ms`,
50
50
  }
51
51
  : null),
52
+ ...style,
52
53
  }, onClick: onClick }, slide && renderThumbnail({ slide, render, rect, imageFit })));
53
- export const ThumbnailsTrack = ({ container, startingIndex, slides, carousel, animation, render, thumbnails, thumbnailRect, }) => {
54
+ export const ThumbnailsTrack = ({ container, startingIndex, slides, carousel, animation, render, thumbnails, thumbnailRect, styles, }) => {
54
55
  const track = React.useRef(null);
55
56
  const [state, setState] = React.useState({
56
57
  index: startingIndex,
@@ -187,8 +188,9 @@ export const ThumbnailsTrack = ({ container, startingIndex, slides, carousel, an
187
188
  ? { [cssVar(cssThumbnailPrefix("padding"))]: `${padding}px` }
188
189
  : null),
189
190
  ...(gap !== defaultThumbnailsProps.gap ? { [cssVar(cssThumbnailPrefix("gap"))]: `${gap}px` } : null),
191
+ ...styles.thumbnailsContainer,
190
192
  } },
191
- React.createElement("nav", { ref: track, className: cssClass(cssPrefix("track")) }, items.map(({ slide, index: slideIndex, placeholder }) => {
193
+ React.createElement("nav", { ref: track, style: styles.thumbnailsTrack, className: cssClass(cssPrefix("track")) }, items.map(({ slide, index: slideIndex, placeholder }) => {
192
194
  var _a;
193
195
  const fadeAnimationDuration = ((_a = refs.current.animationOverride) !== null && _a !== void 0 ? _a : animation.swipe) / Math.abs(offset || 1);
194
196
  const fadeIn = (offset > 0 && slideIndex > index + preload - offset && slideIndex <= index + preload) ||
@@ -210,13 +212,13 @@ export const ThumbnailsTrack = ({ container, startingIndex, slides, carousel, an
210
212
  : -offset - (slideIndex - (index + preload))) * fadeAnimationDuration,
211
213
  }
212
214
  : undefined;
213
- return (React.createElement(Thumbnail, { key: slideIndex, rect: thumbnailRect, slide: slide, imageFit: imageFit, render: render, active: slideIndex === index, fadeIn: fadeIn, fadeOut: fadeOut, placeholder: Boolean(placeholder), onClick: handleClick(slideIndex) }));
215
+ return (React.createElement(Thumbnail, { key: slideIndex, rect: thumbnailRect, slide: slide, imageFit: imageFit, render: render, active: slideIndex === index, fadeIn: fadeIn, fadeOut: fadeOut, placeholder: Boolean(placeholder), onClick: handleClick(slideIndex), style: styles.thumbnail }));
214
216
  }))));
215
217
  };
216
- export const ThumbnailsComponent = ({ thumbnails: thumbnailsProps, slides, index, carousel, animation, render, children, }) => {
218
+ export const ThumbnailsComponent = ({ thumbnails: thumbnailsProps, slides, index, carousel, animation, render, styles, children, }) => {
217
219
  const thumbnails = { ...defaultThumbnailsProps, ...thumbnailsProps };
218
220
  const ref = React.useRef(null);
219
- const track = (React.createElement(ThumbnailsTrack, { container: ref, slides: slides, thumbnails: thumbnails, carousel: carousel, animation: animation, render: render, startingIndex: index, thumbnailRect: { width: thumbnails.width, height: thumbnails.height } }));
221
+ const track = (React.createElement(ThumbnailsTrack, { container: ref, slides: slides, thumbnails: thumbnails, carousel: carousel, animation: animation, render: render, startingIndex: index, thumbnailRect: { width: thumbnails.width, height: thumbnails.height }, styles: styles }));
220
222
  return (React.createElement("div", { ref: ref, className: clsx(cssClass(cssPrefix()), cssClass(cssPrefix(`${thumbnails.position}`)), cssClass("fullsize")) },
221
223
  (thumbnails.position === "start" || thumbnails.position === "top") && track,
222
224
  React.createElement("div", { className: cssClass(cssPrefix("wrapper")) }, children),
@@ -1,27 +1,25 @@
1
+ .yarl__slide_captions_container {
2
+ position: absolute;
3
+ left: var(--yarl__slide_captions_container_left, 0);
4
+ right: var(--yarl__slide_captions_container_right, 0);
5
+ padding: var(--yarl__slide_captions_container_padding, 16px);
6
+ background: var(--yarl__slide_captions_container_background, rgba(0, 0, 0, 0.5));
7
+ -webkit-transform: translateZ(0);
8
+ transform: translateZ(0);
9
+ }
1
10
  .yarl__slide_title {
2
- font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
3
- font-size: 1.25rem;
4
- font-weight: 700;
11
+ color: var(--yarl__slide_title_color, #fff);
12
+ font-size: var(--yarl__slide_title_font_size, 125%);
13
+ font-weight: var(--yarl__slide_title_font_weight, bolder);
5
14
  max-width: calc(100% - var(--yarl__toolbar_width, 0px));
6
15
  overflow: hidden;
7
16
  text-overflow: ellipsis;
8
17
  white-space: nowrap;
9
18
  }
10
19
  .yarl__slide_title_container {
11
- position: absolute;
12
- left: 0;
13
- right: 0;
14
- top: 0;
15
- padding: 16px;
16
- background: rgba(0, 0, 0, 0.5);
17
- -webkit-transform: translateZ(0);
18
- transform: translateZ(0);
20
+ top: var(--yarl__slide_title_container_top, 0);
19
21
  }
20
22
  .yarl__slide_description {
21
- font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
22
- font-size: 1rem;
23
- line-height: 1.2;
24
- font-weight: 500;
25
23
  overflow: hidden;
26
24
  -webkit-hyphens: auto;
27
25
  hyphens: auto;
@@ -29,14 +27,8 @@
29
27
  -webkit-box-orient: vertical;
30
28
  -webkit-line-clamp: var(--yarl__slide_description_max_lines, 3);
31
29
  text-align: var(--yarl__slide_description_text_align, start);
30
+ color: var(--yarl__slide_description_color, #fff);
32
31
  }
33
32
  .yarl__slide_description_container {
34
- position: absolute;
35
- left: 0;
36
- right: 0;
37
- bottom: 0;
38
- padding: 16px;
39
- background: rgba(0, 0, 0, 0.5);
40
- -webkit-transform: translateZ(0);
41
- transform: translateZ(0);
33
+ bottom: var(--yarl__slide_description_container_bottom, 0);
42
34
  }
@@ -18,11 +18,10 @@
18
18
  position: relative;
19
19
  }
20
20
  .yarl__thumbnails_container {
21
- color: #fff;
22
- background-color: #000;
23
- overflow: hidden;
24
- padding: 16px;
21
+ background-color: var(--yarl__thumbnails_container_background_color, var(--yarl__color_backdrop, #000));
22
+ padding: var(--yarl__thumbnails_container_padding, 16px);
25
23
  position: relative;
24
+ overflow: hidden;
26
25
  z-index: 0;
27
26
  -webkit-user-select: none;
28
27
  -moz-user-select: none;
@@ -36,11 +35,11 @@
36
35
  }
37
36
  .yarl__thumbnails_top .yarl__thumbnails_container::before, .yarl__thumbnails_bottom .yarl__thumbnails_container::before {
38
37
  left: 0;
39
- background: linear-gradient(to left, transparent, #000);
38
+ background: linear-gradient(to left, transparent, var(--yarl__color_backdrop, #000));
40
39
  }
41
40
  .yarl__thumbnails_top .yarl__thumbnails_container::after, .yarl__thumbnails_bottom .yarl__thumbnails_container::after {
42
41
  right: 0;
43
- background: linear-gradient(to right, transparent, #000);
42
+ background: linear-gradient(to right, transparent, var(--yarl__color_backdrop, #000));
44
43
  }
45
44
  .yarl__thumbnails_top .yarl__thumbnails_container::before, .yarl__thumbnails_top .yarl__thumbnails_container::after, .yarl__thumbnails_bottom .yarl__thumbnails_container::before, .yarl__thumbnails_bottom .yarl__thumbnails_container::after {
46
45
  top: 0;
@@ -49,11 +48,11 @@
49
48
  }
50
49
  .yarl__thumbnails_start .yarl__thumbnails_container::before, .yarl__thumbnails_end .yarl__thumbnails_container::before {
51
50
  top: 0;
52
- background: linear-gradient(to top, transparent, #000);
51
+ background: linear-gradient(to top, transparent, var(--yarl__color_backdrop, #000));
53
52
  }
54
53
  .yarl__thumbnails_start .yarl__thumbnails_container::after, .yarl__thumbnails_end .yarl__thumbnails_container::after {
55
54
  bottom: 0;
56
- background: linear-gradient(to bottom, transparent, #000);
55
+ background: linear-gradient(to bottom, transparent, var(--yarl__color_backdrop, #000));
57
56
  }
58
57
  .yarl__thumbnails_start .yarl__thumbnails_container::before, .yarl__thumbnails_start .yarl__thumbnails_container::after, .yarl__thumbnails_end .yarl__thumbnails_container::before, .yarl__thumbnails_end .yarl__thumbnails_container::after {
59
58
  left: 0;
@@ -69,8 +68,8 @@
69
68
  -webkit-appearance: none;
70
69
  -moz-appearance: none;
71
70
  appearance: none;
72
- background: transparent;
73
- border: var(--yarl__thumbnails_thumbnail_border, 1px) solid rgba(255, 255, 255, 0.8);
71
+ background: var(--yarl__thumbnails_thumbnail_background, #000);
72
+ border: var(--yarl__thumbnails_thumbnail_border, 1px solid var(--yarl__color_button, rgba(255, 255, 255, 0.8)));
74
73
  border-radius: var(--yarl__thumbnails_thumbnail_border_radius, 4px);
75
74
  -webkit-tap-highlight-color: transparent;
76
75
  flex-shrink: 0;
@@ -81,8 +80,11 @@
81
80
  height: var(--yarl__thumbnails_thumbnail_height, 80px);
82
81
  box-sizing: content-box;
83
82
  }
83
+ .yarl__thumbnails_thumbnail > *:only-child {
84
+ flex: 1;
85
+ }
84
86
  .yarl__thumbnails_thumbnail_active {
85
- border-color: #fff;
87
+ border-color: var(--yarl__thumbnails_thumbnail_active_border_color, var(--yarl__color_button_active, #fff));
86
88
  }
87
89
  .yarl__thumbnails_thumbnail_fadein {
88
90
  opacity: 0;
@@ -99,16 +101,16 @@
99
101
  cursor: unset;
100
102
  }
101
103
  .yarl__thumbnails_thumbnail_icon {
102
- color: rgba(255, 255, 255, 0.8);
103
- -webkit-filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8));
104
- filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8));
104
+ color: var(--yarl__thumbnails_thumbnail_icon_color, var(--yarl__color_button, rgba(255, 255, 255, 0.8)));
105
+ -webkit-filter: var(--yarl__thumbnails_thumbnail_icon_filter, drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8)));
106
+ filter: var(--yarl__thumbnails_thumbnail_icon_filter, drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8)));
105
107
  position: absolute;
106
108
  top: 50%;
107
109
  left: 50%;
108
110
  -webkit-transform: translate3d(-50%, -50%, 0);
109
111
  transform: translate3d(-50%, -50%, 0);
110
- width: 32px;
111
- height: 32px;
112
+ width: var(--yarl__thumbnails_thumbnail_icon_size, 32px);
113
+ height: var(--yarl__thumbnails_thumbnail_icon_size, 32px);
112
114
  }
113
115
  .yarl__thumbnails_contain_image {
114
116
  -o-object-fit: contain;
package/dist/styles.css CHANGED
@@ -5,10 +5,10 @@
5
5
  .yarl__portal {
6
6
  position: fixed;
7
7
  inset: 0;
8
- z-index: 9999;
9
- overflow: hidden;
10
8
  opacity: 0;
11
- transition: opacity var(--yarl__fade_animation_duration, 250ms) ease;
9
+ overflow: hidden;
10
+ z-index: var(--yarl__portal_zindex, 9999);
11
+ transition: opacity var(--yarl__fade_animation_duration, 250ms) var(--yarl__fade_animation_timing_function, ease);
12
12
  }
13
13
  .yarl__portal_open {
14
14
  opacity: 1;
@@ -22,8 +22,7 @@
22
22
  .yarl__container {
23
23
  position: relative;
24
24
  overflow: hidden;
25
- color: #fff;
26
- background-color: #000;
25
+ background-color: var(--yarl__container_background_color, var(--yarl__color_backdrop, #000));
27
26
  outline: 0;
28
27
  }
29
28
  .yarl__carousel {
@@ -44,9 +43,9 @@
44
43
  padding: var(--yarl__carousel_padding, 16px);
45
44
  -webkit-transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%)) * var(--yarl__direction, 1)), 0, 0);
46
45
  transform: translate3d(calc(var(--yarl__slide_offset, 0) * (100% + var(--yarl__carousel_spacing, 30%)) * var(--yarl__direction, 1)), 0, 0);
47
- transition: -webkit-transform var(--yarl__swipe_animation_duration, 500ms) ease-out;
48
- transition: transform var(--yarl__swipe_animation_duration, 500ms) ease-out;
49
- transition: transform var(--yarl__swipe_animation_duration, 500ms) ease-out, -webkit-transform var(--yarl__swipe_animation_duration, 500ms) ease-out;
46
+ transition: -webkit-transform var(--yarl__swipe_animation_duration, 500ms) var(--yarl__swipe_animation_timing_function, ease-out);
47
+ transition: transform var(--yarl__swipe_animation_duration, 500ms) var(--yarl__swipe_animation_timing_function, ease-out);
48
+ transition: transform var(--yarl__swipe_animation_duration, 500ms) var(--yarl__swipe_animation_timing_function, ease-out), -webkit-transform var(--yarl__swipe_animation_duration, 500ms) var(--yarl__swipe_animation_timing_function, ease-out);
50
49
  }
51
50
  [dir=rtl] .yarl__slide {
52
51
  --yarl__direction: -1;
@@ -57,8 +56,7 @@
57
56
  transition: unset;
58
57
  }
59
58
  .yarl__slide_image {
60
- -o-object-fit: contain;
61
- object-fit: contain;
59
+ display: block;
62
60
  -moz-user-select: none;
63
61
  user-select: none;
64
62
  -webkit-user-select: none;
@@ -67,6 +65,8 @@
67
65
  transform: translate3d(0, 0, 0);
68
66
  }
69
67
  .yarl__slide_image_cover {
68
+ width: 100%;
69
+ height: 100%;
70
70
  -o-object-fit: cover;
71
71
  object-fit: cover;
72
72
  }
@@ -82,7 +82,7 @@
82
82
  line-height: 0;
83
83
  }
84
84
  .yarl__slide_loading {
85
- color: rgba(255, 255, 255, 0.8);
85
+ color: var(--yarl__slide_icon_loading_color, var(--yarl__color_button, rgba(255, 255, 255, 0.8)));
86
86
  -webkit-animation: yarl__delayed_fadein 1s linear;
87
87
  animation: yarl__delayed_fadein 1s linear;
88
88
  }
@@ -123,9 +123,9 @@
123
123
  animation-delay: -1s;
124
124
  }
125
125
  .yarl__slide_error {
126
- width: 48px;
127
- height: 48px;
128
- color: red;
126
+ width: var(--yarl__slide_icon_error_size, 48px);
127
+ height: var(--yarl__slide_icon_error_size, 48px);
128
+ color: var(--yarl__slide_icon_error_color, red);
129
129
  }
130
130
  @media (prefers-reduced-motion) {
131
131
  .yarl__portal, .yarl__slide {
@@ -141,47 +141,47 @@
141
141
  inset: 0 0 auto auto;
142
142
  display: flex;
143
143
  justify-content: flex-end;
144
- padding: 8px;
144
+ padding: var(--yarl__toolbar_padding, 8px);
145
145
  }
146
146
  [dir=rtl] .yarl__toolbar {
147
147
  inset: 0 auto auto 0;
148
148
  }
149
149
  .yarl__icon {
150
- width: 32px;
151
- height: 32px;
150
+ width: var(--yarl__icon_size, 32px);
151
+ height: var(--yarl__icon_size, 32px);
152
152
  }
153
153
  .yarl__button {
154
+ cursor: pointer;
154
155
  -webkit-appearance: none;
155
156
  -moz-appearance: none;
156
157
  appearance: none;
157
- background-color: transparent;
158
- cursor: pointer;
159
- border: 0;
160
- margin: 0;
158
+ background-color: var(--yarl__button_background_color, transparent);
159
+ border: var(--yarl__button_border, 0);
160
+ margin: var(--yarl__button_margin, 0);
161
161
  outline: none;
162
162
  line-height: 0;
163
- padding: 8px;
164
- color: rgba(255, 255, 255, 0.8);
165
- -webkit-filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8));
166
- filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8));
163
+ padding: var(--yarl__button_padding, 8px);
164
+ color: var(--yarl__color_button, rgba(255, 255, 255, 0.8));
165
+ -webkit-filter: var(--yarl__button_filter, drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8)));
166
+ filter: var(--yarl__button_filter, drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8)));
167
167
  -webkit-tap-highlight-color: transparent;
168
168
  }
169
169
  .yarl__button:focus {
170
- color: #fff;
170
+ color: var(--yarl__color_button_active, #fff);
171
171
  }
172
172
  .yarl__button:focus:not(:focus-visible) {
173
- color: rgba(255, 255, 255, 0.8);
173
+ color: var(--yarl__color_button, rgba(255, 255, 255, 0.8));
174
174
  }
175
175
  .yarl__button:focus-visible {
176
- color: #fff;
176
+ color: var(--yarl__color_button_active, #fff);
177
177
  }
178
178
  @media (hover: hover) {
179
179
  .yarl__button:hover, .yarl__button:focus:hover, .yarl__button:focus-visible:hover {
180
- color: #fff;
180
+ color: var(--yarl__color_button_active, #fff);
181
181
  }
182
182
  }
183
183
  .yarl__button:disabled {
184
- color: rgba(255, 255, 255, 0.4);
184
+ color: var(--yarl__color_button_disabled, rgba(255, 255, 255, 0.4));
185
185
  cursor: default;
186
186
  }
187
187
  .yarl__navigation_prev, .yarl__navigation_next {
@@ -189,7 +189,7 @@
189
189
  top: 50%;
190
190
  -webkit-transform: translateY(-50%);
191
191
  transform: translateY(-50%);
192
- padding: 24px 16px;
192
+ padding: var(--yarl__navigation_button_padding, 24px 16px);
193
193
  }
194
194
  .yarl__navigation_prev {
195
195
  left: 0;
package/dist/types.d.ts CHANGED
@@ -33,6 +33,23 @@ export interface SlideTypes {
33
33
  }
34
34
  /** Slide */
35
35
  export declare type Slide = SlideTypes[keyof SlideTypes];
36
+ /** Supported customization slots */
37
+ export interface SlotType {
38
+ /** lightbox root customization slot */
39
+ root: "root";
40
+ /** lightbox container customization slot */
41
+ container: "container";
42
+ /** lightbox button customization slot */
43
+ button: "button";
44
+ /** lightbox icon customization slot */
45
+ icon: "icon";
46
+ }
47
+ /** Customization slots */
48
+ export declare type Slot = SlotType[keyof SlotType];
49
+ /** Customization slots styles */
50
+ export declare type SlotStyles = {
51
+ [key in Slot]?: React.CSSProperties;
52
+ };
36
53
  /** Carousel settings */
37
54
  export interface CarouselSettings {
38
55
  /** if `true`, the lightbox carousel doesn't wrap around */
@@ -61,6 +78,8 @@ export interface ControllerSettings {
61
78
  touchAction: "none" | "pan-y";
62
79
  /** if `true`, set ARIA attributes on the controller div */
63
80
  aria: boolean;
81
+ /** if `true`, close the lightbox when the backdrop is clicked */
82
+ closeOnBackdropClick: boolean;
64
83
  }
65
84
  /** Custom render functions. */
66
85
  export interface Render {
@@ -139,6 +158,10 @@ export interface LightboxProps {
139
158
  controller: ControllerSettings;
140
159
  /** lifecycle callbacks */
141
160
  on: Callbacks;
161
+ /** customization styles */
162
+ styles: SlotStyles;
163
+ /** CSS class of the lightbox root element */
164
+ className: string;
142
165
  }
143
166
  export declare const LightboxDefaultProps: {
144
167
  open: boolean;
@@ -153,6 +176,8 @@ export declare const LightboxDefaultProps: {
153
176
  carousel: CarouselSettings;
154
177
  controller: ControllerSettings;
155
178
  on: Callbacks;
179
+ styles: SlotStyles;
180
+ className: string;
156
181
  };
157
182
  /** Custom UI labels */
158
183
  export declare type Labels = {
package/dist/types.js CHANGED
@@ -22,6 +22,9 @@ export const LightboxDefaultProps = {
22
22
  focus: true,
23
23
  aria: false,
24
24
  touchAction: "none",
25
+ closeOnBackdropClick: false,
25
26
  },
26
27
  on: {},
28
+ styles: {},
29
+ className: "",
27
30
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yet-another-react-lightbox",
3
- "version": "1.11.1",
3
+ "version": "1.13.1",
4
4
  "description": "Modern React lightbox component",
5
5
  "author": "Igor Danchenko",
6
6
  "license": "MIT",