@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.
Files changed (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/cjs/Lightbox.cjs +56 -0
  4. package/cjs/Lightbox.cjs.map +1 -0
  5. package/cjs/Lightbox.module.cjs +30 -0
  6. package/cjs/Lightbox.module.cjs.map +1 -0
  7. package/cjs/LightboxCaption/LightboxCaption.cjs +30 -0
  8. package/cjs/LightboxCaption/LightboxCaption.cjs.map +1 -0
  9. package/cjs/LightboxCloseButton/LightboxCloseButton.cjs +32 -0
  10. package/cjs/LightboxCloseButton/LightboxCloseButton.cjs.map +1 -0
  11. package/cjs/LightboxNavigation/LightboxNavigation.cjs +105 -0
  12. package/cjs/LightboxNavigation/LightboxNavigation.cjs.map +1 -0
  13. package/cjs/LightboxProvider/LightboxProvider.cjs +29 -0
  14. package/cjs/LightboxProvider/LightboxProvider.cjs.map +1 -0
  15. package/cjs/LightboxRoot/LightboxRoot.cjs +407 -0
  16. package/cjs/LightboxRoot/LightboxRoot.cjs.map +1 -0
  17. package/cjs/LightboxSlide/ImageSlide.cjs +27 -0
  18. package/cjs/LightboxSlide/ImageSlide.cjs.map +1 -0
  19. package/cjs/LightboxSlide/LightboxSlide.cjs +55 -0
  20. package/cjs/LightboxSlide/LightboxSlide.cjs.map +1 -0
  21. package/cjs/LightboxSlide/VideoSlide.cjs +42 -0
  22. package/cjs/LightboxSlide/VideoSlide.cjs.map +1 -0
  23. package/cjs/LightboxSlides/LightboxSlides.cjs +56 -0
  24. package/cjs/LightboxSlides/LightboxSlides.cjs.map +1 -0
  25. package/cjs/LightboxThumbnails/LightboxThumbnails.cjs +74 -0
  26. package/cjs/LightboxThumbnails/LightboxThumbnails.cjs.map +1 -0
  27. package/cjs/LightboxToolbar/LightboxToolbar.cjs +80 -0
  28. package/cjs/LightboxToolbar/LightboxToolbar.cjs.map +1 -0
  29. package/cjs/LightboxToolbar/toolbar-items.cjs +156 -0
  30. package/cjs/LightboxToolbar/toolbar-items.cjs.map +1 -0
  31. package/cjs/_virtual/_rolldown/runtime.cjs +24 -0
  32. package/cjs/default-labels.cjs +20 -0
  33. package/cjs/default-labels.cjs.map +1 -0
  34. package/cjs/hooks/use-lightbox-keyboard.cjs +107 -0
  35. package/cjs/hooks/use-lightbox-keyboard.cjs.map +1 -0
  36. package/cjs/hooks/use-lightbox-lock-scroll.cjs +30 -0
  37. package/cjs/hooks/use-lightbox-lock-scroll.cjs.map +1 -0
  38. package/cjs/hooks/use-lightbox-swipe-close.cjs +38 -0
  39. package/cjs/hooks/use-lightbox-swipe-close.cjs.map +1 -0
  40. package/cjs/hooks/use-lightbox-zoom.cjs +257 -0
  41. package/cjs/hooks/use-lightbox-zoom.cjs.map +1 -0
  42. package/cjs/index.cjs +34 -0
  43. package/cjs/lightbox.context.cjs +8 -0
  44. package/cjs/lightbox.context.cjs.map +1 -0
  45. package/cjs/lightbox.store.cjs +90 -0
  46. package/cjs/lightbox.store.cjs.map +1 -0
  47. package/esm/Lightbox.mjs +56 -0
  48. package/esm/Lightbox.mjs.map +1 -0
  49. package/esm/Lightbox.module.mjs +30 -0
  50. package/esm/Lightbox.module.mjs.map +1 -0
  51. package/esm/LightboxCaption/LightboxCaption.mjs +30 -0
  52. package/esm/LightboxCaption/LightboxCaption.mjs.map +1 -0
  53. package/esm/LightboxCloseButton/LightboxCloseButton.mjs +32 -0
  54. package/esm/LightboxCloseButton/LightboxCloseButton.mjs.map +1 -0
  55. package/esm/LightboxNavigation/LightboxNavigation.mjs +105 -0
  56. package/esm/LightboxNavigation/LightboxNavigation.mjs.map +1 -0
  57. package/esm/LightboxProvider/LightboxProvider.mjs +29 -0
  58. package/esm/LightboxProvider/LightboxProvider.mjs.map +1 -0
  59. package/esm/LightboxRoot/LightboxRoot.mjs +404 -0
  60. package/esm/LightboxRoot/LightboxRoot.mjs.map +1 -0
  61. package/esm/LightboxSlide/ImageSlide.mjs +27 -0
  62. package/esm/LightboxSlide/ImageSlide.mjs.map +1 -0
  63. package/esm/LightboxSlide/LightboxSlide.mjs +55 -0
  64. package/esm/LightboxSlide/LightboxSlide.mjs.map +1 -0
  65. package/esm/LightboxSlide/VideoSlide.mjs +42 -0
  66. package/esm/LightboxSlide/VideoSlide.mjs.map +1 -0
  67. package/esm/LightboxSlides/LightboxSlides.mjs +56 -0
  68. package/esm/LightboxSlides/LightboxSlides.mjs.map +1 -0
  69. package/esm/LightboxThumbnails/LightboxThumbnails.mjs +72 -0
  70. package/esm/LightboxThumbnails/LightboxThumbnails.mjs.map +1 -0
  71. package/esm/LightboxToolbar/LightboxToolbar.mjs +80 -0
  72. package/esm/LightboxToolbar/LightboxToolbar.mjs.map +1 -0
  73. package/esm/LightboxToolbar/toolbar-items.mjs +153 -0
  74. package/esm/LightboxToolbar/toolbar-items.mjs.map +1 -0
  75. package/esm/default-labels.mjs +20 -0
  76. package/esm/default-labels.mjs.map +1 -0
  77. package/esm/hooks/use-lightbox-keyboard.mjs +107 -0
  78. package/esm/hooks/use-lightbox-keyboard.mjs.map +1 -0
  79. package/esm/hooks/use-lightbox-lock-scroll.mjs +30 -0
  80. package/esm/hooks/use-lightbox-lock-scroll.mjs.map +1 -0
  81. package/esm/hooks/use-lightbox-swipe-close.mjs +38 -0
  82. package/esm/hooks/use-lightbox-swipe-close.mjs.map +1 -0
  83. package/esm/hooks/use-lightbox-zoom.mjs +257 -0
  84. package/esm/hooks/use-lightbox-zoom.mjs.map +1 -0
  85. package/esm/index.mjs +14 -0
  86. package/esm/lightbox.context.mjs +8 -0
  87. package/esm/lightbox.context.mjs.map +1 -0
  88. package/esm/lightbox.store.mjs +79 -0
  89. package/esm/lightbox.store.mjs.map +1 -0
  90. package/lib/Lightbox.d.ts +63 -0
  91. package/lib/LightboxCaption/LightboxCaption.d.ts +18 -0
  92. package/lib/LightboxCloseButton/LightboxCloseButton.d.ts +16 -0
  93. package/lib/LightboxNavigation/LightboxNavigation.d.ts +16 -0
  94. package/lib/LightboxProvider/LightboxProvider.d.ts +19 -0
  95. package/lib/LightboxRoot/LightboxRoot.d.ts +88 -0
  96. package/lib/LightboxSlide/ImageSlide.d.ts +12 -0
  97. package/lib/LightboxSlide/LightboxSlide.d.ts +25 -0
  98. package/lib/LightboxSlide/VideoSlide.d.ts +12 -0
  99. package/lib/LightboxSlides/LightboxSlides.d.ts +20 -0
  100. package/lib/LightboxThumbnails/LightboxThumbnails.d.ts +16 -0
  101. package/lib/LightboxToolbar/LightboxToolbar.d.ts +19 -0
  102. package/lib/LightboxToolbar/toolbar-items.d.ts +5 -0
  103. package/lib/default-labels.d.ts +2 -0
  104. package/lib/hooks/use-lightbox-keyboard.d.ts +15 -0
  105. package/lib/hooks/use-lightbox-lock-scroll.d.ts +7 -0
  106. package/lib/hooks/use-lightbox-swipe-close.d.ts +10 -0
  107. package/lib/hooks/use-lightbox-zoom.d.ts +33 -0
  108. package/lib/index.d.mts +67 -0
  109. package/lib/index.d.ts +67 -0
  110. package/lib/lightbox.context.d.ts +36 -0
  111. package/lib/lightbox.store.d.ts +66 -0
  112. package/lib/lightbox.types.d.ts +131 -0
  113. package/lib/test-utils.d.ts +7 -0
  114. package/package.json +63 -0
  115. package/styles.css +262 -0
  116. package/styles.layer.css +263 -0
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ const require_lightbox_context = require("../lightbox.context.cjs");
3
+ const require_Lightbox_module = require("../Lightbox.module.cjs");
4
+ const require_use_lightbox_swipe_close = require("../hooks/use-lightbox-swipe-close.cjs");
5
+ let _mantine_core = require("@mantine/core");
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ let _mantine_hooks = require("@mantine/hooks");
8
+ //#region packages/@mantine/lightbox/src/LightboxSlides/LightboxSlides.tsx
9
+ const LightboxSlides = (0, _mantine_core.factory)((props) => {
10
+ const { classNames, className, style, styles, vars, emblaRef, children, onTouchStart, onTouchEnd, ...others } = (0, _mantine_core.useProps)("LightboxSlides", null, props);
11
+ const ctx = require_lightbox_context.useLightboxContext();
12
+ const stylesApiProps = {
13
+ classNames,
14
+ styles
15
+ };
16
+ const viewportRef = (0, _mantine_hooks.useMergedRef)(ctx.emblaRef, emblaRef);
17
+ const { handleTouchStart, handleTouchEnd } = require_use_lightbox_swipe_close.useLightboxSwipeClose({
18
+ enabled: ctx.closeOnSwipeDown,
19
+ onClose: ctx.onClose,
20
+ isZoomed: ctx.zoomState.isZoomed
21
+ });
22
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.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__ */ (0, react_jsx_runtime.jsx)("div", {
42
+ ...ctx.getStyles("slidesViewport", stylesApiProps),
43
+ ref: viewportRef,
44
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
45
+ ...ctx.getStyles("slidesContainer", stylesApiProps),
46
+ children
47
+ })
48
+ })
49
+ });
50
+ });
51
+ LightboxSlides.classes = require_Lightbox_module.default;
52
+ LightboxSlides.displayName = "@mantine/lightbox/LightboxSlides";
53
+ //#endregion
54
+ exports.LightboxSlides = LightboxSlides;
55
+
56
+ //# sourceMappingURL=LightboxSlides.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LightboxSlides.cjs","names":["factory","useProps","useLightboxContext","useMergedRef","useLightboxSwipeClose","Box","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,kBAAA,GAAiBA,cAAAA,QAAAA,EAAgC,UAAU;CACtE,MAAM,EACJ,YACA,WACA,OACA,QACA,MACA,UACA,UACA,cACA,YACA,GAAG,YAAA,GACDC,cAAAA,SAAAA,CAAS,kBAAkB,MAAM,KAAK;CAE1C,MAAM,MAAMC,yBAAAA,mBAAmB;CAC/B,MAAM,iBAAiB;EAAE;EAAY;CAAO;CAE5C,MAAM,eAAA,GAAcC,eAAAA,aAAAA,CAAa,IAAI,UAAU,QAAQ;CAEvD,MAAM,EAAE,kBAAkB,mBAAmBC,iCAAAA,sBAAsB;EACjE,SAAS,IAAI;EACb,SAAS,IAAI;EACb,UAAU,IAAI,UAAU;CAC1B,CAAC;CAED,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,cAAAA,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,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAK,GAAI,IAAI,UAAU,kBAAkB,cAAc;GAAG,KAAK;GAC7D,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,GAAI,IAAI,UAAU,mBAAmB,cAAc;IAAI;GAAc,CAAA;EACvE,CAAA;CACF,CAAA;AAET,CAAC;AAED,eAAe,UAAUC,wBAAAA;AACzB,eAAe,cAAc"}
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
3
+ const require_lightbox_context = require("../lightbox.context.cjs");
4
+ const require_Lightbox_module = require("../Lightbox.module.cjs");
5
+ let _mantine_core = require("@mantine/core");
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ let react = require("react");
8
+ let embla_carousel_react = require("embla-carousel-react");
9
+ embla_carousel_react = require_runtime.__toESM(embla_carousel_react);
10
+ //#region packages/@mantine/lightbox/src/LightboxThumbnails/LightboxThumbnails.tsx
11
+ const LightboxThumbnails = (0, _mantine_core.factory)((props) => {
12
+ const { classNames, className, style, styles, vars, ...others } = (0, _mantine_core.useProps)("LightboxThumbnails", null, props);
13
+ const ctx = require_lightbox_context.useLightboxContext();
14
+ const stylesApiProps = {
15
+ classNames,
16
+ styles
17
+ };
18
+ const { dir } = (0, _mantine_core.useDirection)();
19
+ const [thumbsRef, thumbsEmbla] = (0, embla_carousel_react.default)({
20
+ containScroll: "keepSnaps",
21
+ dragFree: true,
22
+ direction: dir,
23
+ active: ctx.withThumbnails
24
+ });
25
+ (0, react.useEffect)(() => {
26
+ if (thumbsEmbla) thumbsEmbla.scrollTo(ctx.currentIndex);
27
+ }, [ctx.currentIndex, thumbsEmbla]);
28
+ if (!ctx.withThumbnails) return null;
29
+ const thumbnails = ctx.slides.map((slide, index) => {
30
+ const hasCustomThumb = slide.type === "custom" && slide.renderThumb;
31
+ const thumbSrc = slide.thumbSrc ?? (slide.type === "video" ? slide.poster : void 0) ?? (slide.type !== "custom" ? slide.src : void 0);
32
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.UnstyledButton, {
33
+ ...ctx.getStyles("thumbnail", stylesApiProps),
34
+ mod: "reduce-motion",
35
+ "data-active": index === ctx.currentIndex || void 0,
36
+ "aria-label": ctx.labels.thumbnailLabel(index + 1, ctx.slides.length),
37
+ "aria-current": index === ctx.currentIndex || void 0,
38
+ onClick: () => ctx.setIndex(index),
39
+ children: hasCustomThumb ? slide.renderThumb() : thumbSrc ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
40
+ ...ctx.getStyles("thumbnailImage", stylesApiProps),
41
+ src: thumbSrc,
42
+ alt: "",
43
+ loading: "lazy",
44
+ draggable: false
45
+ }) : null
46
+ }, index);
47
+ });
48
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.Collapse, {
49
+ expanded: ctx.thumbnailsVisible,
50
+ transitionDuration: ctx.transitionDuration,
51
+ keepMounted: false,
52
+ ...ctx.getStyles("thumbnails", {
53
+ className,
54
+ style,
55
+ classNames,
56
+ styles
57
+ }),
58
+ ...others,
59
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
60
+ ...ctx.getStyles("thumbnailsViewport", stylesApiProps),
61
+ ref: thumbsRef,
62
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
63
+ ...ctx.getStyles("thumbnailsContainer", stylesApiProps),
64
+ children: thumbnails
65
+ })
66
+ })
67
+ });
68
+ });
69
+ LightboxThumbnails.classes = require_Lightbox_module.default;
70
+ LightboxThumbnails.displayName = "@mantine/lightbox/LightboxThumbnails";
71
+ //#endregion
72
+ exports.LightboxThumbnails = LightboxThumbnails;
73
+
74
+ //# sourceMappingURL=LightboxThumbnails.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LightboxThumbnails.cjs","names":["factory","useProps","useLightboxContext","useDirection","useEmblaCarousel","UnstyledButton","Collapse","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,sBAAA,GAAqBA,cAAAA,QAAAA,EAAoC,UAAU;CAC9E,MAAM,EAAE,YAAY,WAAW,OAAO,QAAQ,MAAM,GAAG,YAAA,GAAWC,cAAAA,SAAAA,CAChE,sBACA,MACA,KACF;CAEA,MAAM,MAAMC,yBAAAA,mBAAmB;CAC/B,MAAM,iBAAiB;EAAE;EAAY;CAAO;CAE5C,MAAM,EAAE,SAAA,GAAQC,cAAAA,aAAAA,CAAa;CAK7B,MAAM,CAAC,WAAW,gBAAA,GAAeC,qBAAAA,QAAAA,CAAiB;EAChD,eAAe;EACf,UAAU;EACV,WAAW;EACX,QAAQ,IAAI;CACd,CAAC;CAED,CAAA,GAAA,MAAA,UAAA,OAAgB;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,iBAAA,GAAA,kBAAA,IAAA,CAACC,cAAAA,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,iBAAA,GAAA,kBAAA,IAAA,CAAC,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,iBAAA,GAAA,kBAAA,IAAA,CAACC,cAAAA,UAAD;EACE,UAAU,IAAI;EACd,oBAAoB,IAAI;EACxB,aAAa;EACb,GAAI,IAAI,UAAU,cAAc;GAAE;GAAW;GAAO;GAAY;EAAO,CAAC;EACxE,GAAI;EAEJ,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAK,GAAI,IAAI,UAAU,sBAAsB,cAAc;GAAG,KAAK;GACjE,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,GAAI,IAAI,UAAU,uBAAuB,cAAc;IAAI,UAAA;GAAgB,CAAA;EAC7E,CAAA;CACG,CAAA;AAEd,CAAC;AAED,mBAAmB,UAAUC,wBAAAA;AAC7B,mBAAmB,cAAc"}
@@ -0,0 +1,80 @@
1
+ "use client";
2
+ const require_lightbox_context = require("../lightbox.context.cjs");
3
+ const require_Lightbox_module = require("../Lightbox.module.cjs");
4
+ const require_toolbar_items = require("./toolbar-items.cjs");
5
+ let _mantine_core = require("@mantine/core");
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ //#region packages/@mantine/lightbox/src/LightboxToolbar/LightboxToolbar.tsx
8
+ const LightboxToolbar = (0, _mantine_core.factory)((props) => {
9
+ const { classNames, className, style, styles, vars, toolbarItems, ...others } = (0, _mantine_core.useProps)("LightboxToolbar", null, props);
10
+ const ctx = require_lightbox_context.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(require_toolbar_items.createThumbnailsToolbarItem(ctx.toggleThumbnails, ctx.thumbnailsVisible, ctx.labels));
18
+ if (ctx.withFullscreen) defaultItems.push(require_toolbar_items.createFullscreenToolbarItem(ctx.toggleFullscreen, ctx.isFullscreen, ctx.labels));
19
+ if (ctx.withDownload && currentSlide && currentSlide.type !== "custom") defaultItems.push(require_toolbar_items.createDownloadToolbarItem(currentSlide.src, ctx.labels));
20
+ defaultItems.push(require_toolbar_items.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__ */ (0, react_jsx_runtime.jsxs)(_mantine_core.Box, {
39
+ ...ctx.getStyles("toolbar", {
40
+ className,
41
+ style,
42
+ classNames,
43
+ styles
44
+ }),
45
+ ...others,
46
+ children: [
47
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
48
+ ...ctx.getStyles("toolbarGroup", stylesApiProps),
49
+ children: leftItems.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.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__ */ (0, react_jsx_runtime.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__ */ (0, react_jsx_runtime.jsx)("div", {
63
+ ...ctx.getStyles("toolbarGroup", stylesApiProps),
64
+ children: rightItems.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mantine_core.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 = require_Lightbox_module.default;
76
+ LightboxToolbar.displayName = "@mantine/lightbox/LightboxToolbar";
77
+ //#endregion
78
+ exports.LightboxToolbar = LightboxToolbar;
79
+
80
+ //# sourceMappingURL=LightboxToolbar.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LightboxToolbar.cjs","names":["factory","useProps","useLightboxContext","createThumbnailsToolbarItem","createFullscreenToolbarItem","createDownloadToolbarItem","createCloseToolbarItem","Box","UnstyledButton","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,mBAAA,GAAkBA,cAAAA,QAAAA,EAAiC,UAAU;CACxE,MAAM,EAAE,YAAY,WAAW,OAAO,QAAQ,MAAM,cAAc,GAAG,YAAA,GAAWC,cAAAA,SAAAA,CAC9E,mBACA,MACA,KACF;CAEA,MAAM,MAAMC,yBAAAA,mBAAmB;CAC/B,MAAM,iBAAiB;EAAE;EAAY;CAAO;CAC5C,MAAM,eAAe,IAAI,OAAO,IAAI;CAEpC,MAAM,eAA8B,CAAC;CAErC,IAAI,IAAI,gBACN,aAAa,KACXC,sBAAAA,4BAA4B,IAAI,kBAAkB,IAAI,mBAAmB,IAAI,MAAM,CACrF;CAGF,IAAI,IAAI,gBACN,aAAa,KACXC,sBAAAA,4BAA4B,IAAI,kBAAkB,IAAI,cAAc,IAAI,MAAM,CAChF;CAGF,IAAI,IAAI,gBAAgB,gBAAgB,aAAa,SAAS,UAC5D,aAAa,KAAKC,sBAAAA,0BAA0B,aAAa,KAAK,IAAI,MAAM,CAAC;CAG3E,aAAa,KAAKC,sBAAAA,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,iBAAA,GAAA,kBAAA,KAAA,CAACC,cAAAA,KAAD;EAAK,GAAI,IAAI,UAAU,WAAW;GAAE;GAAW;GAAO;GAAY;EAAO,CAAC;EAAG,GAAI;EAAjF,UAAA;GACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,GAAI,IAAI,UAAU,gBAAgB,cAAc;IAClD,UAAA,UAAU,KAAK,SACd,iBAAA,GAAA,kBAAA,IAAA,CAACC,cAAAA,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,iBAAA,GAAA,kBAAA,IAAA,CAAC,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,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,GAAI,IAAI,UAAU,gBAAgB,cAAc;IAClD,UAAA,WAAW,KAAK,SACf,iBAAA,GAAA,kBAAA,IAAA,CAACA,cAAAA,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,UAAUC,wBAAAA;AAC1B,gBAAgB,cAAc"}
@@ -0,0 +1,156 @@
1
+ "use client";
2
+ const require_default_labels = require("../default-labels.cjs");
3
+ let react_jsx_runtime = require("react/jsx-runtime");
4
+ //#region packages/@mantine/lightbox/src/LightboxToolbar/toolbar-items.tsx
5
+ function IconEnterFullscreen() {
6
+ return /* @__PURE__ */ (0, react_jsx_runtime.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__ */ (0, react_jsx_runtime.jsx)("path", { d: "M3 3h6v2H5v4H3V3zm12 0h6v6h-2V5h-4V3zM3 15h2v4h4v2H3v-6zm18 0v6h-6v-2h4v-4h2z" })
13
+ });
14
+ }
15
+ function IconExitFullscreen() {
16
+ return /* @__PURE__ */ (0, react_jsx_runtime.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__ */ (0, react_jsx_runtime.jsx)("path", { d: "M9 3v6H3V7h4V3h2zm6 0h2v4h4v2h-6V3zM3 15h6v6H7v-4H3v-2zm12 0h6v2h-4v4h-2v-6z" })
23
+ });
24
+ }
25
+ function IconThumbnails() {
26
+ return /* @__PURE__ */ (0, react_jsx_runtime.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__ */ (0, react_jsx_runtime.jsx)("path", { d: "M3 3h8v8H3V3zm0 10h8v8H3v-8zm10-10h8v8h-8V3zm0 10h8v8h-8v-8z" })
33
+ });
34
+ }
35
+ function IconDownload() {
36
+ return /* @__PURE__ */ (0, react_jsx_runtime.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__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12 16l-6-6h4V4h4v6h4l-6 6zm-8 2h16v2H4v-2z" })
43
+ });
44
+ }
45
+ function IconClose() {
46
+ return /* @__PURE__ */ (0, react_jsx_runtime.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__ */ (0, react_jsx_runtime.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 = require_default_labels.DEFAULT_LABELS) {
56
+ return {
57
+ key: "fullscreen",
58
+ icon: isFullscreen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExitFullscreen, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconEnterFullscreen, {}),
59
+ label: isFullscreen ? labels.exitFullscreenLabel : labels.enterFullscreenLabel,
60
+ onClick: toggle,
61
+ position: "right"
62
+ };
63
+ }
64
+ function createThumbnailsToolbarItem(toggle, visible, labels = require_default_labels.DEFAULT_LABELS) {
65
+ return {
66
+ key: "thumbnails",
67
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.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 = require_default_labels.DEFAULT_LABELS) {
133
+ return {
134
+ key: "download",
135
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconDownload, {}),
136
+ label: labels.downloadLabel,
137
+ onClick: () => downloadFile(src),
138
+ position: "right"
139
+ };
140
+ }
141
+ function createCloseToolbarItem(onClose, labels = require_default_labels.DEFAULT_LABELS) {
142
+ return {
143
+ key: "close",
144
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconClose, {}),
145
+ label: labels.closeLabel,
146
+ onClick: onClose,
147
+ position: "right"
148
+ };
149
+ }
150
+ //#endregion
151
+ exports.createCloseToolbarItem = createCloseToolbarItem;
152
+ exports.createDownloadToolbarItem = createDownloadToolbarItem;
153
+ exports.createFullscreenToolbarItem = createFullscreenToolbarItem;
154
+ exports.createThumbnailsToolbarItem = createThumbnailsToolbarItem;
155
+
156
+ //# sourceMappingURL=toolbar-items.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar-items.cjs","names":["DEFAULT_LABELS"],"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,24 @@
1
+ "use client";
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ exports.__toESM = __toESM;
@@ -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
+ exports.DEFAULT_LABELS = DEFAULT_LABELS;
19
+
20
+ //# sourceMappingURL=default-labels.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-labels.cjs","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"}
@@ -0,0 +1,107 @@
1
+ "use client";
2
+ let react = require("react");
3
+ //#region packages/@mantine/lightbox/src/hooks/use-lightbox-keyboard.ts
4
+ /** Elements that consume typing wherever they are, including the lightbox chrome */
5
+ const TEXT_ENTRY_SELECTOR = "input, textarea, select, video, audio, [contenteditable]:not([contenteditable=\"false\"])";
6
+ /**
7
+ * Elements that consume arrow keys and letter shortcuts only inside slide content – the
8
+ * lightbox toolbar and navigation are buttons too, and keyboard shortcuts have to keep
9
+ * working while one of them has focus.
10
+ */
11
+ const SLIDE_WIDGET_SELECTOR = [
12
+ "button",
13
+ "a[href]",
14
+ "[role=\"button\"]",
15
+ "[role=\"link\"]",
16
+ "[role=\"checkbox\"]",
17
+ "[role=\"radio\"]",
18
+ "[role=\"menuitem\"]",
19
+ "[role=\"option\"]",
20
+ "[role=\"slider\"]",
21
+ "[role=\"spinbutton\"]",
22
+ "[role=\"switch\"]",
23
+ "[role=\"tab\"]",
24
+ "[role=\"textbox\"]",
25
+ "[role=\"combobox\"]",
26
+ "[role=\"listbox\"]",
27
+ "[role=\"menu\"]",
28
+ "[role=\"menubar\"]",
29
+ "[role=\"tablist\"]",
30
+ "[role=\"tree\"]",
31
+ "[role=\"treeitem\"]",
32
+ "[role=\"grid\"]",
33
+ "[role=\"gridcell\"]"
34
+ ].join(", ");
35
+ const ZOOM_PAN_STEP = 50;
36
+ function useLightboxKeyboard({ opened, enabled, dir, onClose, onNext, onPrev, onToggleFullscreen, onToggleThumbnails, onToggleZoom, onZoomPan }) {
37
+ (0, react.useEffect)(() => {
38
+ if (!opened) return;
39
+ const onLeadingArrow = dir === "rtl" ? onNext : onPrev;
40
+ const onTrailingArrow = dir === "rtl" ? onPrev : onNext;
41
+ const handler = (event) => {
42
+ if (event.defaultPrevented) return;
43
+ if (event.key === "Escape") {
44
+ event.preventDefault();
45
+ onClose();
46
+ return;
47
+ }
48
+ if (!enabled || event.ctrlKey || event.metaKey || event.altKey) return;
49
+ if (event.target instanceof Element) {
50
+ if (event.target.closest(TEXT_ENTRY_SELECTOR)) return;
51
+ if (event.target.closest("[data-lightbox-slide]") && event.target.closest(SLIDE_WIDGET_SELECTOR)) return;
52
+ }
53
+ switch (event.key) {
54
+ case "ArrowLeft":
55
+ event.preventDefault();
56
+ if (!onZoomPan?.(ZOOM_PAN_STEP, 0)) onLeadingArrow();
57
+ break;
58
+ case "ArrowRight":
59
+ event.preventDefault();
60
+ if (!onZoomPan?.(-50, 0)) onTrailingArrow();
61
+ break;
62
+ case "ArrowUp":
63
+ if (onZoomPan?.(0, ZOOM_PAN_STEP)) event.preventDefault();
64
+ break;
65
+ case "ArrowDown":
66
+ if (onZoomPan?.(0, -50)) event.preventDefault();
67
+ break;
68
+ case "f":
69
+ case "F":
70
+ if (onToggleFullscreen) {
71
+ event.preventDefault();
72
+ onToggleFullscreen();
73
+ }
74
+ break;
75
+ case "t":
76
+ case "T":
77
+ if (onToggleThumbnails) {
78
+ event.preventDefault();
79
+ onToggleThumbnails();
80
+ }
81
+ break;
82
+ case "z":
83
+ case "Z": if (onToggleZoom) {
84
+ event.preventDefault();
85
+ onToggleZoom();
86
+ }
87
+ }
88
+ };
89
+ document.addEventListener("keydown", handler);
90
+ return () => document.removeEventListener("keydown", handler);
91
+ }, [
92
+ opened,
93
+ enabled,
94
+ dir,
95
+ onClose,
96
+ onNext,
97
+ onPrev,
98
+ onToggleFullscreen,
99
+ onToggleThumbnails,
100
+ onToggleZoom,
101
+ onZoomPan
102
+ ]);
103
+ }
104
+ //#endregion
105
+ exports.useLightboxKeyboard = useLightboxKeyboard;
106
+
107
+ //# sourceMappingURL=use-lightbox-keyboard.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-lightbox-keyboard.cjs","names":[],"sources":["../../src/hooks/use-lightbox-keyboard.ts"],"sourcesContent":["import { useEffect } from 'react';\n\ninterface UseLightboxKeyboardInput {\n opened: boolean;\n enabled: boolean;\n /** Text direction of the lightbox, arrow keys follow it the same way the navigation buttons do */\n dir: 'ltr' | 'rtl';\n onClose: () => void;\n onNext: () => void;\n onPrev: () => void;\n onToggleFullscreen?: () => void;\n onToggleThumbnails?: () => void;\n onToggleZoom?: () => void;\n onZoomPan?: (deltaX: number, deltaY: number) => boolean;\n}\n\n/** Elements that consume typing wherever they are, including the lightbox chrome */\nconst TEXT_ENTRY_SELECTOR =\n 'input, textarea, select, video, audio, [contenteditable]:not([contenteditable=\"false\"])';\n\n/**\n * Elements that consume arrow keys and letter shortcuts only inside slide content – the\n * lightbox toolbar and navigation are buttons too, and keyboard shortcuts have to keep\n * working while one of them has focus.\n */\nconst SLIDE_WIDGET_SELECTOR = [\n 'button',\n 'a[href]',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"menuitem\"]',\n '[role=\"option\"]',\n '[role=\"slider\"]',\n '[role=\"spinbutton\"]',\n '[role=\"switch\"]',\n '[role=\"tab\"]',\n '[role=\"textbox\"]',\n '[role=\"combobox\"]',\n '[role=\"listbox\"]',\n '[role=\"menu\"]',\n '[role=\"menubar\"]',\n '[role=\"tablist\"]',\n '[role=\"tree\"]',\n '[role=\"treeitem\"]',\n '[role=\"grid\"]',\n '[role=\"gridcell\"]',\n].join(', ');\n\nconst ZOOM_PAN_STEP = 50;\n\nexport function useLightboxKeyboard({\n opened,\n enabled,\n dir,\n onClose,\n onNext,\n onPrev,\n onToggleFullscreen,\n onToggleThumbnails,\n onToggleZoom,\n onZoomPan,\n}: UseLightboxKeyboardInput) {\n useEffect(() => {\n if (!opened) {\n return undefined;\n }\n\n // Slides advance along the reading direction, so in RTL the next slide is the one to the\n // left – the arrow keys follow the same rule as the navigation chevrons, which are\n // already mirrored. Zoom panning stays physical: an arrow always moves the image the way\n // it points.\n const onLeadingArrow = dir === 'rtl' ? onNext : onPrev;\n const onTrailingArrow = dir === 'rtl' ? onPrev : onNext;\n\n const handler = (event: KeyboardEvent) => {\n if (event.defaultPrevented) {\n return;\n }\n\n if (event.key === 'Escape') {\n event.preventDefault();\n onClose();\n return;\n }\n\n if (!enabled || event.ctrlKey || event.metaKey || event.altKey) {\n return;\n }\n\n if (event.target instanceof Element) {\n if (event.target.closest(TEXT_ENTRY_SELECTOR)) {\n return;\n }\n\n if (\n event.target.closest('[data-lightbox-slide]') &&\n event.target.closest(SLIDE_WIDGET_SELECTOR)\n ) {\n return;\n }\n }\n\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault();\n if (!onZoomPan?.(ZOOM_PAN_STEP, 0)) {\n onLeadingArrow();\n }\n break;\n case 'ArrowRight':\n event.preventDefault();\n if (!onZoomPan?.(-ZOOM_PAN_STEP, 0)) {\n onTrailingArrow();\n }\n break;\n case 'ArrowUp':\n if (onZoomPan?.(0, ZOOM_PAN_STEP)) {\n event.preventDefault();\n }\n break;\n case 'ArrowDown':\n if (onZoomPan?.(0, -ZOOM_PAN_STEP)) {\n event.preventDefault();\n }\n break;\n case 'f':\n case 'F':\n if (onToggleFullscreen) {\n event.preventDefault();\n onToggleFullscreen();\n }\n break;\n case 't':\n case 'T':\n if (onToggleThumbnails) {\n event.preventDefault();\n onToggleThumbnails();\n }\n break;\n case 'z':\n case 'Z':\n if (onToggleZoom) {\n event.preventDefault();\n onToggleZoom();\n }\n break;\n default:\n break;\n }\n };\n\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n }, [\n opened,\n enabled,\n dir,\n onClose,\n onNext,\n onPrev,\n onToggleFullscreen,\n onToggleThumbnails,\n onToggleZoom,\n onZoomPan,\n ]);\n}\n"],"mappings":";;;;AAiBA,MAAM,sBACJ;;;;;;AAOF,MAAM,wBAAwB;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,CAAC,KAAK,IAAI;AAEX,MAAM,gBAAgB;AAEtB,SAAgB,oBAAoB,EAClC,QACA,SACA,KACA,SACA,QACA,QACA,oBACA,oBACA,cACA,aAC2B;CAC3B,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,CAAC,QACH;EAOF,MAAM,iBAAiB,QAAQ,QAAQ,SAAS;EAChD,MAAM,kBAAkB,QAAQ,QAAQ,SAAS;EAEjD,MAAM,WAAW,UAAyB;GACxC,IAAI,MAAM,kBACR;GAGF,IAAI,MAAM,QAAQ,UAAU;IAC1B,MAAM,eAAe;IACrB,QAAQ;IACR;GACF;GAEA,IAAI,CAAC,WAAW,MAAM,WAAW,MAAM,WAAW,MAAM,QACtD;GAGF,IAAI,MAAM,kBAAkB,SAAS;IACnC,IAAI,MAAM,OAAO,QAAQ,mBAAmB,GAC1C;IAGF,IACE,MAAM,OAAO,QAAQ,uBAAuB,KAC5C,MAAM,OAAO,QAAQ,qBAAqB,GAE1C;GAEJ;GAEA,QAAQ,MAAM,KAAd;IACE,KAAK;KACH,MAAM,eAAe;KACrB,IAAI,CAAC,YAAY,eAAe,CAAC,GAC/B,eAAe;KAEjB;IACF,KAAK;KACH,MAAM,eAAe;KACrB,IAAI,CAAC,YAAY,KAAgB,CAAC,GAChC,gBAAgB;KAElB;IACF,KAAK;KACH,IAAI,YAAY,GAAG,aAAa,GAC9B,MAAM,eAAe;KAEvB;IACF,KAAK;KACH,IAAI,YAAY,GAAG,GAAc,GAC/B,MAAM,eAAe;KAEvB;IACF,KAAK;IACL,KAAK;KACH,IAAI,oBAAoB;MACtB,MAAM,eAAe;MACrB,mBAAmB;KACrB;KACA;IACF,KAAK;IACL,KAAK;KACH,IAAI,oBAAoB;MACtB,MAAM,eAAe;MACrB,mBAAmB;KACrB;KACA;IACF,KAAK;IACL,KAAK,KACH,IAAI,cAAc;KAChB,MAAM,eAAe;KACrB,aAAa;IACf;GAIJ;EACF;EAEA,SAAS,iBAAiB,WAAW,OAAO;EAC5C,aAAa,SAAS,oBAAoB,WAAW,OAAO;CAC9D,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;AACH"}
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ let _mantine_core = require("@mantine/core");
3
+ let react = require("react");
4
+ let _mantine_hooks = require("@mantine/hooks");
5
+ //#region packages/@mantine/lightbox/src/hooks/use-lightbox-lock-scroll.ts
6
+ function useLightboxLockScroll({ opened, exitDuration, exitDelay }) {
7
+ const [unlocked, setUnlocked] = (0, react.useState)(!opened);
8
+ const [prevOpened, setPrevOpened] = (0, react.useState)(opened);
9
+ const timeout = (0, react.useRef)(-1);
10
+ const theme = (0, _mantine_core.useMantineTheme)();
11
+ const shouldReduceMotion = (0, _mantine_hooks.useReducedMotion)();
12
+ const unlockDelay = exitDelay + ((theme.respectReducedMotion ? shouldReduceMotion : false) ? 0 : exitDuration);
13
+ if (opened !== prevOpened) {
14
+ setPrevOpened(opened);
15
+ if (opened) setUnlocked(false);
16
+ }
17
+ (0, react.useEffect)(() => {
18
+ if (opened || unlockDelay === 0) {
19
+ window.clearTimeout(timeout.current);
20
+ return;
21
+ }
22
+ timeout.current = window.setTimeout(() => setUnlocked(true), unlockDelay);
23
+ return () => window.clearTimeout(timeout.current);
24
+ }, [opened, unlockDelay]);
25
+ return opened || !unlocked && unlockDelay > 0;
26
+ }
27
+ //#endregion
28
+ exports.useLightboxLockScroll = useLightboxLockScroll;
29
+
30
+ //# sourceMappingURL=use-lightbox-lock-scroll.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-lightbox-lock-scroll.cjs","names":["useState","useRef","useMantineTheme","useReducedMotion"],"sources":["../../src/hooks/use-lightbox-lock-scroll.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { useMantineTheme } from '@mantine/core';\nimport { useReducedMotion } from '@mantine/hooks';\n\ninterface UseLightboxLockScrollInput {\n opened: boolean;\n exitDuration: number;\n exitDelay: number;\n}\n\nexport function useLightboxLockScroll({\n opened,\n exitDuration,\n exitDelay,\n}: UseLightboxLockScrollInput) {\n const [unlocked, setUnlocked] = useState(!opened);\n const [prevOpened, setPrevOpened] = useState(opened);\n const timeout = useRef<number>(-1);\n const theme = useMantineTheme();\n const shouldReduceMotion = useReducedMotion();\n const reduceMotion = theme.respectReducedMotion ? shouldReduceMotion : false;\n const unlockDelay = exitDelay + (reduceMotion ? 0 : exitDuration);\n\n // Opening arms the lock in the same render rather than one commit later, so the page\n // cannot scroll in the frame between mounting the lightbox and the effect running.\n if (opened !== prevOpened) {\n setPrevOpened(opened);\n if (opened) {\n setUnlocked(false);\n }\n }\n\n useEffect(() => {\n if (opened || unlockDelay === 0) {\n window.clearTimeout(timeout.current);\n return undefined;\n }\n\n // The lock is released only after the exit transition has played out, otherwise the\n // page jumps by the scrollbar width while the lightbox is still fading out.\n timeout.current = window.setTimeout(() => setUnlocked(true), unlockDelay);\n return () => window.clearTimeout(timeout.current);\n }, [opened, unlockDelay]);\n\n return opened || (!unlocked && unlockDelay > 0);\n}\n"],"mappings":";;;;;AAUA,SAAgB,sBAAsB,EACpC,QACA,cACA,aAC6B;CAC7B,MAAM,CAAC,UAAU,gBAAA,GAAeA,MAAAA,SAAAA,CAAS,CAAC,MAAM;CAChD,MAAM,CAAC,YAAY,kBAAA,GAAiBA,MAAAA,SAAAA,CAAS,MAAM;CACnD,MAAM,WAAA,GAAUC,MAAAA,OAAAA,CAAe,EAAE;CACjC,MAAM,SAAA,GAAQC,cAAAA,gBAAAA,CAAgB;CAC9B,MAAM,sBAAA,GAAqBC,eAAAA,iBAAAA,CAAiB;CAE5C,MAAM,cAAc,cADC,MAAM,uBAAuB,qBAAqB,SACvB,IAAI;CAIpD,IAAI,WAAW,YAAY;EACzB,cAAc,MAAM;EACpB,IAAI,QACF,YAAY,KAAK;CAErB;CAEA,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,UAAU,gBAAgB,GAAG;GAC/B,OAAO,aAAa,QAAQ,OAAO;GACnC;EACF;EAIA,QAAQ,UAAU,OAAO,iBAAiB,YAAY,IAAI,GAAG,WAAW;EACxE,aAAa,OAAO,aAAa,QAAQ,OAAO;CAClD,GAAG,CAAC,QAAQ,WAAW,CAAC;CAExB,OAAO,UAAW,CAAC,YAAY,cAAc;AAC/C"}