@jekrch/react-viewport-lightbox 0.2.0 → 0.3.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 +30 -22
- package/dist/index.cjs +50 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -1
- package/dist/index.d.ts +58 -1
- package/dist/index.js +50 -9
- package/dist/index.js.map +1 -1
- package/dist/styles.css +60 -7
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -50,6 +50,12 @@ interface ViewerContext<TData = unknown> {
|
|
|
50
50
|
index: number;
|
|
51
51
|
item: ViewerItem<TData>;
|
|
52
52
|
total: number;
|
|
53
|
+
/**
|
|
54
|
+
* True once the exit animation has started (after a close was requested,
|
|
55
|
+
* before `onClose` fires and the viewer unmounts). Lets overlay content fade
|
|
56
|
+
* out in step with the closing chrome instead of vanishing on unmount.
|
|
57
|
+
*/
|
|
58
|
+
closing: boolean;
|
|
53
59
|
hasPrev: boolean;
|
|
54
60
|
hasNext: boolean;
|
|
55
61
|
goPrev: () => void;
|
|
@@ -90,6 +96,14 @@ interface ImageViewerProps<TData = unknown> {
|
|
|
90
96
|
onNavigate?: (direction: "prev" | "next") => void;
|
|
91
97
|
/** Called AFTER the exit animation completes. */
|
|
92
98
|
onClose: () => void;
|
|
99
|
+
/**
|
|
100
|
+
* Called when the user presses Escape, before the viewer closes. Return
|
|
101
|
+
* `true` to mark the key handled and veto the default close — e.g. to dismiss
|
|
102
|
+
* a consumer overlay (drawer/graph) first, closing the viewer only on a
|
|
103
|
+
* second press. Return `false`/`undefined` to fall through to the default
|
|
104
|
+
* close.
|
|
105
|
+
*/
|
|
106
|
+
onEscape?: () => boolean;
|
|
93
107
|
/**
|
|
94
108
|
* Enables a shared-element "zoom from thumbnail" open/close transition. Given
|
|
95
109
|
* the active index, return the on-screen rect of the source element (e.g. the
|
|
@@ -109,6 +123,20 @@ interface ImageViewerProps<TData = unknown> {
|
|
|
109
123
|
zoomToCursor?: boolean;
|
|
110
124
|
/** Show the `index / total` counter. Default `true`. */
|
|
111
125
|
showCounter?: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Show the built-in zoom in/out/reset buttons in the top bar. Independent of
|
|
128
|
+
* `zoom` (which governs the gesture behavior): set this `false` to keep
|
|
129
|
+
* zoom/pan gestures while a consumer overlay (e.g. an open graph/drawer that
|
|
130
|
+
* covers the image) temporarily owns the chrome. Default `true`.
|
|
131
|
+
*/
|
|
132
|
+
showZoomControls?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Suppress built-in arrow-key navigation (and the swipe commit) without
|
|
135
|
+
* tearing the viewer down. Useful while an overlay that has its own
|
|
136
|
+
* left/right handling is open. Does not hide the on-screen nav buttons.
|
|
137
|
+
* Default `false`.
|
|
138
|
+
*/
|
|
139
|
+
disableNavigation?: boolean;
|
|
112
140
|
/** Wrap around at the ends. Default `false`. */
|
|
113
141
|
loop?: boolean;
|
|
114
142
|
/**
|
|
@@ -129,6 +157,35 @@ interface ImageViewerProps<TData = unknown> {
|
|
|
129
157
|
renderNavStart?: (ctx: ViewerContext<TData>) => ReactNode;
|
|
130
158
|
/** Pinned to the RIGHT edge of the nav row; mirror of `renderNavStart`. */
|
|
131
159
|
renderNavEnd?: (ctx: ViewerContext<TData>) => ReactNode;
|
|
160
|
+
/**
|
|
161
|
+
* Where the `renderNavStart` / `renderNavEnd` slots sit relative to the
|
|
162
|
+
* prev/counter/next group:
|
|
163
|
+
* - `"edge"` (default): pinned to the left/right edges of the nav row (max
|
|
164
|
+
* 42rem), keeping the nav group optically centered regardless of slot width.
|
|
165
|
+
* - `"inline"`: placed directly flanking the nav group as one centered
|
|
166
|
+
* cluster, so a details/info toggle hugs the arrows.
|
|
167
|
+
*/
|
|
168
|
+
navSlotPlacement?: "edge" | "inline";
|
|
169
|
+
/**
|
|
170
|
+
* Size of the prev/next nav arrows (the bottom nav controls). A number is
|
|
171
|
+
* treated as pixels; a string is used verbatim (e.g. `"1.5rem"`). Sets the
|
|
172
|
+
* `--rvl-nav-height` custom property, so it can equally be themed in CSS.
|
|
173
|
+
* Defaults to `2.375rem` (38px) to match the comic-snaps viewer.
|
|
174
|
+
*/
|
|
175
|
+
navHeight?: number | string;
|
|
176
|
+
/**
|
|
177
|
+
* Gap between the bottom nav controls and the viewport's bottom edge. A number
|
|
178
|
+
* is treated as pixels; a string is used verbatim (e.g. `"2rem"`). Sets the
|
|
179
|
+
* `--rvl-nav-inset` custom property and is floored by the device safe-area
|
|
180
|
+
* inset. Defaults to `1.3rem`.
|
|
181
|
+
*/
|
|
182
|
+
navInset?: number | string;
|
|
183
|
+
/**
|
|
184
|
+
* Counter font size. By default the counter scales with `navHeight` (≈0.29×);
|
|
185
|
+
* set this to override that ratio with a fixed size. A number is treated as
|
|
186
|
+
* pixels; a string is used verbatim. Sets `--rvl-counter-font-size`.
|
|
187
|
+
*/
|
|
188
|
+
counterFontSize?: number | string;
|
|
132
189
|
/** Content below the nav row. */
|
|
133
190
|
renderFooter?: (ctx: ViewerContext<TData>) => ReactNode;
|
|
134
191
|
/** Drawers/graphs layered over the image. */
|
|
@@ -144,7 +201,7 @@ interface ImageViewerProps<TData = unknown> {
|
|
|
144
201
|
* `onIndexChange`; mount it when open and it runs its own enter/exit animation,
|
|
145
202
|
* calling `onClose` after the exit completes.
|
|
146
203
|
*/
|
|
147
|
-
declare function ImageViewer<TData = unknown>({ items, index, onIndexChange, onNavigate, onClose, getOriginRect, zoom, zoomToCursor, showCounter, loop, closeOnBackdropClick, renderHeader, renderHeaderActions, renderNavStart, renderNavEnd, renderFooter, renderOverlay, classNames, icons, ariaLabel, }: ImageViewerProps<TData>): react.JSX.Element | null;
|
|
204
|
+
declare function ImageViewer<TData = unknown>({ items, index, onIndexChange, onNavigate, onClose, onEscape, getOriginRect, zoom, zoomToCursor, showCounter, showZoomControls, disableNavigation, loop, closeOnBackdropClick, renderHeader, renderHeaderActions, renderNavStart, renderNavEnd, navSlotPlacement, navHeight, navInset, counterFontSize, renderFooter, renderOverlay, classNames, icons, ariaLabel, }: ImageViewerProps<TData>): react.JSX.Element | null;
|
|
148
205
|
|
|
149
206
|
interface NavButtonProps {
|
|
150
207
|
direction: "prev" | "next";
|
package/dist/index.d.ts
CHANGED
|
@@ -50,6 +50,12 @@ interface ViewerContext<TData = unknown> {
|
|
|
50
50
|
index: number;
|
|
51
51
|
item: ViewerItem<TData>;
|
|
52
52
|
total: number;
|
|
53
|
+
/**
|
|
54
|
+
* True once the exit animation has started (after a close was requested,
|
|
55
|
+
* before `onClose` fires and the viewer unmounts). Lets overlay content fade
|
|
56
|
+
* out in step with the closing chrome instead of vanishing on unmount.
|
|
57
|
+
*/
|
|
58
|
+
closing: boolean;
|
|
53
59
|
hasPrev: boolean;
|
|
54
60
|
hasNext: boolean;
|
|
55
61
|
goPrev: () => void;
|
|
@@ -90,6 +96,14 @@ interface ImageViewerProps<TData = unknown> {
|
|
|
90
96
|
onNavigate?: (direction: "prev" | "next") => void;
|
|
91
97
|
/** Called AFTER the exit animation completes. */
|
|
92
98
|
onClose: () => void;
|
|
99
|
+
/**
|
|
100
|
+
* Called when the user presses Escape, before the viewer closes. Return
|
|
101
|
+
* `true` to mark the key handled and veto the default close — e.g. to dismiss
|
|
102
|
+
* a consumer overlay (drawer/graph) first, closing the viewer only on a
|
|
103
|
+
* second press. Return `false`/`undefined` to fall through to the default
|
|
104
|
+
* close.
|
|
105
|
+
*/
|
|
106
|
+
onEscape?: () => boolean;
|
|
93
107
|
/**
|
|
94
108
|
* Enables a shared-element "zoom from thumbnail" open/close transition. Given
|
|
95
109
|
* the active index, return the on-screen rect of the source element (e.g. the
|
|
@@ -109,6 +123,20 @@ interface ImageViewerProps<TData = unknown> {
|
|
|
109
123
|
zoomToCursor?: boolean;
|
|
110
124
|
/** Show the `index / total` counter. Default `true`. */
|
|
111
125
|
showCounter?: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Show the built-in zoom in/out/reset buttons in the top bar. Independent of
|
|
128
|
+
* `zoom` (which governs the gesture behavior): set this `false` to keep
|
|
129
|
+
* zoom/pan gestures while a consumer overlay (e.g. an open graph/drawer that
|
|
130
|
+
* covers the image) temporarily owns the chrome. Default `true`.
|
|
131
|
+
*/
|
|
132
|
+
showZoomControls?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Suppress built-in arrow-key navigation (and the swipe commit) without
|
|
135
|
+
* tearing the viewer down. Useful while an overlay that has its own
|
|
136
|
+
* left/right handling is open. Does not hide the on-screen nav buttons.
|
|
137
|
+
* Default `false`.
|
|
138
|
+
*/
|
|
139
|
+
disableNavigation?: boolean;
|
|
112
140
|
/** Wrap around at the ends. Default `false`. */
|
|
113
141
|
loop?: boolean;
|
|
114
142
|
/**
|
|
@@ -129,6 +157,35 @@ interface ImageViewerProps<TData = unknown> {
|
|
|
129
157
|
renderNavStart?: (ctx: ViewerContext<TData>) => ReactNode;
|
|
130
158
|
/** Pinned to the RIGHT edge of the nav row; mirror of `renderNavStart`. */
|
|
131
159
|
renderNavEnd?: (ctx: ViewerContext<TData>) => ReactNode;
|
|
160
|
+
/**
|
|
161
|
+
* Where the `renderNavStart` / `renderNavEnd` slots sit relative to the
|
|
162
|
+
* prev/counter/next group:
|
|
163
|
+
* - `"edge"` (default): pinned to the left/right edges of the nav row (max
|
|
164
|
+
* 42rem), keeping the nav group optically centered regardless of slot width.
|
|
165
|
+
* - `"inline"`: placed directly flanking the nav group as one centered
|
|
166
|
+
* cluster, so a details/info toggle hugs the arrows.
|
|
167
|
+
*/
|
|
168
|
+
navSlotPlacement?: "edge" | "inline";
|
|
169
|
+
/**
|
|
170
|
+
* Size of the prev/next nav arrows (the bottom nav controls). A number is
|
|
171
|
+
* treated as pixels; a string is used verbatim (e.g. `"1.5rem"`). Sets the
|
|
172
|
+
* `--rvl-nav-height` custom property, so it can equally be themed in CSS.
|
|
173
|
+
* Defaults to `2.375rem` (38px) to match the comic-snaps viewer.
|
|
174
|
+
*/
|
|
175
|
+
navHeight?: number | string;
|
|
176
|
+
/**
|
|
177
|
+
* Gap between the bottom nav controls and the viewport's bottom edge. A number
|
|
178
|
+
* is treated as pixels; a string is used verbatim (e.g. `"2rem"`). Sets the
|
|
179
|
+
* `--rvl-nav-inset` custom property and is floored by the device safe-area
|
|
180
|
+
* inset. Defaults to `1.3rem`.
|
|
181
|
+
*/
|
|
182
|
+
navInset?: number | string;
|
|
183
|
+
/**
|
|
184
|
+
* Counter font size. By default the counter scales with `navHeight` (≈0.29×);
|
|
185
|
+
* set this to override that ratio with a fixed size. A number is treated as
|
|
186
|
+
* pixels; a string is used verbatim. Sets `--rvl-counter-font-size`.
|
|
187
|
+
*/
|
|
188
|
+
counterFontSize?: number | string;
|
|
132
189
|
/** Content below the nav row. */
|
|
133
190
|
renderFooter?: (ctx: ViewerContext<TData>) => ReactNode;
|
|
134
191
|
/** Drawers/graphs layered over the image. */
|
|
@@ -144,7 +201,7 @@ interface ImageViewerProps<TData = unknown> {
|
|
|
144
201
|
* `onIndexChange`; mount it when open and it runs its own enter/exit animation,
|
|
145
202
|
* calling `onClose` after the exit completes.
|
|
146
203
|
*/
|
|
147
|
-
declare function ImageViewer<TData = unknown>({ items, index, onIndexChange, onNavigate, onClose, getOriginRect, zoom, zoomToCursor, showCounter, loop, closeOnBackdropClick, renderHeader, renderHeaderActions, renderNavStart, renderNavEnd, renderFooter, renderOverlay, classNames, icons, ariaLabel, }: ImageViewerProps<TData>): react.JSX.Element | null;
|
|
204
|
+
declare function ImageViewer<TData = unknown>({ items, index, onIndexChange, onNavigate, onClose, onEscape, getOriginRect, zoom, zoomToCursor, showCounter, showZoomControls, disableNavigation, loop, closeOnBackdropClick, renderHeader, renderHeaderActions, renderNavStart, renderNavEnd, navSlotPlacement, navHeight, navInset, counterFontSize, renderFooter, renderOverlay, classNames, icons, ariaLabel, }: ImageViewerProps<TData>): react.JSX.Element | null;
|
|
148
205
|
|
|
149
206
|
interface NavButtonProps {
|
|
150
207
|
direction: "prev" | "next";
|
package/dist/index.js
CHANGED
|
@@ -590,16 +590,29 @@ function useBarMeasure(topBarRef, bottomBarRef, measureKey) {
|
|
|
590
590
|
var lockCount = 0;
|
|
591
591
|
var previousOverflow = "";
|
|
592
592
|
var previousPaddingRight = "";
|
|
593
|
+
var previousPosition = "";
|
|
594
|
+
var previousTop = "";
|
|
595
|
+
var previousWidth = "";
|
|
596
|
+
var lockedScrollY = 0;
|
|
593
597
|
function useBodyScrollLock(isLocked) {
|
|
594
598
|
useEffect(() => {
|
|
595
599
|
if (!isLocked) return;
|
|
596
600
|
if (typeof document === "undefined") return;
|
|
597
601
|
if (lockCount === 0) {
|
|
598
602
|
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
603
|
+
const rootGutter = window.getComputedStyle(document.documentElement).scrollbarGutter;
|
|
604
|
+
const reservesGutter = typeof rootGutter === "string" && rootGutter.includes("stable");
|
|
605
|
+
lockedScrollY = window.scrollY;
|
|
599
606
|
previousOverflow = document.body.style.overflow;
|
|
600
607
|
previousPaddingRight = document.body.style.paddingRight;
|
|
608
|
+
previousPosition = document.body.style.position;
|
|
609
|
+
previousTop = document.body.style.top;
|
|
610
|
+
previousWidth = document.body.style.width;
|
|
601
611
|
document.body.style.overflow = "hidden";
|
|
602
|
-
|
|
612
|
+
document.body.style.position = "fixed";
|
|
613
|
+
document.body.style.top = `-${lockedScrollY}px`;
|
|
614
|
+
document.body.style.width = "100%";
|
|
615
|
+
if (scrollbarWidth > 0 && !reservesGutter) {
|
|
603
616
|
const currentPaddingRight = parseFloat(window.getComputedStyle(document.body).paddingRight) || 0;
|
|
604
617
|
document.body.style.paddingRight = `${currentPaddingRight + scrollbarWidth}px`;
|
|
605
618
|
}
|
|
@@ -610,6 +623,10 @@ function useBodyScrollLock(isLocked) {
|
|
|
610
623
|
if (lockCount === 0) {
|
|
611
624
|
document.body.style.overflow = previousOverflow;
|
|
612
625
|
document.body.style.paddingRight = previousPaddingRight;
|
|
626
|
+
document.body.style.position = previousPosition;
|
|
627
|
+
document.body.style.top = previousTop;
|
|
628
|
+
document.body.style.width = previousWidth;
|
|
629
|
+
window.scrollTo(0, lockedScrollY);
|
|
613
630
|
}
|
|
614
631
|
};
|
|
615
632
|
}, [isLocked]);
|
|
@@ -747,16 +764,23 @@ function ImageViewer({
|
|
|
747
764
|
onIndexChange,
|
|
748
765
|
onNavigate,
|
|
749
766
|
onClose,
|
|
767
|
+
onEscape,
|
|
750
768
|
getOriginRect,
|
|
751
769
|
zoom = true,
|
|
752
770
|
zoomToCursor = true,
|
|
753
771
|
showCounter = true,
|
|
772
|
+
showZoomControls = true,
|
|
773
|
+
disableNavigation = false,
|
|
754
774
|
loop = false,
|
|
755
775
|
closeOnBackdropClick = false,
|
|
756
776
|
renderHeader,
|
|
757
777
|
renderHeaderActions,
|
|
758
778
|
renderNavStart,
|
|
759
779
|
renderNavEnd,
|
|
780
|
+
navSlotPlacement = "edge",
|
|
781
|
+
navHeight,
|
|
782
|
+
navInset,
|
|
783
|
+
counterFontSize,
|
|
760
784
|
renderFooter,
|
|
761
785
|
renderOverlay,
|
|
762
786
|
classNames,
|
|
@@ -801,7 +825,15 @@ function ImageViewer({
|
|
|
801
825
|
const { slideTrackRef, slideActive, slideAnimating, swipeOffset, commitSlide } = slide;
|
|
802
826
|
const gestures = useGestureHandler(zoomPan, slide, hasPrev, hasNext, zoom, zoomToCursor);
|
|
803
827
|
useEffect(() => {
|
|
804
|
-
|
|
828
|
+
if (typeof window === "undefined" || !window.matchMedia) {
|
|
829
|
+
setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
const mq = window.matchMedia("(hover: none) and (pointer: coarse)");
|
|
833
|
+
const update = () => setIsTouchDevice(mq.matches);
|
|
834
|
+
update();
|
|
835
|
+
mq.addEventListener("change", update);
|
|
836
|
+
return () => mq.removeEventListener("change", update);
|
|
805
837
|
}, []);
|
|
806
838
|
useEffect(() => {
|
|
807
839
|
const onResize = () => setViewportWidth(window.innerWidth);
|
|
@@ -920,16 +952,17 @@ function ImageViewer({
|
|
|
920
952
|
useEffect(() => {
|
|
921
953
|
const handler = (e) => {
|
|
922
954
|
if (e.key === "Escape") {
|
|
955
|
+
if (onEscape?.()) return;
|
|
923
956
|
handleClose();
|
|
924
957
|
return;
|
|
925
958
|
}
|
|
926
|
-
if (displayScale > 1) return;
|
|
959
|
+
if (disableNavigation || displayScale > 1) return;
|
|
927
960
|
if (e.key === "ArrowLeft" && hasPrev) navigate("prev");
|
|
928
961
|
if (e.key === "ArrowRight" && hasNext) navigate("next");
|
|
929
962
|
};
|
|
930
963
|
window.addEventListener("keydown", handler);
|
|
931
964
|
return () => window.removeEventListener("keydown", handler);
|
|
932
|
-
}, [handleClose, hasPrev, hasNext, displayScale, navigate]);
|
|
965
|
+
}, [handleClose, hasPrev, hasNext, displayScale, navigate, onEscape, disableNavigation]);
|
|
933
966
|
const setContentShift = useCallback((transform, animate = true) => {
|
|
934
967
|
setContentShiftState({ transform, animate });
|
|
935
968
|
}, []);
|
|
@@ -938,6 +971,7 @@ function ImageViewer({
|
|
|
938
971
|
index,
|
|
939
972
|
item,
|
|
940
973
|
total: items.length,
|
|
974
|
+
closing,
|
|
941
975
|
hasPrev,
|
|
942
976
|
hasNext,
|
|
943
977
|
goPrev: () => navigate("prev"),
|
|
@@ -970,6 +1004,12 @@ function ImageViewer({
|
|
|
970
1004
|
const reservedH = bottomBarH + IMG_PADDING * 2;
|
|
971
1005
|
const imgMaxHeight = `calc(100vh - ${reservedH}px)`;
|
|
972
1006
|
const imgStyle = { maxHeight: imgMaxHeight };
|
|
1007
|
+
const dim = (v) => typeof v === "number" ? `${v}px` : v;
|
|
1008
|
+
const rootStyle = {
|
|
1009
|
+
...navHeight != null && { "--rvl-nav-height": dim(navHeight) },
|
|
1010
|
+
...navInset != null && { "--rvl-nav-inset": dim(navInset) },
|
|
1011
|
+
...counterFontSize != null && { "--rvl-counter-font-size": dim(counterFontSize) }
|
|
1012
|
+
};
|
|
973
1013
|
if (gateEntry && !fullLoaded) imgStyle.opacity = 0;
|
|
974
1014
|
const totalDigits = String(items.length).length;
|
|
975
1015
|
const counterMinWidth = `${totalDigits * 2 * 0.6 + 1.5}em`;
|
|
@@ -979,7 +1019,7 @@ function ImageViewer({
|
|
|
979
1019
|
const nextItem = nextIndex >= 0 ? items[nextIndex] : null;
|
|
980
1020
|
const showAdjacent = slideActive || slideAnimating || swipeOffset !== 0;
|
|
981
1021
|
const adjacentOpacity = Math.min(1, Math.abs(swipeOffset) / (viewportWidth * 0.8 || 1));
|
|
982
|
-
const
|
|
1022
|
+
const showZoomCtrls = zoom && !isTouchDevice && showZoomControls && !contentShift.transform;
|
|
983
1023
|
const headerActions = renderHeaderActions?.(ctx);
|
|
984
1024
|
const navStart = renderNavStart?.(ctx);
|
|
985
1025
|
const navEnd = renderNavEnd?.(ctx);
|
|
@@ -994,6 +1034,7 @@ function ImageViewer({
|
|
|
994
1034
|
"aria-modal": "true",
|
|
995
1035
|
"aria-label": ariaLabel ?? item.alt ?? "Image viewer",
|
|
996
1036
|
tabIndex: -1,
|
|
1037
|
+
style: rootStyle,
|
|
997
1038
|
children: [
|
|
998
1039
|
/* @__PURE__ */ jsx(
|
|
999
1040
|
"div",
|
|
@@ -1007,7 +1048,7 @@ function ImageViewer({
|
|
|
1007
1048
|
/* @__PURE__ */ jsx("div", { className: cx("rvl-header", cn("topBar")), children: renderHeader?.(ctx) }),
|
|
1008
1049
|
/* @__PURE__ */ jsxs("div", { className: "rvl-header-actions", children: [
|
|
1009
1050
|
headerActions,
|
|
1010
|
-
|
|
1051
|
+
showZoomCtrls && isZoomed && /* @__PURE__ */ jsxs(
|
|
1011
1052
|
"button",
|
|
1012
1053
|
{
|
|
1013
1054
|
type: "button",
|
|
@@ -1024,7 +1065,7 @@ function ImageViewer({
|
|
|
1024
1065
|
]
|
|
1025
1066
|
}
|
|
1026
1067
|
),
|
|
1027
|
-
|
|
1068
|
+
showZoomCtrls && /* @__PURE__ */ jsx(
|
|
1028
1069
|
"button",
|
|
1029
1070
|
{
|
|
1030
1071
|
type: "button",
|
|
@@ -1038,7 +1079,7 @@ function ImageViewer({
|
|
|
1038
1079
|
children: mergedIcons.zoomIn
|
|
1039
1080
|
}
|
|
1040
1081
|
),
|
|
1041
|
-
|
|
1082
|
+
showZoomCtrls && /* @__PURE__ */ jsx(
|
|
1042
1083
|
"button",
|
|
1043
1084
|
{
|
|
1044
1085
|
type: "button",
|
|
@@ -1164,7 +1205,7 @@ function ImageViewer({
|
|
|
1164
1205
|
}
|
|
1165
1206
|
),
|
|
1166
1207
|
/* @__PURE__ */ jsxs("div", { ref: bottomBarRef, className: cx("rvl-bar", "rvl-bottom-bar", cn("bottomBar")), children: [
|
|
1167
|
-
showNavRow && /* @__PURE__ */ jsx("div", { className: "rvl-nav-row", children: /* @__PURE__ */ jsxs("div", { className: "rvl-nav-inner", children: [
|
|
1208
|
+
showNavRow && /* @__PURE__ */ jsx("div", { className: "rvl-nav-row", children: /* @__PURE__ */ jsxs("div", { className: cx("rvl-nav-inner", navSlotPlacement === "inline" && "rvl-nav-inline"), children: [
|
|
1168
1209
|
navStart != null && /* @__PURE__ */ jsx("div", { className: cx("rvl-nav-start", cn("navStart")), children: navStart }),
|
|
1169
1210
|
hasNavGroup && /* @__PURE__ */ jsxs("div", { className: "rvl-nav-group", children: [
|
|
1170
1211
|
/* @__PURE__ */ jsx(
|