@mantine/lightbox 9.5.2
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/LICENSE +21 -0
- package/README.md +21 -0
- package/cjs/Lightbox.cjs +56 -0
- package/cjs/Lightbox.cjs.map +1 -0
- package/cjs/Lightbox.module.cjs +30 -0
- package/cjs/Lightbox.module.cjs.map +1 -0
- package/cjs/LightboxCaption/LightboxCaption.cjs +30 -0
- package/cjs/LightboxCaption/LightboxCaption.cjs.map +1 -0
- package/cjs/LightboxCloseButton/LightboxCloseButton.cjs +32 -0
- package/cjs/LightboxCloseButton/LightboxCloseButton.cjs.map +1 -0
- package/cjs/LightboxNavigation/LightboxNavigation.cjs +105 -0
- package/cjs/LightboxNavigation/LightboxNavigation.cjs.map +1 -0
- package/cjs/LightboxProvider/LightboxProvider.cjs +29 -0
- package/cjs/LightboxProvider/LightboxProvider.cjs.map +1 -0
- package/cjs/LightboxRoot/LightboxRoot.cjs +407 -0
- package/cjs/LightboxRoot/LightboxRoot.cjs.map +1 -0
- package/cjs/LightboxSlide/ImageSlide.cjs +27 -0
- package/cjs/LightboxSlide/ImageSlide.cjs.map +1 -0
- package/cjs/LightboxSlide/LightboxSlide.cjs +55 -0
- package/cjs/LightboxSlide/LightboxSlide.cjs.map +1 -0
- package/cjs/LightboxSlide/VideoSlide.cjs +42 -0
- package/cjs/LightboxSlide/VideoSlide.cjs.map +1 -0
- package/cjs/LightboxSlides/LightboxSlides.cjs +56 -0
- package/cjs/LightboxSlides/LightboxSlides.cjs.map +1 -0
- package/cjs/LightboxThumbnails/LightboxThumbnails.cjs +74 -0
- package/cjs/LightboxThumbnails/LightboxThumbnails.cjs.map +1 -0
- package/cjs/LightboxToolbar/LightboxToolbar.cjs +80 -0
- package/cjs/LightboxToolbar/LightboxToolbar.cjs.map +1 -0
- package/cjs/LightboxToolbar/toolbar-items.cjs +156 -0
- package/cjs/LightboxToolbar/toolbar-items.cjs.map +1 -0
- package/cjs/_virtual/_rolldown/runtime.cjs +24 -0
- package/cjs/default-labels.cjs +20 -0
- package/cjs/default-labels.cjs.map +1 -0
- package/cjs/hooks/use-lightbox-keyboard.cjs +107 -0
- package/cjs/hooks/use-lightbox-keyboard.cjs.map +1 -0
- package/cjs/hooks/use-lightbox-lock-scroll.cjs +30 -0
- package/cjs/hooks/use-lightbox-lock-scroll.cjs.map +1 -0
- package/cjs/hooks/use-lightbox-swipe-close.cjs +38 -0
- package/cjs/hooks/use-lightbox-swipe-close.cjs.map +1 -0
- package/cjs/hooks/use-lightbox-zoom.cjs +257 -0
- package/cjs/hooks/use-lightbox-zoom.cjs.map +1 -0
- package/cjs/index.cjs +34 -0
- package/cjs/lightbox.context.cjs +8 -0
- package/cjs/lightbox.context.cjs.map +1 -0
- package/cjs/lightbox.store.cjs +90 -0
- package/cjs/lightbox.store.cjs.map +1 -0
- package/esm/Lightbox.mjs +56 -0
- package/esm/Lightbox.mjs.map +1 -0
- package/esm/Lightbox.module.mjs +30 -0
- package/esm/Lightbox.module.mjs.map +1 -0
- package/esm/LightboxCaption/LightboxCaption.mjs +30 -0
- package/esm/LightboxCaption/LightboxCaption.mjs.map +1 -0
- package/esm/LightboxCloseButton/LightboxCloseButton.mjs +32 -0
- package/esm/LightboxCloseButton/LightboxCloseButton.mjs.map +1 -0
- package/esm/LightboxNavigation/LightboxNavigation.mjs +105 -0
- package/esm/LightboxNavigation/LightboxNavigation.mjs.map +1 -0
- package/esm/LightboxProvider/LightboxProvider.mjs +29 -0
- package/esm/LightboxProvider/LightboxProvider.mjs.map +1 -0
- package/esm/LightboxRoot/LightboxRoot.mjs +404 -0
- package/esm/LightboxRoot/LightboxRoot.mjs.map +1 -0
- package/esm/LightboxSlide/ImageSlide.mjs +27 -0
- package/esm/LightboxSlide/ImageSlide.mjs.map +1 -0
- package/esm/LightboxSlide/LightboxSlide.mjs +55 -0
- package/esm/LightboxSlide/LightboxSlide.mjs.map +1 -0
- package/esm/LightboxSlide/VideoSlide.mjs +42 -0
- package/esm/LightboxSlide/VideoSlide.mjs.map +1 -0
- package/esm/LightboxSlides/LightboxSlides.mjs +56 -0
- package/esm/LightboxSlides/LightboxSlides.mjs.map +1 -0
- package/esm/LightboxThumbnails/LightboxThumbnails.mjs +72 -0
- package/esm/LightboxThumbnails/LightboxThumbnails.mjs.map +1 -0
- package/esm/LightboxToolbar/LightboxToolbar.mjs +80 -0
- package/esm/LightboxToolbar/LightboxToolbar.mjs.map +1 -0
- package/esm/LightboxToolbar/toolbar-items.mjs +153 -0
- package/esm/LightboxToolbar/toolbar-items.mjs.map +1 -0
- package/esm/default-labels.mjs +20 -0
- package/esm/default-labels.mjs.map +1 -0
- package/esm/hooks/use-lightbox-keyboard.mjs +107 -0
- package/esm/hooks/use-lightbox-keyboard.mjs.map +1 -0
- package/esm/hooks/use-lightbox-lock-scroll.mjs +30 -0
- package/esm/hooks/use-lightbox-lock-scroll.mjs.map +1 -0
- package/esm/hooks/use-lightbox-swipe-close.mjs +38 -0
- package/esm/hooks/use-lightbox-swipe-close.mjs.map +1 -0
- package/esm/hooks/use-lightbox-zoom.mjs +257 -0
- package/esm/hooks/use-lightbox-zoom.mjs.map +1 -0
- package/esm/index.mjs +14 -0
- package/esm/lightbox.context.mjs +8 -0
- package/esm/lightbox.context.mjs.map +1 -0
- package/esm/lightbox.store.mjs +79 -0
- package/esm/lightbox.store.mjs.map +1 -0
- package/lib/Lightbox.d.ts +63 -0
- package/lib/LightboxCaption/LightboxCaption.d.ts +18 -0
- package/lib/LightboxCloseButton/LightboxCloseButton.d.ts +16 -0
- package/lib/LightboxNavigation/LightboxNavigation.d.ts +16 -0
- package/lib/LightboxProvider/LightboxProvider.d.ts +19 -0
- package/lib/LightboxRoot/LightboxRoot.d.ts +88 -0
- package/lib/LightboxSlide/ImageSlide.d.ts +12 -0
- package/lib/LightboxSlide/LightboxSlide.d.ts +25 -0
- package/lib/LightboxSlide/VideoSlide.d.ts +12 -0
- package/lib/LightboxSlides/LightboxSlides.d.ts +20 -0
- package/lib/LightboxThumbnails/LightboxThumbnails.d.ts +16 -0
- package/lib/LightboxToolbar/LightboxToolbar.d.ts +19 -0
- package/lib/LightboxToolbar/toolbar-items.d.ts +5 -0
- package/lib/default-labels.d.ts +2 -0
- package/lib/hooks/use-lightbox-keyboard.d.ts +15 -0
- package/lib/hooks/use-lightbox-lock-scroll.d.ts +7 -0
- package/lib/hooks/use-lightbox-swipe-close.d.ts +10 -0
- package/lib/hooks/use-lightbox-zoom.d.ts +33 -0
- package/lib/index.d.mts +67 -0
- package/lib/index.d.ts +67 -0
- package/lib/lightbox.context.d.ts +36 -0
- package/lib/lightbox.store.d.ts +66 -0
- package/lib/lightbox.types.d.ts +131 -0
- package/lib/test-utils.d.ts +7 -0
- package/package.json +63 -0
- package/styles.css +262 -0
- package/styles.layer.css +263 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useLightboxContext } from "../lightbox.context.mjs";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region packages/@mantine/lightbox/src/LightboxSlide/ImageSlide.tsx
|
|
5
|
+
function ImageSlide({ slide, active, stylesApiProps }) {
|
|
6
|
+
const ctx = useLightboxContext();
|
|
7
|
+
const { style: zoomStyle, ...zoomProps } = active && ctx.withZoom ? ctx.getImageZoomProps() : { style: void 0 };
|
|
8
|
+
return /* @__PURE__ */ jsx("img", {
|
|
9
|
+
...ctx.getStyles("slideImage", {
|
|
10
|
+
...stylesApiProps,
|
|
11
|
+
style: zoomStyle
|
|
12
|
+
}),
|
|
13
|
+
src: slide.src,
|
|
14
|
+
alt: slide.alt ?? "",
|
|
15
|
+
srcSet: slide.srcSet,
|
|
16
|
+
sizes: slide.sizes,
|
|
17
|
+
loading: slide.loading ?? (active ? "eager" : "lazy"),
|
|
18
|
+
draggable: false,
|
|
19
|
+
"data-reduce-motion": "true",
|
|
20
|
+
...zoomProps
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
ImageSlide.displayName = "@mantine/lightbox/ImageSlide";
|
|
24
|
+
//#endregion
|
|
25
|
+
export { ImageSlide };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=ImageSlide.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageSlide.mjs","names":[],"sources":["../../src/LightboxSlide/ImageSlide.tsx"],"sourcesContent":["import { useLightboxContext } from '../lightbox.context';\nimport type { LightboxImageSlide } from '../lightbox.types';\nimport type { LightboxSlideStylesApiProps } from './LightboxSlide';\n\ninterface ImageSlideProps {\n slide: LightboxImageSlide;\n active: boolean;\n stylesApiProps?: LightboxSlideStylesApiProps;\n}\n\nexport function ImageSlide({ slide, active, stylesApiProps }: ImageSlideProps) {\n const ctx = useLightboxContext();\n const { style: zoomStyle, ...zoomProps } =\n active && ctx.withZoom ? ctx.getImageZoomProps() : { style: undefined };\n\n return (\n <img\n {...ctx.getStyles('slideImage', { ...stylesApiProps, style: zoomStyle })}\n src={slide.src}\n alt={slide.alt ?? ''}\n srcSet={slide.srcSet}\n sizes={slide.sizes}\n loading={slide.loading ?? (active ? 'eager' : 'lazy')}\n draggable={false}\n data-reduce-motion=\"true\"\n {...zoomProps}\n />\n );\n}\n\nImageSlide.displayName = '@mantine/lightbox/ImageSlide';\n"],"mappings":";;;;AAUA,SAAgB,WAAW,EAAE,OAAO,QAAQ,kBAAmC;CAC7E,MAAM,MAAM,mBAAmB;CAC/B,MAAM,EAAE,OAAO,WAAW,GAAG,cAC3B,UAAU,IAAI,WAAW,IAAI,kBAAkB,IAAI,EAAE,OAAO,KAAA,EAAU;CAExE,OACE,oBAAC,OAAD;EACE,GAAI,IAAI,UAAU,cAAc;GAAE,GAAG;GAAgB,OAAO;EAAU,CAAC;EACvE,KAAK,MAAM;EACX,KAAK,MAAM,OAAO;EAClB,QAAQ,MAAM;EACd,OAAO,MAAM;EACb,SAAS,MAAM,YAAY,SAAS,UAAU;EAC9C,WAAW;EACX,sBAAmB;EACnB,GAAI;CACL,CAAA;AAEL;AAEA,WAAW,cAAc"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useLightboxContext } from "../lightbox.context.mjs";
|
|
3
|
+
import Lightbox_module_default from "../Lightbox.module.mjs";
|
|
4
|
+
import { ImageSlide } from "./ImageSlide.mjs";
|
|
5
|
+
import { VideoSlide } from "./VideoSlide.mjs";
|
|
6
|
+
import { Box, factory, useProps } from "@mantine/core";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
//#region packages/@mantine/lightbox/src/LightboxSlide/LightboxSlide.tsx
|
|
9
|
+
const LightboxSlide = factory((props) => {
|
|
10
|
+
const { classNames, className, style, styles, vars, slide, index, onClick, ...others } = useProps("LightboxSlide", null, props);
|
|
11
|
+
const ctx = useLightboxContext();
|
|
12
|
+
const active = ctx.currentIndex === index;
|
|
13
|
+
const stylesApiProps = {
|
|
14
|
+
classNames,
|
|
15
|
+
styles
|
|
16
|
+
};
|
|
17
|
+
const renderContent = () => {
|
|
18
|
+
if (slide.type === "video") return /* @__PURE__ */ jsx(VideoSlide, {
|
|
19
|
+
slide,
|
|
20
|
+
active,
|
|
21
|
+
stylesApiProps
|
|
22
|
+
});
|
|
23
|
+
if (slide.type === "custom") return slide.render({ active });
|
|
24
|
+
return /* @__PURE__ */ jsx(ImageSlide, {
|
|
25
|
+
slide,
|
|
26
|
+
active,
|
|
27
|
+
stylesApiProps
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
return /* @__PURE__ */ jsx(Box, {
|
|
31
|
+
...ctx.getStyles("slide", {
|
|
32
|
+
className,
|
|
33
|
+
style,
|
|
34
|
+
classNames,
|
|
35
|
+
styles
|
|
36
|
+
}),
|
|
37
|
+
role: "group",
|
|
38
|
+
"aria-roledescription": "slide",
|
|
39
|
+
"data-lightbox-slide": true,
|
|
40
|
+
"aria-label": ctx.labels.slideLabel(index + 1, ctx.slides.length),
|
|
41
|
+
inert: !active,
|
|
42
|
+
...others,
|
|
43
|
+
onClick: (event) => {
|
|
44
|
+
onClick?.(event);
|
|
45
|
+
if (ctx.closeOnClickOutside && !event.defaultPrevented && event.target === event.currentTarget) ctx.onClose();
|
|
46
|
+
},
|
|
47
|
+
children: renderContent()
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
LightboxSlide.classes = Lightbox_module_default;
|
|
51
|
+
LightboxSlide.displayName = "@mantine/lightbox/LightboxSlide";
|
|
52
|
+
//#endregion
|
|
53
|
+
export { LightboxSlide };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=LightboxSlide.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LightboxSlide.mjs","names":["classes"],"sources":["../../src/LightboxSlide/LightboxSlide.tsx"],"sourcesContent":["import {\n Box,\n BoxProps,\n CompoundStylesApiProps,\n ElementProps,\n factory,\n Factory,\n useProps,\n} from '@mantine/core';\nimport { useLightboxContext } from '../lightbox.context';\nimport type { LightboxSlideData } from '../lightbox.types';\nimport { ImageSlide } from './ImageSlide';\nimport { VideoSlide } from './VideoSlide';\nimport classes from '../Lightbox.module.css';\n\nexport type LightboxSlideStylesNames = 'slide' | 'slideImage' | 'slideVideo';\n\nexport interface LightboxSlideStylesApiProps {\n classNames?: CompoundStylesApiProps<LightboxSlideFactory>['classNames'];\n styles?: CompoundStylesApiProps<LightboxSlideFactory>['styles'];\n}\n\nexport interface LightboxSlideProps\n extends BoxProps, CompoundStylesApiProps<LightboxSlideFactory>, ElementProps<'div'> {\n /** Slide data object */\n slide: LightboxSlideData;\n\n /** Index of the slide in the slides array */\n index: number;\n}\n\nexport type LightboxSlideFactory = Factory<{\n props: LightboxSlideProps;\n ref: HTMLDivElement;\n stylesNames: LightboxSlideStylesNames;\n compound: true;\n}>;\n\nexport const LightboxSlide = factory<LightboxSlideFactory>((props) => {\n const { classNames, className, style, styles, vars, slide, index, onClick, ...others } = useProps(\n 'LightboxSlide',\n null,\n props\n );\n\n const ctx = useLightboxContext();\n const active = ctx.currentIndex === index;\n\n const stylesApiProps = { classNames, styles };\n\n const renderContent = () => {\n if (slide.type === 'video') {\n return <VideoSlide slide={slide} active={active} stylesApiProps={stylesApiProps} />;\n }\n\n if (slide.type === 'custom') {\n return slide.render({ active });\n }\n\n return <ImageSlide slide={slide} active={active} stylesApiProps={stylesApiProps} />;\n };\n\n return (\n <Box\n {...ctx.getStyles('slide', { className, style, classNames, styles })}\n role=\"group\"\n aria-roledescription=\"slide\"\n data-lightbox-slide\n aria-label={ctx.labels.slideLabel(index + 1, ctx.slides.length)}\n inert={!active}\n {...others}\n onClick={(event) => {\n onClick?.(event);\n if (\n ctx.closeOnClickOutside &&\n !event.defaultPrevented &&\n event.target === event.currentTarget\n ) {\n ctx.onClose();\n }\n }}\n >\n {renderContent()}\n </Box>\n );\n});\n\nLightboxSlide.classes = classes;\nLightboxSlide.displayName = '@mantine/lightbox/LightboxSlide';\n"],"mappings":";;;;;;;;AAsCA,MAAa,gBAAgB,SAA+B,UAAU;CACpE,MAAM,EAAE,YAAY,WAAW,OAAO,QAAQ,MAAM,OAAO,OAAO,SAAS,GAAG,WAAW,SACvF,iBACA,MACA,KACF;CAEA,MAAM,MAAM,mBAAmB;CAC/B,MAAM,SAAS,IAAI,iBAAiB;CAEpC,MAAM,iBAAiB;EAAE;EAAY;CAAO;CAE5C,MAAM,sBAAsB;EAC1B,IAAI,MAAM,SAAS,SACjB,OAAO,oBAAC,YAAD;GAAmB;GAAe;GAAwB;EAAiB,CAAA;EAGpF,IAAI,MAAM,SAAS,UACjB,OAAO,MAAM,OAAO,EAAE,OAAO,CAAC;EAGhC,OAAO,oBAAC,YAAD;GAAmB;GAAe;GAAwB;EAAiB,CAAA;CACpF;CAEA,OACE,oBAAC,KAAD;EACE,GAAI,IAAI,UAAU,SAAS;GAAE;GAAW;GAAO;GAAY;EAAO,CAAC;EACnE,MAAK;EACL,wBAAqB;EACrB,uBAAA;EACA,cAAY,IAAI,OAAO,WAAW,QAAQ,GAAG,IAAI,OAAO,MAAM;EAC9D,OAAO,CAAC;EACR,GAAI;EACJ,UAAU,UAAU;GAClB,UAAU,KAAK;GACf,IACE,IAAI,uBACJ,CAAC,MAAM,oBACP,MAAM,WAAW,MAAM,eAEvB,IAAI,QAAQ;EAEhB;EAEC,UAAA,cAAc;CACZ,CAAA;AAET,CAAC;AAED,cAAc,UAAUA;AACxB,cAAc,cAAc"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useLightboxContext } from "../lightbox.context.mjs";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { useEffect, useRef } from "react";
|
|
5
|
+
//#region packages/@mantine/lightbox/src/LightboxSlide/VideoSlide.tsx
|
|
6
|
+
function VideoSlide({ slide, active, stylesApiProps }) {
|
|
7
|
+
const ctx = useLightboxContext();
|
|
8
|
+
const videoRef = useRef(null);
|
|
9
|
+
const playing = active && ctx.opened;
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const video = videoRef.current;
|
|
12
|
+
if (!video) return;
|
|
13
|
+
if (!playing) {
|
|
14
|
+
video.pause();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (slide.autoPlay) video.play().catch(() => {});
|
|
18
|
+
}, [playing, slide.autoPlay]);
|
|
19
|
+
return /* @__PURE__ */ jsx("video", {
|
|
20
|
+
ref: videoRef,
|
|
21
|
+
...ctx.getStyles("slideVideo", stylesApiProps),
|
|
22
|
+
src: slide.src,
|
|
23
|
+
poster: slide.poster,
|
|
24
|
+
"aria-label": slide.label,
|
|
25
|
+
autoPlay: playing && slide.autoPlay,
|
|
26
|
+
"data-active": active || void 0,
|
|
27
|
+
controls: true,
|
|
28
|
+
playsInline: true,
|
|
29
|
+
children: slide.tracks?.map((track, index) => /* @__PURE__ */ jsx("track", {
|
|
30
|
+
src: track.src,
|
|
31
|
+
kind: track.kind ?? "subtitles",
|
|
32
|
+
srcLang: track.srcLang,
|
|
33
|
+
label: track.label,
|
|
34
|
+
default: track.default
|
|
35
|
+
}, index))
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
VideoSlide.displayName = "@mantine/lightbox/VideoSlide";
|
|
39
|
+
//#endregion
|
|
40
|
+
export { VideoSlide };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=VideoSlide.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VideoSlide.mjs","names":[],"sources":["../../src/LightboxSlide/VideoSlide.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { useLightboxContext } from '../lightbox.context';\nimport type { LightboxVideoSlide } from '../lightbox.types';\nimport type { LightboxSlideStylesApiProps } from './LightboxSlide';\n\ninterface VideoSlideProps {\n slide: LightboxVideoSlide;\n active: boolean;\n stylesApiProps?: LightboxSlideStylesApiProps;\n}\n\nexport function VideoSlide({ slide, active, stylesApiProps }: VideoSlideProps) {\n const ctx = useLightboxContext();\n const videoRef = useRef<HTMLVideoElement>(null);\n\n // With `transitionProps.keepMounted` the slides stay mounted while the lightbox is\n // closed, so playback has to follow `opened` as well – otherwise a hidden autoplay video\n // starts on its own and keeps playing after the lightbox is dismissed.\n const playing = active && ctx.opened;\n\n useEffect(() => {\n const video = videoRef.current;\n\n if (!video) {\n return;\n }\n\n if (!playing) {\n video.pause();\n return;\n }\n\n // All slides are mounted up front, so the `autoPlay` attribute only ever fires for the\n // slide that happens to be active on mount – playback has to be started explicitly\n // when an already mounted video becomes the current slide.\n if (slide.autoPlay) {\n video.play().catch(() => {});\n }\n }, [playing, slide.autoPlay]);\n\n return (\n /* eslint-disable jsx-a11y/media-has-caption */\n <video\n ref={videoRef}\n {...ctx.getStyles('slideVideo', stylesApiProps)}\n src={slide.src}\n poster={slide.poster}\n aria-label={slide.label}\n autoPlay={playing && slide.autoPlay}\n data-active={active || undefined}\n controls\n playsInline\n >\n {slide.tracks?.map((track, index) => (\n <track\n key={index}\n src={track.src}\n kind={track.kind ?? 'subtitles'}\n srcLang={track.srcLang}\n label={track.label}\n default={track.default}\n />\n ))}\n </video>\n /* eslint-enable jsx-a11y/media-has-caption */\n );\n}\n\nVideoSlide.displayName = '@mantine/lightbox/VideoSlide';\n"],"mappings":";;;;;AAWA,SAAgB,WAAW,EAAE,OAAO,QAAQ,kBAAmC;CAC7E,MAAM,MAAM,mBAAmB;CAC/B,MAAM,WAAW,OAAyB,IAAI;CAK9C,MAAM,UAAU,UAAU,IAAI;CAE9B,gBAAgB;EACd,MAAM,QAAQ,SAAS;EAEvB,IAAI,CAAC,OACH;EAGF,IAAI,CAAC,SAAS;GACZ,MAAM,MAAM;GACZ;EACF;EAKA,IAAI,MAAM,UACR,MAAM,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC;CAE/B,GAAG,CAAC,SAAS,MAAM,QAAQ,CAAC;CAE5B,OAEE,oBAAC,SAAD;EACE,KAAK;EACL,GAAI,IAAI,UAAU,cAAc,cAAc;EAC9C,KAAK,MAAM;EACX,QAAQ,MAAM;EACd,cAAY,MAAM;EAClB,UAAU,WAAW,MAAM;EAC3B,eAAa,UAAU,KAAA;EACvB,UAAA;EACA,aAAA;EAEC,UAAA,MAAM,QAAQ,KAAK,OAAO,UACzB,oBAAC,SAAD;GAEE,KAAK,MAAM;GACX,MAAM,MAAM,QAAQ;GACpB,SAAS,MAAM;GACf,OAAO,MAAM;GACb,SAAS,MAAM;EAChB,GANM,KAMN,CACF;CACI,CAAA;AAGX;AAEA,WAAW,cAAc"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useLightboxContext } from "../lightbox.context.mjs";
|
|
3
|
+
import Lightbox_module_default from "../Lightbox.module.mjs";
|
|
4
|
+
import { useLightboxSwipeClose } from "../hooks/use-lightbox-swipe-close.mjs";
|
|
5
|
+
import { Box, factory, useProps } from "@mantine/core";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
import { useMergedRef } from "@mantine/hooks";
|
|
8
|
+
//#region packages/@mantine/lightbox/src/LightboxSlides/LightboxSlides.tsx
|
|
9
|
+
const LightboxSlides = factory((props) => {
|
|
10
|
+
const { classNames, className, style, styles, vars, emblaRef, children, onTouchStart, onTouchEnd, ...others } = useProps("LightboxSlides", null, props);
|
|
11
|
+
const ctx = useLightboxContext();
|
|
12
|
+
const stylesApiProps = {
|
|
13
|
+
classNames,
|
|
14
|
+
styles
|
|
15
|
+
};
|
|
16
|
+
const viewportRef = useMergedRef(ctx.emblaRef, emblaRef);
|
|
17
|
+
const { handleTouchStart, handleTouchEnd } = useLightboxSwipeClose({
|
|
18
|
+
enabled: ctx.closeOnSwipeDown,
|
|
19
|
+
onClose: ctx.onClose,
|
|
20
|
+
isZoomed: ctx.zoomState.isZoomed
|
|
21
|
+
});
|
|
22
|
+
return /* @__PURE__ */ jsx(Box, {
|
|
23
|
+
...ctx.getStyles("slides", {
|
|
24
|
+
className,
|
|
25
|
+
style,
|
|
26
|
+
classNames,
|
|
27
|
+
styles
|
|
28
|
+
}),
|
|
29
|
+
role: "region",
|
|
30
|
+
"aria-roledescription": "carousel",
|
|
31
|
+
"aria-label": ctx.labels.slidesLabel,
|
|
32
|
+
...others,
|
|
33
|
+
onTouchStart: (event) => {
|
|
34
|
+
onTouchStart?.(event);
|
|
35
|
+
handleTouchStart(event);
|
|
36
|
+
},
|
|
37
|
+
onTouchEnd: (event) => {
|
|
38
|
+
onTouchEnd?.(event);
|
|
39
|
+
handleTouchEnd(event);
|
|
40
|
+
},
|
|
41
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
42
|
+
...ctx.getStyles("slidesViewport", stylesApiProps),
|
|
43
|
+
ref: viewportRef,
|
|
44
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
45
|
+
...ctx.getStyles("slidesContainer", stylesApiProps),
|
|
46
|
+
children
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
LightboxSlides.classes = Lightbox_module_default;
|
|
52
|
+
LightboxSlides.displayName = "@mantine/lightbox/LightboxSlides";
|
|
53
|
+
//#endregion
|
|
54
|
+
export { LightboxSlides };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=LightboxSlides.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LightboxSlides.mjs","names":["classes"],"sources":["../../src/LightboxSlides/LightboxSlides.tsx"],"sourcesContent":["import {\n Box,\n BoxProps,\n CompoundStylesApiProps,\n ElementProps,\n factory,\n Factory,\n useProps,\n} from '@mantine/core';\nimport { useMergedRef } from '@mantine/hooks';\nimport { useLightboxSwipeClose } from '../hooks/use-lightbox-swipe-close';\nimport { useLightboxContext } from '../lightbox.context';\nimport classes from '../Lightbox.module.css';\n\nexport type LightboxSlidesStylesNames = 'slides' | 'slidesViewport' | 'slidesContainer';\n\nexport interface LightboxSlidesProps\n extends BoxProps, CompoundStylesApiProps<LightboxSlidesFactory>, ElementProps<'div'> {\n /** Embla carousel ref callback */\n emblaRef?: React.RefCallback<HTMLDivElement>;\n\n /** Slide components */\n children: React.ReactNode;\n}\n\nexport type LightboxSlidesFactory = Factory<{\n props: LightboxSlidesProps;\n ref: HTMLDivElement;\n stylesNames: LightboxSlidesStylesNames;\n compound: true;\n}>;\n\nexport const LightboxSlides = factory<LightboxSlidesFactory>((props) => {\n const {\n classNames,\n className,\n style,\n styles,\n vars,\n emblaRef,\n children,\n onTouchStart,\n onTouchEnd,\n ...others\n } = useProps('LightboxSlides', null, props);\n\n const ctx = useLightboxContext();\n const stylesApiProps = { classNames, styles };\n\n const viewportRef = useMergedRef(ctx.emblaRef, emblaRef);\n\n const { handleTouchStart, handleTouchEnd } = useLightboxSwipeClose({\n enabled: ctx.closeOnSwipeDown,\n onClose: ctx.onClose,\n isZoomed: ctx.zoomState.isZoomed,\n });\n\n return (\n <Box\n {...ctx.getStyles('slides', { className, style, classNames, styles })}\n role=\"region\"\n aria-roledescription=\"carousel\"\n aria-label={ctx.labels.slidesLabel}\n {...others}\n onTouchStart={(event) => {\n onTouchStart?.(event);\n handleTouchStart(event);\n }}\n onTouchEnd={(event) => {\n onTouchEnd?.(event);\n handleTouchEnd(event);\n }}\n >\n <div {...ctx.getStyles('slidesViewport', stylesApiProps)} ref={viewportRef}>\n <div {...ctx.getStyles('slidesContainer', stylesApiProps)}>{children}</div>\n </div>\n </Box>\n );\n});\n\nLightboxSlides.classes = classes;\nLightboxSlides.displayName = '@mantine/lightbox/LightboxSlides';\n"],"mappings":";;;;;;;;AAgCA,MAAa,iBAAiB,SAAgC,UAAU;CACtE,MAAM,EACJ,YACA,WACA,OACA,QACA,MACA,UACA,UACA,cACA,YACA,GAAG,WACD,SAAS,kBAAkB,MAAM,KAAK;CAE1C,MAAM,MAAM,mBAAmB;CAC/B,MAAM,iBAAiB;EAAE;EAAY;CAAO;CAE5C,MAAM,cAAc,aAAa,IAAI,UAAU,QAAQ;CAEvD,MAAM,EAAE,kBAAkB,mBAAmB,sBAAsB;EACjE,SAAS,IAAI;EACb,SAAS,IAAI;EACb,UAAU,IAAI,UAAU;CAC1B,CAAC;CAED,OACE,oBAAC,KAAD;EACE,GAAI,IAAI,UAAU,UAAU;GAAE;GAAW;GAAO;GAAY;EAAO,CAAC;EACpE,MAAK;EACL,wBAAqB;EACrB,cAAY,IAAI,OAAO;EACvB,GAAI;EACJ,eAAe,UAAU;GACvB,eAAe,KAAK;GACpB,iBAAiB,KAAK;EACxB;EACA,aAAa,UAAU;GACrB,aAAa,KAAK;GAClB,eAAe,KAAK;EACtB;EAEA,UAAA,oBAAC,OAAD;GAAK,GAAI,IAAI,UAAU,kBAAkB,cAAc;GAAG,KAAK;GAC7D,UAAA,oBAAC,OAAD;IAAK,GAAI,IAAI,UAAU,mBAAmB,cAAc;IAAI;GAAc,CAAA;EACvE,CAAA;CACF,CAAA;AAET,CAAC;AAED,eAAe,UAAUA;AACzB,eAAe,cAAc"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useLightboxContext } from "../lightbox.context.mjs";
|
|
3
|
+
import Lightbox_module_default from "../Lightbox.module.mjs";
|
|
4
|
+
import { Collapse, UnstyledButton, factory, useDirection, useProps } from "@mantine/core";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import { useEffect } from "react";
|
|
7
|
+
import useEmblaCarousel from "embla-carousel-react";
|
|
8
|
+
//#region packages/@mantine/lightbox/src/LightboxThumbnails/LightboxThumbnails.tsx
|
|
9
|
+
const LightboxThumbnails = factory((props) => {
|
|
10
|
+
const { classNames, className, style, styles, vars, ...others } = useProps("LightboxThumbnails", null, props);
|
|
11
|
+
const ctx = useLightboxContext();
|
|
12
|
+
const stylesApiProps = {
|
|
13
|
+
classNames,
|
|
14
|
+
styles
|
|
15
|
+
};
|
|
16
|
+
const { dir } = useDirection();
|
|
17
|
+
const [thumbsRef, thumbsEmbla] = useEmblaCarousel({
|
|
18
|
+
containScroll: "keepSnaps",
|
|
19
|
+
dragFree: true,
|
|
20
|
+
direction: dir,
|
|
21
|
+
active: ctx.withThumbnails
|
|
22
|
+
});
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (thumbsEmbla) thumbsEmbla.scrollTo(ctx.currentIndex);
|
|
25
|
+
}, [ctx.currentIndex, thumbsEmbla]);
|
|
26
|
+
if (!ctx.withThumbnails) return null;
|
|
27
|
+
const thumbnails = ctx.slides.map((slide, index) => {
|
|
28
|
+
const hasCustomThumb = slide.type === "custom" && slide.renderThumb;
|
|
29
|
+
const thumbSrc = slide.thumbSrc ?? (slide.type === "video" ? slide.poster : void 0) ?? (slide.type !== "custom" ? slide.src : void 0);
|
|
30
|
+
return /* @__PURE__ */ jsx(UnstyledButton, {
|
|
31
|
+
...ctx.getStyles("thumbnail", stylesApiProps),
|
|
32
|
+
mod: "reduce-motion",
|
|
33
|
+
"data-active": index === ctx.currentIndex || void 0,
|
|
34
|
+
"aria-label": ctx.labels.thumbnailLabel(index + 1, ctx.slides.length),
|
|
35
|
+
"aria-current": index === ctx.currentIndex || void 0,
|
|
36
|
+
onClick: () => ctx.setIndex(index),
|
|
37
|
+
children: hasCustomThumb ? slide.renderThumb() : thumbSrc ? /* @__PURE__ */ jsx("img", {
|
|
38
|
+
...ctx.getStyles("thumbnailImage", stylesApiProps),
|
|
39
|
+
src: thumbSrc,
|
|
40
|
+
alt: "",
|
|
41
|
+
loading: "lazy",
|
|
42
|
+
draggable: false
|
|
43
|
+
}) : null
|
|
44
|
+
}, index);
|
|
45
|
+
});
|
|
46
|
+
return /* @__PURE__ */ jsx(Collapse, {
|
|
47
|
+
expanded: ctx.thumbnailsVisible,
|
|
48
|
+
transitionDuration: ctx.transitionDuration,
|
|
49
|
+
keepMounted: false,
|
|
50
|
+
...ctx.getStyles("thumbnails", {
|
|
51
|
+
className,
|
|
52
|
+
style,
|
|
53
|
+
classNames,
|
|
54
|
+
styles
|
|
55
|
+
}),
|
|
56
|
+
...others,
|
|
57
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
58
|
+
...ctx.getStyles("thumbnailsViewport", stylesApiProps),
|
|
59
|
+
ref: thumbsRef,
|
|
60
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
61
|
+
...ctx.getStyles("thumbnailsContainer", stylesApiProps),
|
|
62
|
+
children: thumbnails
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
LightboxThumbnails.classes = Lightbox_module_default;
|
|
68
|
+
LightboxThumbnails.displayName = "@mantine/lightbox/LightboxThumbnails";
|
|
69
|
+
//#endregion
|
|
70
|
+
export { LightboxThumbnails };
|
|
71
|
+
|
|
72
|
+
//# sourceMappingURL=LightboxThumbnails.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LightboxThumbnails.mjs","names":["classes"],"sources":["../../src/LightboxThumbnails/LightboxThumbnails.tsx"],"sourcesContent":["import { useEffect } from 'react';\nimport useEmblaCarousel from 'embla-carousel-react';\nimport {\n BoxProps,\n Collapse,\n CompoundStylesApiProps,\n ElementProps,\n factory,\n Factory,\n UnstyledButton,\n useDirection,\n useProps,\n} from '@mantine/core';\nimport { useLightboxContext } from '../lightbox.context';\nimport classes from '../Lightbox.module.css';\n\nexport type LightboxThumbnailsStylesNames =\n | 'thumbnails'\n | 'thumbnailsViewport'\n | 'thumbnailsContainer'\n | 'thumbnail'\n | 'thumbnailImage';\n\nexport interface LightboxThumbnailsProps\n extends\n BoxProps,\n CompoundStylesApiProps<LightboxThumbnailsFactory>,\n ElementProps<'div', 'onTransitionEnd' | 'onTransitionStart'> {}\n\nexport type LightboxThumbnailsFactory = Factory<{\n props: LightboxThumbnailsProps;\n ref: HTMLDivElement;\n stylesNames: LightboxThumbnailsStylesNames;\n compound: true;\n}>;\n\nexport const LightboxThumbnails = factory<LightboxThumbnailsFactory>((props) => {\n const { classNames, className, style, styles, vars, ...others } = useProps(\n 'LightboxThumbnails',\n null,\n props\n );\n\n const ctx = useLightboxContext();\n const stylesApiProps = { classNames, styles };\n\n const { dir } = useDirection();\n\n // The second carousel is only built when the strip can actually be shown – `active: false`\n // makes Embla skip its listeners and measurements entirely, so a lightbox without\n // thumbnails does not pay for an instance it never renders.\n const [thumbsRef, thumbsEmbla] = useEmblaCarousel({\n containScroll: 'keepSnaps',\n dragFree: true,\n direction: dir,\n active: ctx.withThumbnails,\n });\n\n useEffect(() => {\n if (thumbsEmbla) {\n thumbsEmbla.scrollTo(ctx.currentIndex);\n }\n }, [ctx.currentIndex, thumbsEmbla]);\n\n if (!ctx.withThumbnails) {\n return null;\n }\n\n const thumbnails = ctx.slides.map((slide, index) => {\n const hasCustomThumb = slide.type === 'custom' && slide.renderThumb;\n const thumbSrc =\n slide.thumbSrc ??\n (slide.type === 'video' ? slide.poster : undefined) ??\n (slide.type !== 'custom' ? slide.src : undefined);\n\n return (\n <UnstyledButton\n key={index}\n {...ctx.getStyles('thumbnail', stylesApiProps)}\n mod=\"reduce-motion\"\n data-active={index === ctx.currentIndex || undefined}\n aria-label={ctx.labels.thumbnailLabel(index + 1, ctx.slides.length)}\n aria-current={index === ctx.currentIndex || undefined}\n onClick={() => ctx.setIndex(index)}\n >\n {hasCustomThumb ? (\n slide.renderThumb!()\n ) : thumbSrc ? (\n <img\n {...ctx.getStyles('thumbnailImage', stylesApiProps)}\n src={thumbSrc}\n alt=\"\"\n loading=\"lazy\"\n draggable={false}\n />\n ) : null}\n </UnstyledButton>\n );\n });\n\n return (\n <Collapse\n expanded={ctx.thumbnailsVisible}\n transitionDuration={ctx.transitionDuration}\n keepMounted={false}\n {...ctx.getStyles('thumbnails', { className, style, classNames, styles })}\n {...others}\n >\n <div {...ctx.getStyles('thumbnailsViewport', stylesApiProps)} ref={thumbsRef}>\n <div {...ctx.getStyles('thumbnailsContainer', stylesApiProps)}>{thumbnails}</div>\n </div>\n </Collapse>\n );\n});\n\nLightboxThumbnails.classes = classes;\nLightboxThumbnails.displayName = '@mantine/lightbox/LightboxThumbnails';\n"],"mappings":";;;;;;;;AAoCA,MAAa,qBAAqB,SAAoC,UAAU;CAC9E,MAAM,EAAE,YAAY,WAAW,OAAO,QAAQ,MAAM,GAAG,WAAW,SAChE,sBACA,MACA,KACF;CAEA,MAAM,MAAM,mBAAmB;CAC/B,MAAM,iBAAiB;EAAE;EAAY;CAAO;CAE5C,MAAM,EAAE,QAAQ,aAAa;CAK7B,MAAM,CAAC,WAAW,eAAe,iBAAiB;EAChD,eAAe;EACf,UAAU;EACV,WAAW;EACX,QAAQ,IAAI;CACd,CAAC;CAED,gBAAgB;EACd,IAAI,aACF,YAAY,SAAS,IAAI,YAAY;CAEzC,GAAG,CAAC,IAAI,cAAc,WAAW,CAAC;CAElC,IAAI,CAAC,IAAI,gBACP,OAAO;CAGT,MAAM,aAAa,IAAI,OAAO,KAAK,OAAO,UAAU;EAClD,MAAM,iBAAiB,MAAM,SAAS,YAAY,MAAM;EACxD,MAAM,WACJ,MAAM,aACL,MAAM,SAAS,UAAU,MAAM,SAAS,KAAA,OACxC,MAAM,SAAS,WAAW,MAAM,MAAM,KAAA;EAEzC,OACE,oBAAC,gBAAD;GAEE,GAAI,IAAI,UAAU,aAAa,cAAc;GAC7C,KAAI;GACJ,eAAa,UAAU,IAAI,gBAAgB,KAAA;GAC3C,cAAY,IAAI,OAAO,eAAe,QAAQ,GAAG,IAAI,OAAO,MAAM;GAClE,gBAAc,UAAU,IAAI,gBAAgB,KAAA;GAC5C,eAAe,IAAI,SAAS,KAAK;GAEhC,UAAA,iBACC,MAAM,YAAa,IACjB,WACF,oBAAC,OAAD;IACE,GAAI,IAAI,UAAU,kBAAkB,cAAc;IAClD,KAAK;IACL,KAAI;IACJ,SAAQ;IACR,WAAW;GACZ,CAAA,IACC;EACU,GAnBT,KAmBS;CAEpB,CAAC;CAED,OACE,oBAAC,UAAD;EACE,UAAU,IAAI;EACd,oBAAoB,IAAI;EACxB,aAAa;EACb,GAAI,IAAI,UAAU,cAAc;GAAE;GAAW;GAAO;GAAY;EAAO,CAAC;EACxE,GAAI;EAEJ,UAAA,oBAAC,OAAD;GAAK,GAAI,IAAI,UAAU,sBAAsB,cAAc;GAAG,KAAK;GACjE,UAAA,oBAAC,OAAD;IAAK,GAAI,IAAI,UAAU,uBAAuB,cAAc;IAAI,UAAA;GAAgB,CAAA;EAC7E,CAAA;CACG,CAAA;AAEd,CAAC;AAED,mBAAmB,UAAUA;AAC7B,mBAAmB,cAAc"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useLightboxContext } from "../lightbox.context.mjs";
|
|
3
|
+
import Lightbox_module_default from "../Lightbox.module.mjs";
|
|
4
|
+
import { createCloseToolbarItem, createDownloadToolbarItem, createFullscreenToolbarItem, createThumbnailsToolbarItem } from "./toolbar-items.mjs";
|
|
5
|
+
import { Box, UnstyledButton, factory, useProps } from "@mantine/core";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region packages/@mantine/lightbox/src/LightboxToolbar/LightboxToolbar.tsx
|
|
8
|
+
const LightboxToolbar = factory((props) => {
|
|
9
|
+
const { classNames, className, style, styles, vars, toolbarItems, ...others } = useProps("LightboxToolbar", null, props);
|
|
10
|
+
const ctx = useLightboxContext();
|
|
11
|
+
const stylesApiProps = {
|
|
12
|
+
classNames,
|
|
13
|
+
styles
|
|
14
|
+
};
|
|
15
|
+
const currentSlide = ctx.slides[ctx.currentIndex];
|
|
16
|
+
const defaultItems = [];
|
|
17
|
+
if (ctx.withThumbnails) defaultItems.push(createThumbnailsToolbarItem(ctx.toggleThumbnails, ctx.thumbnailsVisible, ctx.labels));
|
|
18
|
+
if (ctx.withFullscreen) defaultItems.push(createFullscreenToolbarItem(ctx.toggleFullscreen, ctx.isFullscreen, ctx.labels));
|
|
19
|
+
if (ctx.withDownload && currentSlide && currentSlide.type !== "custom") defaultItems.push(createDownloadToolbarItem(currentSlide.src, ctx.labels));
|
|
20
|
+
defaultItems.push(createCloseToolbarItem(ctx.onClose, ctx.labels));
|
|
21
|
+
const items = typeof toolbarItems === "function" ? toolbarItems({
|
|
22
|
+
slides: ctx.slides,
|
|
23
|
+
currentIndex: ctx.currentIndex,
|
|
24
|
+
setIndex: ctx.setIndex,
|
|
25
|
+
next: ctx.next,
|
|
26
|
+
prev: ctx.prev,
|
|
27
|
+
close: ctx.onClose,
|
|
28
|
+
thumbnailsVisible: ctx.thumbnailsVisible,
|
|
29
|
+
toggleThumbnails: ctx.toggleThumbnails,
|
|
30
|
+
isFullscreen: ctx.isFullscreen,
|
|
31
|
+
toggleFullscreen: ctx.toggleFullscreen,
|
|
32
|
+
zoomed: ctx.zoomState.isZoomed,
|
|
33
|
+
toggleZoom: ctx.toggleZoom,
|
|
34
|
+
labels: ctx.labels
|
|
35
|
+
}) : toolbarItems ?? defaultItems;
|
|
36
|
+
const leftItems = items.filter((item) => item.position === "left");
|
|
37
|
+
const rightItems = items.filter((item) => item.position !== "left");
|
|
38
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
39
|
+
...ctx.getStyles("toolbar", {
|
|
40
|
+
className,
|
|
41
|
+
style,
|
|
42
|
+
classNames,
|
|
43
|
+
styles
|
|
44
|
+
}),
|
|
45
|
+
...others,
|
|
46
|
+
children: [
|
|
47
|
+
/* @__PURE__ */ jsx("div", {
|
|
48
|
+
...ctx.getStyles("toolbarGroup", stylesApiProps),
|
|
49
|
+
children: leftItems.map((item) => /* @__PURE__ */ jsx(UnstyledButton, {
|
|
50
|
+
...ctx.getStyles("toolbarButton", stylesApiProps),
|
|
51
|
+
mod: "reduce-motion",
|
|
52
|
+
"aria-label": item.label,
|
|
53
|
+
onClick: item.onClick,
|
|
54
|
+
children: item.icon
|
|
55
|
+
}, item.key))
|
|
56
|
+
}),
|
|
57
|
+
/* @__PURE__ */ jsx("span", {
|
|
58
|
+
...ctx.getStyles("counter", stylesApiProps),
|
|
59
|
+
"aria-hidden": "true",
|
|
60
|
+
children: ctx.slides.length > 0 ? `${ctx.currentIndex + 1} / ${ctx.slides.length}` : null
|
|
61
|
+
}),
|
|
62
|
+
/* @__PURE__ */ jsx("div", {
|
|
63
|
+
...ctx.getStyles("toolbarGroup", stylesApiProps),
|
|
64
|
+
children: rightItems.map((item) => /* @__PURE__ */ jsx(UnstyledButton, {
|
|
65
|
+
...ctx.getStyles("toolbarButton", stylesApiProps),
|
|
66
|
+
mod: "reduce-motion",
|
|
67
|
+
"aria-label": item.label,
|
|
68
|
+
onClick: item.onClick,
|
|
69
|
+
children: item.icon
|
|
70
|
+
}, item.key))
|
|
71
|
+
})
|
|
72
|
+
]
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
LightboxToolbar.classes = Lightbox_module_default;
|
|
76
|
+
LightboxToolbar.displayName = "@mantine/lightbox/LightboxToolbar";
|
|
77
|
+
//#endregion
|
|
78
|
+
export { LightboxToolbar };
|
|
79
|
+
|
|
80
|
+
//# sourceMappingURL=LightboxToolbar.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LightboxToolbar.mjs","names":["classes"],"sources":["../../src/LightboxToolbar/LightboxToolbar.tsx"],"sourcesContent":["import {\n Box,\n BoxProps,\n CompoundStylesApiProps,\n ElementProps,\n factory,\n Factory,\n UnstyledButton,\n useProps,\n} from '@mantine/core';\nimport { useLightboxContext } from '../lightbox.context';\nimport type { ToolbarItem, ToolbarItems } from '../lightbox.types';\nimport {\n createCloseToolbarItem,\n createDownloadToolbarItem,\n createFullscreenToolbarItem,\n createThumbnailsToolbarItem,\n} from './toolbar-items';\nimport classes from '../Lightbox.module.css';\n\nexport type LightboxToolbarStylesNames = 'toolbar' | 'toolbarGroup' | 'toolbarButton' | 'counter';\n\nexport interface LightboxToolbarProps\n extends BoxProps, CompoundStylesApiProps<LightboxToolbarFactory>, ElementProps<'div'> {\n /** Custom toolbar items, overrides default toolbar actions. Can be a function that receives the current lightbox state and handlers. */\n toolbarItems?: ToolbarItems;\n}\n\nexport type LightboxToolbarFactory = Factory<{\n props: LightboxToolbarProps;\n ref: HTMLDivElement;\n stylesNames: LightboxToolbarStylesNames;\n compound: true;\n}>;\n\nexport const LightboxToolbar = factory<LightboxToolbarFactory>((props) => {\n const { classNames, className, style, styles, vars, toolbarItems, ...others } = useProps(\n 'LightboxToolbar',\n null,\n props\n );\n\n const ctx = useLightboxContext();\n const stylesApiProps = { classNames, styles };\n const currentSlide = ctx.slides[ctx.currentIndex];\n\n const defaultItems: ToolbarItem[] = [];\n\n if (ctx.withThumbnails) {\n defaultItems.push(\n createThumbnailsToolbarItem(ctx.toggleThumbnails, ctx.thumbnailsVisible, ctx.labels)\n );\n }\n\n if (ctx.withFullscreen) {\n defaultItems.push(\n createFullscreenToolbarItem(ctx.toggleFullscreen, ctx.isFullscreen, ctx.labels)\n );\n }\n\n if (ctx.withDownload && currentSlide && currentSlide.type !== 'custom') {\n defaultItems.push(createDownloadToolbarItem(currentSlide.src, ctx.labels));\n }\n\n defaultItems.push(createCloseToolbarItem(ctx.onClose, ctx.labels));\n\n const items =\n typeof toolbarItems === 'function'\n ? toolbarItems({\n slides: ctx.slides,\n currentIndex: ctx.currentIndex,\n setIndex: ctx.setIndex,\n next: ctx.next,\n prev: ctx.prev,\n close: ctx.onClose,\n thumbnailsVisible: ctx.thumbnailsVisible,\n toggleThumbnails: ctx.toggleThumbnails,\n isFullscreen: ctx.isFullscreen,\n toggleFullscreen: ctx.toggleFullscreen,\n zoomed: ctx.zoomState.isZoomed,\n toggleZoom: ctx.toggleZoom,\n labels: ctx.labels,\n })\n : (toolbarItems ?? defaultItems);\n const leftItems = items.filter((item) => item.position === 'left');\n const rightItems = items.filter((item) => item.position !== 'left');\n\n return (\n <Box {...ctx.getStyles('toolbar', { className, style, classNames, styles })} {...others}>\n <div {...ctx.getStyles('toolbarGroup', stylesApiProps)}>\n {leftItems.map((item) => (\n <UnstyledButton\n key={item.key}\n {...ctx.getStyles('toolbarButton', stylesApiProps)}\n mod=\"reduce-motion\"\n aria-label={item.label}\n onClick={item.onClick}\n >\n {item.icon}\n </UnstyledButton>\n ))}\n </div>\n\n {/* An empty gallery has no slide to count – rendering the counter anyway would show\n an impossible \"1 / 0\". */}\n <span {...ctx.getStyles('counter', stylesApiProps)} aria-hidden=\"true\">\n {ctx.slides.length > 0 ? `${ctx.currentIndex + 1} / ${ctx.slides.length}` : null}\n </span>\n\n <div {...ctx.getStyles('toolbarGroup', stylesApiProps)}>\n {rightItems.map((item) => (\n <UnstyledButton\n key={item.key}\n {...ctx.getStyles('toolbarButton', stylesApiProps)}\n mod=\"reduce-motion\"\n aria-label={item.label}\n onClick={item.onClick}\n >\n {item.icon}\n </UnstyledButton>\n ))}\n </div>\n </Box>\n );\n});\n\nLightboxToolbar.classes = classes;\nLightboxToolbar.displayName = '@mantine/lightbox/LightboxToolbar';\n"],"mappings":";;;;;;;AAmCA,MAAa,kBAAkB,SAAiC,UAAU;CACxE,MAAM,EAAE,YAAY,WAAW,OAAO,QAAQ,MAAM,cAAc,GAAG,WAAW,SAC9E,mBACA,MACA,KACF;CAEA,MAAM,MAAM,mBAAmB;CAC/B,MAAM,iBAAiB;EAAE;EAAY;CAAO;CAC5C,MAAM,eAAe,IAAI,OAAO,IAAI;CAEpC,MAAM,eAA8B,CAAC;CAErC,IAAI,IAAI,gBACN,aAAa,KACX,4BAA4B,IAAI,kBAAkB,IAAI,mBAAmB,IAAI,MAAM,CACrF;CAGF,IAAI,IAAI,gBACN,aAAa,KACX,4BAA4B,IAAI,kBAAkB,IAAI,cAAc,IAAI,MAAM,CAChF;CAGF,IAAI,IAAI,gBAAgB,gBAAgB,aAAa,SAAS,UAC5D,aAAa,KAAK,0BAA0B,aAAa,KAAK,IAAI,MAAM,CAAC;CAG3E,aAAa,KAAK,uBAAuB,IAAI,SAAS,IAAI,MAAM,CAAC;CAEjE,MAAM,QACJ,OAAO,iBAAiB,aACpB,aAAa;EACX,QAAQ,IAAI;EACZ,cAAc,IAAI;EAClB,UAAU,IAAI;EACd,MAAM,IAAI;EACV,MAAM,IAAI;EACV,OAAO,IAAI;EACX,mBAAmB,IAAI;EACvB,kBAAkB,IAAI;EACtB,cAAc,IAAI;EAClB,kBAAkB,IAAI;EACtB,QAAQ,IAAI,UAAU;EACtB,YAAY,IAAI;EAChB,QAAQ,IAAI;CACd,CAAC,IACA,gBAAgB;CACvB,MAAM,YAAY,MAAM,QAAQ,SAAS,KAAK,aAAa,MAAM;CACjE,MAAM,aAAa,MAAM,QAAQ,SAAS,KAAK,aAAa,MAAM;CAElE,OACE,qBAAC,KAAD;EAAK,GAAI,IAAI,UAAU,WAAW;GAAE;GAAW;GAAO;GAAY;EAAO,CAAC;EAAG,GAAI;EAAjF,UAAA;GACE,oBAAC,OAAD;IAAK,GAAI,IAAI,UAAU,gBAAgB,cAAc;IAClD,UAAA,UAAU,KAAK,SACd,oBAAC,gBAAD;KAEE,GAAI,IAAI,UAAU,iBAAiB,cAAc;KACjD,KAAI;KACJ,cAAY,KAAK;KACjB,SAAS,KAAK;KAEb,UAAA,KAAK;IACQ,GAPT,KAAK,GAOI,CACjB;GACE,CAAA;GAIL,oBAAC,QAAD;IAAM,GAAI,IAAI,UAAU,WAAW,cAAc;IAAG,eAAY;IAC7D,UAAA,IAAI,OAAO,SAAS,IAAI,GAAG,IAAI,eAAe,EAAE,KAAK,IAAI,OAAO,WAAW;GACxE,CAAA;GAEN,oBAAC,OAAD;IAAK,GAAI,IAAI,UAAU,gBAAgB,cAAc;IAClD,UAAA,WAAW,KAAK,SACf,oBAAC,gBAAD;KAEE,GAAI,IAAI,UAAU,iBAAiB,cAAc;KACjD,KAAI;KACJ,cAAY,KAAK;KACjB,SAAS,KAAK;KAEb,UAAA,KAAK;IACQ,GAPT,KAAK,GAOI,CACjB;GACE,CAAA;EACF;;AAET,CAAC;AAED,gBAAgB,UAAUA;AAC1B,gBAAgB,cAAc"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { DEFAULT_LABELS } from "../default-labels.mjs";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region packages/@mantine/lightbox/src/LightboxToolbar/toolbar-items.tsx
|
|
5
|
+
function IconEnterFullscreen() {
|
|
6
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
7
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
8
|
+
viewBox: "0 0 24 24",
|
|
9
|
+
width: "20",
|
|
10
|
+
height: "20",
|
|
11
|
+
fill: "currentColor",
|
|
12
|
+
children: /* @__PURE__ */ jsx("path", { d: "M3 3h6v2H5v4H3V3zm12 0h6v6h-2V5h-4V3zM3 15h2v4h4v2H3v-6zm18 0v6h-6v-2h4v-4h2z" })
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function IconExitFullscreen() {
|
|
16
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
17
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
18
|
+
viewBox: "0 0 24 24",
|
|
19
|
+
width: "20",
|
|
20
|
+
height: "20",
|
|
21
|
+
fill: "currentColor",
|
|
22
|
+
children: /* @__PURE__ */ jsx("path", { d: "M9 3v6H3V7h4V3h2zm6 0h2v4h4v2h-6V3zM3 15h6v6H7v-4H3v-2zm12 0h6v2h-4v4h-2v-6z" })
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function IconThumbnails() {
|
|
26
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
27
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
28
|
+
viewBox: "0 0 24 24",
|
|
29
|
+
width: "20",
|
|
30
|
+
height: "20",
|
|
31
|
+
fill: "currentColor",
|
|
32
|
+
children: /* @__PURE__ */ jsx("path", { d: "M3 3h8v8H3V3zm0 10h8v8H3v-8zm10-10h8v8h-8V3zm0 10h8v8h-8v-8z" })
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function IconDownload() {
|
|
36
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
37
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
38
|
+
viewBox: "0 0 24 24",
|
|
39
|
+
width: "20",
|
|
40
|
+
height: "20",
|
|
41
|
+
fill: "currentColor",
|
|
42
|
+
children: /* @__PURE__ */ jsx("path", { d: "M12 16l-6-6h4V4h4v6h4l-6 6zm-8 2h16v2H4v-2z" })
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function IconClose() {
|
|
46
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
47
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
48
|
+
viewBox: "0 0 24 24",
|
|
49
|
+
width: "20",
|
|
50
|
+
height: "20",
|
|
51
|
+
fill: "currentColor",
|
|
52
|
+
children: /* @__PURE__ */ jsx("path", { d: "M18.3 5.7a1 1 0 0 0-1.4 0L12 10.6 7.1 5.7a1 1 0 0 0-1.4 1.4L10.6 12l-4.9 4.9a1 1 0 1 0 1.4 1.4L12 13.4l4.9 4.9a1 1 0 0 0 1.4-1.4L13.4 12l4.9-4.9a1 1 0 0 0 0-1.4z" })
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function createFullscreenToolbarItem(toggle, isFullscreen, labels = DEFAULT_LABELS) {
|
|
56
|
+
return {
|
|
57
|
+
key: "fullscreen",
|
|
58
|
+
icon: isFullscreen ? /* @__PURE__ */ jsx(IconExitFullscreen, {}) : /* @__PURE__ */ jsx(IconEnterFullscreen, {}),
|
|
59
|
+
label: isFullscreen ? labels.exitFullscreenLabel : labels.enterFullscreenLabel,
|
|
60
|
+
onClick: toggle,
|
|
61
|
+
position: "right"
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function createThumbnailsToolbarItem(toggle, visible, labels = DEFAULT_LABELS) {
|
|
65
|
+
return {
|
|
66
|
+
key: "thumbnails",
|
|
67
|
+
icon: /* @__PURE__ */ jsx(IconThumbnails, {}),
|
|
68
|
+
label: visible ? labels.hideThumbnailsLabel : labels.showThumbnailsLabel,
|
|
69
|
+
onClick: toggle,
|
|
70
|
+
position: "left"
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const ALLOWED_DOWNLOAD_PROTOCOLS = [
|
|
74
|
+
"http:",
|
|
75
|
+
"https:",
|
|
76
|
+
"blob:",
|
|
77
|
+
"data:"
|
|
78
|
+
];
|
|
79
|
+
function parseDownloadUrl(src) {
|
|
80
|
+
try {
|
|
81
|
+
const url = new URL(src, window.location.href);
|
|
82
|
+
return ALLOWED_DOWNLOAD_PROTOCOLS.includes(url.protocol) ? url : null;
|
|
83
|
+
} catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const downloadsInProgress = /* @__PURE__ */ new Set();
|
|
88
|
+
function getDownloadFileName(parsed) {
|
|
89
|
+
if (parsed.protocol === "data:") return "download";
|
|
90
|
+
const lastSegment = parsed.pathname.split("/").pop() || "";
|
|
91
|
+
try {
|
|
92
|
+
return decodeURIComponent(lastSegment) || "download";
|
|
93
|
+
} catch {
|
|
94
|
+
return lastSegment || "download";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function openInNewTab(src) {
|
|
98
|
+
const link = document.createElement("a");
|
|
99
|
+
link.href = src;
|
|
100
|
+
link.target = "_blank";
|
|
101
|
+
link.rel = "noopener noreferrer";
|
|
102
|
+
document.body.appendChild(link);
|
|
103
|
+
link.click();
|
|
104
|
+
link.remove();
|
|
105
|
+
}
|
|
106
|
+
function downloadFile(src) {
|
|
107
|
+
const parsed = parseDownloadUrl(src);
|
|
108
|
+
if (!parsed || downloadsInProgress.has(src)) return;
|
|
109
|
+
if ((parsed.protocol === "http:" || parsed.protocol === "https:") && parsed.origin !== window.location.origin) {
|
|
110
|
+
openInNewTab(src);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
downloadsInProgress.add(src);
|
|
114
|
+
fetch(src).then((res) => {
|
|
115
|
+
if (!res.ok) throw new Error(`Failed to download ${src}: ${res.status}`);
|
|
116
|
+
return res.blob();
|
|
117
|
+
}).then((blob) => {
|
|
118
|
+
const url = URL.createObjectURL(blob);
|
|
119
|
+
const link = document.createElement("a");
|
|
120
|
+
link.href = url;
|
|
121
|
+
link.download = getDownloadFileName(parsed);
|
|
122
|
+
document.body.appendChild(link);
|
|
123
|
+
link.click();
|
|
124
|
+
link.remove();
|
|
125
|
+
window.setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
126
|
+
}).catch(() => {
|
|
127
|
+
openInNewTab(src);
|
|
128
|
+
}).finally(() => {
|
|
129
|
+
downloadsInProgress.delete(src);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function createDownloadToolbarItem(src, labels = DEFAULT_LABELS) {
|
|
133
|
+
return {
|
|
134
|
+
key: "download",
|
|
135
|
+
icon: /* @__PURE__ */ jsx(IconDownload, {}),
|
|
136
|
+
label: labels.downloadLabel,
|
|
137
|
+
onClick: () => downloadFile(src),
|
|
138
|
+
position: "right"
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function createCloseToolbarItem(onClose, labels = DEFAULT_LABELS) {
|
|
142
|
+
return {
|
|
143
|
+
key: "close",
|
|
144
|
+
icon: /* @__PURE__ */ jsx(IconClose, {}),
|
|
145
|
+
label: labels.closeLabel,
|
|
146
|
+
onClick: onClose,
|
|
147
|
+
position: "right"
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
export { createCloseToolbarItem, createDownloadToolbarItem, createFullscreenToolbarItem, createThumbnailsToolbarItem };
|
|
152
|
+
|
|
153
|
+
//# sourceMappingURL=toolbar-items.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolbar-items.mjs","names":[],"sources":["../../src/LightboxToolbar/toolbar-items.tsx"],"sourcesContent":["import { DEFAULT_LABELS } from '../default-labels';\nimport type { LightboxLabels, ToolbarItem } from '../lightbox.types';\n\nfunction IconEnterFullscreen() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width=\"20\"\n height=\"20\"\n fill=\"currentColor\"\n >\n <path d=\"M3 3h6v2H5v4H3V3zm12 0h6v6h-2V5h-4V3zM3 15h2v4h4v2H3v-6zm18 0v6h-6v-2h4v-4h2z\" />\n </svg>\n );\n}\n\nfunction IconExitFullscreen() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width=\"20\"\n height=\"20\"\n fill=\"currentColor\"\n >\n <path d=\"M9 3v6H3V7h4V3h2zm6 0h2v4h4v2h-6V3zM3 15h6v6H7v-4H3v-2zm12 0h6v2h-4v4h-2v-6z\" />\n </svg>\n );\n}\n\nfunction IconThumbnails() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width=\"20\"\n height=\"20\"\n fill=\"currentColor\"\n >\n <path d=\"M3 3h8v8H3V3zm0 10h8v8H3v-8zm10-10h8v8h-8V3zm0 10h8v8h-8v-8z\" />\n </svg>\n );\n}\n\nfunction IconDownload() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width=\"20\"\n height=\"20\"\n fill=\"currentColor\"\n >\n <path d=\"M12 16l-6-6h4V4h4v6h4l-6 6zm-8 2h16v2H4v-2z\" />\n </svg>\n );\n}\n\nfunction IconClose() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width=\"20\"\n height=\"20\"\n fill=\"currentColor\"\n >\n <path d=\"M18.3 5.7a1 1 0 0 0-1.4 0L12 10.6 7.1 5.7a1 1 0 0 0-1.4 1.4L10.6 12l-4.9 4.9a1 1 0 1 0 1.4 1.4L12 13.4l4.9 4.9a1 1 0 0 0 1.4-1.4L13.4 12l4.9-4.9a1 1 0 0 0 0-1.4z\" />\n </svg>\n );\n}\n\nexport function createFullscreenToolbarItem(\n toggle: () => void,\n isFullscreen: boolean,\n labels: LightboxLabels = DEFAULT_LABELS\n): ToolbarItem {\n return {\n key: 'fullscreen',\n icon: isFullscreen ? <IconExitFullscreen /> : <IconEnterFullscreen />,\n label: isFullscreen ? labels.exitFullscreenLabel : labels.enterFullscreenLabel,\n onClick: toggle,\n position: 'right',\n };\n}\n\nexport function createThumbnailsToolbarItem(\n toggle: () => void,\n visible: boolean,\n labels: LightboxLabels = DEFAULT_LABELS\n): ToolbarItem {\n return {\n key: 'thumbnails',\n icon: <IconThumbnails />,\n label: visible ? labels.hideThumbnailsLabel : labels.showThumbnailsLabel,\n onClick: toggle,\n position: 'left',\n };\n}\n\nconst ALLOWED_DOWNLOAD_PROTOCOLS = ['http:', 'https:', 'blob:', 'data:'];\n\nfunction parseDownloadUrl(src: string): URL | null {\n try {\n const url = new URL(src, window.location.href);\n return ALLOWED_DOWNLOAD_PROTOCOLS.includes(url.protocol) ? url : null;\n } catch {\n return null;\n }\n}\n\nconst downloadsInProgress = new Set<string>();\n\nfunction getDownloadFileName(parsed: URL) {\n if (parsed.protocol === 'data:') {\n return 'download';\n }\n\n const lastSegment = parsed.pathname.split('/').pop() || '';\n\n try {\n return decodeURIComponent(lastSegment) || 'download';\n } catch {\n return lastSegment || 'download';\n }\n}\n\nfunction openInNewTab(src: string) {\n const link = document.createElement('a');\n link.href = src;\n link.target = '_blank';\n link.rel = 'noopener noreferrer';\n document.body.appendChild(link);\n link.click();\n link.remove();\n}\n\nfunction downloadFile(src: string) {\n const parsed = parseDownloadUrl(src);\n\n if (!parsed || downloadsInProgress.has(src)) {\n return;\n }\n\n // A cross-origin fetch fails unless the host sends CORS headers, and by the time it\n // rejects the user activation from the click is gone, so the fallback is popup-blocked.\n // Navigating straight away keeps the gesture. The `download` attribute is ignored for\n // cross-origin URLs anyway, so nothing is lost by skipping the blob round-trip.\n const isCrossOrigin =\n (parsed.protocol === 'http:' || parsed.protocol === 'https:') &&\n parsed.origin !== window.location.origin;\n\n if (isCrossOrigin) {\n openInNewTab(src);\n return;\n }\n\n downloadsInProgress.add(src);\n\n fetch(src)\n .then((res) => {\n // Without this an error page is happily turned into a blob and saved under the\n // media file name.\n if (!res.ok) {\n throw new Error(`Failed to download ${src}: ${res.status}`);\n }\n\n return res.blob();\n })\n .then((blob) => {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = getDownloadFileName(parsed);\n document.body.appendChild(link);\n link.click();\n link.remove();\n window.setTimeout(() => URL.revokeObjectURL(url), 1000);\n })\n .catch(() => {\n openInNewTab(src);\n })\n .finally(() => {\n downloadsInProgress.delete(src);\n });\n}\n\nexport function createDownloadToolbarItem(\n src: string,\n labels: LightboxLabels = DEFAULT_LABELS\n): ToolbarItem {\n return {\n key: 'download',\n icon: <IconDownload />,\n label: labels.downloadLabel,\n onClick: () => downloadFile(src),\n position: 'right',\n };\n}\n\nexport function createCloseToolbarItem(\n onClose: () => void,\n labels: LightboxLabels = DEFAULT_LABELS\n): ToolbarItem {\n return {\n key: 'close',\n icon: <IconClose />,\n label: labels.closeLabel,\n onClick: onClose,\n position: 'right',\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
//#region packages/@mantine/lightbox/src/default-labels.ts
|
|
3
|
+
const DEFAULT_LABELS = {
|
|
4
|
+
lightboxLabel: "Gallery",
|
|
5
|
+
slideLabel: (index, total) => `Slide ${index} of ${total}`,
|
|
6
|
+
slidesLabel: "Slides",
|
|
7
|
+
previousSlideLabel: "Previous slide",
|
|
8
|
+
nextSlideLabel: "Next slide",
|
|
9
|
+
thumbnailLabel: (index) => `Go to slide ${index}`,
|
|
10
|
+
enterFullscreenLabel: "Enter fullscreen",
|
|
11
|
+
exitFullscreenLabel: "Exit fullscreen",
|
|
12
|
+
showThumbnailsLabel: "Show thumbnails",
|
|
13
|
+
hideThumbnailsLabel: "Hide thumbnails",
|
|
14
|
+
downloadLabel: "Download",
|
|
15
|
+
closeLabel: "Close"
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { DEFAULT_LABELS };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=default-labels.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-labels.mjs","names":[],"sources":["../src/default-labels.ts"],"sourcesContent":["import type { LightboxLabels } from './lightbox.types';\n\nexport const DEFAULT_LABELS: LightboxLabels = {\n lightboxLabel: 'Gallery',\n slideLabel: (index, total) => `Slide ${index} of ${total}`,\n slidesLabel: 'Slides',\n previousSlideLabel: 'Previous slide',\n nextSlideLabel: 'Next slide',\n thumbnailLabel: (index) => `Go to slide ${index}`,\n enterFullscreenLabel: 'Enter fullscreen',\n exitFullscreenLabel: 'Exit fullscreen',\n showThumbnailsLabel: 'Show thumbnails',\n hideThumbnailsLabel: 'Hide thumbnails',\n downloadLabel: 'Download',\n closeLabel: 'Close',\n};\n"],"mappings":";;AAEA,MAAa,iBAAiC;CAC5C,eAAe;CACf,aAAa,OAAO,UAAU,SAAS,MAAM,MAAM;CACnD,aAAa;CACb,oBAAoB;CACpB,gBAAgB;CAChB,iBAAiB,UAAU,eAAe;CAC1C,sBAAsB;CACtB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,eAAe;CACf,YAAY;AACd"}
|