@hh.ru/magritte-ui-media-viewer 1.2.2 → 1.2.3
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/index.css +79 -79
- package/index.js +1 -1
- package/index.mock.js.map +1 -1
- package/internal/Counter.js +1 -1
- package/internal/Counter.js.map +1 -1
- package/internal/GalleryItemBody.js +1 -1
- package/internal/GalleryItemBody.js.map +1 -1
- package/internal/ImagesLoader.js.map +1 -1
- package/internal/PreviewItem.js +1 -1
- package/internal/PreviewItem.js.map +1 -1
- package/internal/PreviewItemBody.js +1 -1
- package/internal/PreviewItemBody.js.map +1 -1
- package/internal/PreviewZoomControl.js +1 -1
- package/internal/PreviewZoomControl.js.map +1 -1
- package/internal/animations.js.map +1 -1
- package/internal/context.js.map +1 -1
- package/internal/hooks/useAutoHideTools.js.map +1 -1
- package/internal/hooks/useDoubleTapScale.js.map +1 -1
- package/internal/hooks/useGalleryItemController.js.map +1 -1
- package/internal/hooks/usePan.js.map +1 -1
- package/internal/hooks/usePinchToZoom.js.map +1 -1
- package/internal/hooks/useSwipe.js.map +1 -1
- package/internal/hooks/useSwipeToClose.js.map +1 -1
- package/internal/hooks/useTapToToggleTools.js.map +1 -1
- package/internal/hooks/useVirtualization.js.map +1 -1
- package/internal/hooks/useWheelToZoom.js.map +1 -1
- package/internal/utils.js.map +1 -1
- package/media-viewer-DhN96vgd.js +5 -0
- package/media-viewer-DhN96vgd.js.map +1 -0
- package/package.json +15 -15
- package/public/Footer.js +1 -1
- package/public/Footer.js.map +1 -1
- package/public/Gallery.js +1 -1
- package/public/Gallery.js.map +1 -1
- package/public/GalleryItem.js +1 -1
- package/public/GalleryItem.js.map +1 -1
- package/public/Header.js +1 -1
- package/public/Header.js.map +1 -1
- package/public/MediaViewer.js +1 -1
- package/public/MediaViewer.js.map +1 -1
- package/public/Preview.js +1 -1
- package/public/Preview.js.map +1 -1
- package/public/Toolbar.js +1 -1
- package/public/Toolbar.js.map +1 -1
- package/public/Tools.js.map +1 -1
- package/media-viewer-CYTGXlUE.js +0 -5
- package/media-viewer-CYTGXlUE.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PreviewItemBody.js","sources":["
|
|
1
|
+
{"version":3,"file":"PreviewItemBody.js","sources":["src/internal/PreviewItemBody.tsx"],"sourcesContent":["import { type FC, type PropsWithChildren, useEffect, useRef } from 'react';\nimport { useMotionValue, animate, useTransform, type MotionValue, useMotionValueEvent, motion } from 'motion/react';\n\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { useMediaViewerContext, usePreviewContext } from '@hh.ru/magritte-ui-media-viewer/internal/context';\nimport { clamp, useDetectDiscreteChange } from '@hh.ru/magritte-ui-media-viewer/internal/utils';\n\nimport styles from '../public/media-viewer.less';\n\nconst calcSizeFactor = (activeItemIndex: number, itemIndex: number, dragFactor: number): number => {\n const diff = Math.abs(activeItemIndex - itemIndex);\n return Math.max(0, clamp(1 - diff, 0, 1) - dragFactor);\n};\n\nconst MINIATURE_MIN_SIZE = 48;\n\nexport const PreviewItemBody: FC<\n PropsWithChildren<{ index: number; src: string; dragFactor: MotionValue<number> }>\n> = ({ index, src, dragFactor }) => {\n const globalContext = useMediaViewerContext();\n const { activeItemIndex } = usePreviewContext();\n const sizeFactor = useMotionValue(calcSizeFactor(activeItemIndex.get(), index, dragFactor.get()));\n const display = useMotionValue<'block' | 'none'>('none');\n const imageWidth = useMotionValue(0);\n const imageHeight = useMotionValue(0);\n const isDiscrete = useDetectDiscreteChange(activeItemIndex);\n const sizeFactorTarget = useRef<number>(-1);\n const { isMobile } = useBreakpoint();\n const width = useTransform(sizeFactor, [0, 1], isMobile ? [24, 48] : [40, 80]);\n useMotionValueEvent(dragFactor, 'change', (value) => {\n sizeFactor.set(calcSizeFactor(activeItemIndex.get(), index, value));\n });\n\n useMotionValueEvent(activeItemIndex, 'change', (newIndex) => {\n const newSizeFactor = calcSizeFactor(newIndex, index, dragFactor.get());\n if (newSizeFactor === sizeFactorTarget.current || newSizeFactor === sizeFactor.get()) {\n return;\n }\n sizeFactorTarget.current = newSizeFactor;\n if (isDiscrete()) {\n animate(sizeFactor, newSizeFactor, { duration: 0.2 });\n } else {\n sizeFactor.set(newSizeFactor);\n }\n });\n\n useEffect(() => {\n const applySize = (width: number, height: number) => {\n const minSide = Math.min(width, height);\n const scale = MINIATURE_MIN_SIZE / minSide;\n const scaledWidth = width * scale;\n const scaledHeight = height * scale;\n imageWidth.set(scaledWidth);\n imageHeight.set(scaledHeight);\n display.set('block');\n };\n const meta = globalContext.imagesLoader.getUrlMeta(src);\n if (meta && meta.status === 'loaded' && meta.width && meta.height) {\n applySize(meta.width, meta.height);\n return void 0;\n }\n display.set('none');\n return globalContext.imagesLoader.waitingForUrl(src, ({ width, height }) => {\n if (!width || !height) {\n return;\n }\n applySize(width, height);\n });\n }, [src, globalContext, display, imageWidth, imageHeight]);\n\n return (\n <motion.div\n onClick={() => {\n globalContext.currentSlideIndex.set(index);\n }}\n className={styles.previewItem}\n style={{\n width,\n }}\n draggable={false}\n >\n <motion.div\n draggable={false}\n className={styles.previewItemContainer}\n style={{\n width: imageWidth,\n height: imageHeight,\n display,\n flex: '0 0 auto',\n }}\n >\n <img src={src} draggable={false} />\n </motion.div>\n </motion.div>\n );\n};\n"],"names":["_jsx"],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ import { EASE_BASE } from './animations.js';
|
|
|
9
9
|
import { useMediaViewerContext } from './context.js';
|
|
10
10
|
import { useInitOnce, findNextValue, getDimensionsAfterRotation, clampOffset } from './utils.js';
|
|
11
11
|
import { Text } from '@hh.ru/magritte-ui-typography';
|
|
12
|
-
import { s as styles } from '../media-viewer-
|
|
12
|
+
import { s as styles } from '../media-viewer-DhN96vgd.js';
|
|
13
13
|
import './ImagesLoader.js';
|
|
14
14
|
|
|
15
15
|
const getCurrentControllerLimits = (globalContext) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PreviewZoomControl.js","sources":["../../src/internal/PreviewZoomControl.tsx"],"sourcesContent":["import { type FC, useState, useRef, useEffect } from 'react';\nimport { animate } from 'motion/react';\n\nimport { useTranslation } from '@hh.ru/magritte-common-use-translation';\nimport { tokenSemanticAnimationTimeMDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { MagnifierMinusOutlinedSize24, MagnifierPlusOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { type MediaViewerContextValue, useMediaViewerContext } from '@hh.ru/magritte-ui-media-viewer/internal/context';\nimport {\n findNextValue,\n getDimensionsAfterRotation,\n clampOffset,\n useInitOnce,\n} from '@hh.ru/magritte-ui-media-viewer/internal/utils';\nimport { Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from '../public/media-viewer.less';\n\nconst getCurrentControllerLimits = (globalContext: MediaViewerContextValue) => {\n const controller = globalContext.currentSlideController.get();\n if (!controller) {\n return null;\n }\n const rotation = controller.rotation.get();\n const zoomStops = controller.zoomStops.get()[rotation % 2];\n return {\n min: zoomStops?.[0] ?? Number.NEGATIVE_INFINITY,\n max: zoomStops?.[zoomStops.length - 1] ?? Number.POSITIVE_INFINITY,\n };\n};\n\nexport const PreviewZoomControl: FC = () => {\n const globalContext = useMediaViewerContext();\n const [zoom, setZoom] = useState<number | null>(() => {\n const zoom = globalContext.currentSlideController.get()?.scale.get() || null;\n return zoom ? Math.round(zoom * 100) : null;\n });\n const updateZoom = useInitOnce(() => (newZoom: number | null) => {\n setZoom(newZoom ? Math.round(newZoom * 100) : null);\n });\n\n const [zoomLimits, setZoomLimits] = useState<{ min: number; max: number } | null>(() =>\n getCurrentControllerLimits(globalContext)\n );\n const prevControllerUnsubRef = useRef<VoidFunction[]>([]);\n const zoomInTrl = useTranslation('MediaViewer', 'zoomIn');\n const zoomOutTrl = useTranslation('MediaViewer', 'zoomOut');\n\n const applyNextZoom = (direction: 'in' | 'out') => {\n const controller = globalContext.currentSlideController.get();\n const contentSize = controller?.contentSize.get();\n const viewPortDimensions = globalContext.viewPortDimensions.get();\n const rotation = controller?.rotation.get() ?? 0;\n if (!controller || !contentSize || !viewPortDimensions) {\n return;\n }\n const nextZoom = findNextValue(\n controller.zoomStops.get()[rotation % 2],\n controller.scale.get() ?? 1,\n direction === 'in'\n );\n\n controller.scale.stop();\n controller.offsetX.stop();\n controller.offsetY.stop();\n\n const sizeAfterRotation = getDimensionsAfterRotation(contentSize, rotation);\n const clampedOffsetX = clampOffset(\n controller.offsetX.get(),\n sizeAfterRotation.width * nextZoom,\n viewPortDimensions.width\n );\n const clampedOffsetY = clampOffset(\n controller.offsetY.get(),\n sizeAfterRotation.height * nextZoom,\n viewPortDimensions.height\n );\n\n animate(controller.scale, nextZoom, { duration: tokenSemanticAnimationTimeMDuration / 1000, ease: EASE_BASE });\n animate(controller.offsetX, clampedOffsetX, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n animate(controller.offsetY, clampedOffsetY, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n };\n\n useEffect(() => {\n const subs = [\n globalContext.currentSlideController.on('change', (controller) => {\n if (!controller) {\n return;\n }\n const scale = controller.scale.get() || null;\n updateZoom(scale);\n // слушаем всегда только один контроллер, от предыдущего надо отписаться\n prevControllerUnsubRef.current.forEach((unsub) => unsub());\n prevControllerUnsubRef.current = [\n controller.scale.on('change', updateZoom),\n controller.zoomStops.on('change', () => setZoomLimits(getCurrentControllerLimits(globalContext))),\n ];\n setZoomLimits(getCurrentControllerLimits(globalContext));\n }),\n () => prevControllerUnsubRef.current.forEach((unsub) => unsub()),\n ];\n\n const currentController = globalContext.currentSlideController.get();\n if (currentController) {\n prevControllerUnsubRef.current = [\n currentController.scale.on('change', updateZoom),\n currentController.zoomStops.on('change', () =>\n setZoomLimits(getCurrentControllerLimits(globalContext))\n ),\n ];\n setZoomLimits(getCurrentControllerLimits(globalContext));\n }\n return () => subs.forEach((unsub) => unsub?.());\n }, [globalContext, updateZoom]);\n\n return (\n <div className={styles.previewZoomControl}>\n <MagnifierMinusOutlinedSize24\n initialColor=\"contrast\"\n padding={8}\n disabled={zoom !== null && (zoomLimits === null || zoom <= Math.round(zoomLimits?.min * 100))}\n onClick={() => {\n applyNextZoom('out');\n }}\n borderRadius=\"halfHeight\"\n aria-label={zoomOutTrl}\n />\n <Text style=\"contrast\" typography=\"label-2-regular\">\n {`${zoom ?? 100}%`}\n </Text>\n <MagnifierPlusOutlinedSize24\n initialColor=\"contrast\"\n padding={8}\n disabled={zoom !== null && (zoomLimits === null || zoom >= Math.round(zoomLimits?.max * 100))}\n onClick={() => {\n applyNextZoom('in');\n }}\n borderRadius=\"halfHeight\"\n aria-label={zoomInTrl}\n />\n </div>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PreviewZoomControl.js","sources":["src/internal/PreviewZoomControl.tsx"],"sourcesContent":["import { type FC, useState, useRef, useEffect } from 'react';\nimport { animate } from 'motion/react';\n\nimport { useTranslation } from '@hh.ru/magritte-common-use-translation';\nimport { tokenSemanticAnimationTimeMDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { MagnifierMinusOutlinedSize24, MagnifierPlusOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { type MediaViewerContextValue, useMediaViewerContext } from '@hh.ru/magritte-ui-media-viewer/internal/context';\nimport {\n findNextValue,\n getDimensionsAfterRotation,\n clampOffset,\n useInitOnce,\n} from '@hh.ru/magritte-ui-media-viewer/internal/utils';\nimport { Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from '../public/media-viewer.less';\n\nconst getCurrentControllerLimits = (globalContext: MediaViewerContextValue) => {\n const controller = globalContext.currentSlideController.get();\n if (!controller) {\n return null;\n }\n const rotation = controller.rotation.get();\n const zoomStops = controller.zoomStops.get()[rotation % 2];\n return {\n min: zoomStops?.[0] ?? Number.NEGATIVE_INFINITY,\n max: zoomStops?.[zoomStops.length - 1] ?? Number.POSITIVE_INFINITY,\n };\n};\n\nexport const PreviewZoomControl: FC = () => {\n const globalContext = useMediaViewerContext();\n const [zoom, setZoom] = useState<number | null>(() => {\n const zoom = globalContext.currentSlideController.get()?.scale.get() || null;\n return zoom ? Math.round(zoom * 100) : null;\n });\n const updateZoom = useInitOnce(() => (newZoom: number | null) => {\n setZoom(newZoom ? Math.round(newZoom * 100) : null);\n });\n\n const [zoomLimits, setZoomLimits] = useState<{ min: number; max: number } | null>(() =>\n getCurrentControllerLimits(globalContext)\n );\n const prevControllerUnsubRef = useRef<VoidFunction[]>([]);\n const zoomInTrl = useTranslation('MediaViewer', 'zoomIn');\n const zoomOutTrl = useTranslation('MediaViewer', 'zoomOut');\n\n const applyNextZoom = (direction: 'in' | 'out') => {\n const controller = globalContext.currentSlideController.get();\n const contentSize = controller?.contentSize.get();\n const viewPortDimensions = globalContext.viewPortDimensions.get();\n const rotation = controller?.rotation.get() ?? 0;\n if (!controller || !contentSize || !viewPortDimensions) {\n return;\n }\n const nextZoom = findNextValue(\n controller.zoomStops.get()[rotation % 2],\n controller.scale.get() ?? 1,\n direction === 'in'\n );\n\n controller.scale.stop();\n controller.offsetX.stop();\n controller.offsetY.stop();\n\n const sizeAfterRotation = getDimensionsAfterRotation(contentSize, rotation);\n const clampedOffsetX = clampOffset(\n controller.offsetX.get(),\n sizeAfterRotation.width * nextZoom,\n viewPortDimensions.width\n );\n const clampedOffsetY = clampOffset(\n controller.offsetY.get(),\n sizeAfterRotation.height * nextZoom,\n viewPortDimensions.height\n );\n\n animate(controller.scale, nextZoom, { duration: tokenSemanticAnimationTimeMDuration / 1000, ease: EASE_BASE });\n animate(controller.offsetX, clampedOffsetX, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n animate(controller.offsetY, clampedOffsetY, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n };\n\n useEffect(() => {\n const subs = [\n globalContext.currentSlideController.on('change', (controller) => {\n if (!controller) {\n return;\n }\n const scale = controller.scale.get() || null;\n updateZoom(scale);\n // слушаем всегда только один контроллер, от предыдущего надо отписаться\n prevControllerUnsubRef.current.forEach((unsub) => unsub());\n prevControllerUnsubRef.current = [\n controller.scale.on('change', updateZoom),\n controller.zoomStops.on('change', () => setZoomLimits(getCurrentControllerLimits(globalContext))),\n ];\n setZoomLimits(getCurrentControllerLimits(globalContext));\n }),\n () => prevControllerUnsubRef.current.forEach((unsub) => unsub()),\n ];\n\n const currentController = globalContext.currentSlideController.get();\n if (currentController) {\n prevControllerUnsubRef.current = [\n currentController.scale.on('change', updateZoom),\n currentController.zoomStops.on('change', () =>\n setZoomLimits(getCurrentControllerLimits(globalContext))\n ),\n ];\n setZoomLimits(getCurrentControllerLimits(globalContext));\n }\n return () => subs.forEach((unsub) => unsub?.());\n }, [globalContext, updateZoom]);\n\n return (\n <div className={styles.previewZoomControl}>\n <MagnifierMinusOutlinedSize24\n initialColor=\"contrast\"\n padding={8}\n disabled={zoom !== null && (zoomLimits === null || zoom <= Math.round(zoomLimits?.min * 100))}\n onClick={() => {\n applyNextZoom('out');\n }}\n borderRadius=\"halfHeight\"\n aria-label={zoomOutTrl}\n />\n <Text style=\"contrast\" typography=\"label-2-regular\">\n {`${zoom ?? 100}%`}\n </Text>\n <MagnifierPlusOutlinedSize24\n initialColor=\"contrast\"\n padding={8}\n disabled={zoom !== null && (zoomLimits === null || zoom >= Math.round(zoomLimits?.max * 100))}\n onClick={() => {\n applyNextZoom('in');\n }}\n borderRadius=\"halfHeight\"\n aria-label={zoomInTrl}\n />\n </div>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animations.js","sources":["
|
|
1
|
+
{"version":3,"file":"animations.js","sources":["src/internal/animations.ts"],"sourcesContent":["import {\n tokenSemanticAnimationEaseBaseX1,\n tokenSemanticAnimationEaseBaseX2,\n tokenSemanticAnimationEaseBaseY1,\n tokenSemanticAnimationEaseBaseY2,\n} from '@hh.ru/magritte-design-tokens/types';\n\nexport const EASE_BASE = [\n tokenSemanticAnimationEaseBaseX1,\n tokenSemanticAnimationEaseBaseY1,\n tokenSemanticAnimationEaseBaseX2,\n tokenSemanticAnimationEaseBaseY2,\n] as const;\n"],"names":[],"mappings":";;AAOa,MAAA,SAAS,GAAG;IACrB,gCAAgC;IAChC,gCAAgC;IAChC,gCAAgC;IAChC,gCAAgC;;;;;"}
|
package/internal/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sources":["
|
|
1
|
+
{"version":3,"file":"context.js","sources":["src/internal/context.ts"],"sourcesContent":["import { createContext, ReactElement, useCallback, useContext, useState } from 'react';\nimport { MotionValue, motionValue, useMotionValueEvent } from 'motion/react';\n\nimport { GalleryItemProps } from '@hh.ru/magritte-ui-media-viewer/internal/GalleryItemBody';\nimport { ImagesLoader } from '@hh.ru/magritte-ui-media-viewer/internal/ImagesLoader';\nimport { GalleryItemController } from '@hh.ru/magritte-ui-media-viewer/internal/hooks/useGalleryItemController';\nimport { VirtualizationVisibleRange } from '@hh.ru/magritte-ui-media-viewer/internal/hooks/useVirtualization';\nimport { clamp } from '@hh.ru/magritte-ui-media-viewer/internal/utils';\n\n/* eslint-disable @typescript-eslint/explicit-module-boundary-types */\nexport const createMediaViewerContextValue = (\n visibleRange: VirtualizationVisibleRange,\n currentSlideIndex: MotionValue<number>,\n closeProgress: MotionValue<number>,\n close: VoidFunction\n) => ({\n /* eslint-enable @typescript-eslint/explicit-module-boundary-types */\n viewPortDimensions: motionValue<DOMRectReadOnly | null>(null),\n currentSlideIndex,\n totalSlides: motionValue(0),\n currentSlideController: motionValue<GalleryItemController | null>(null),\n closeProgress,\n close,\n hideToolsProgress: motionValue(0),\n onRequestClose: () => {},\n visibleRange,\n imagesLoader: new ImagesLoader(),\n});\n\nexport type MediaViewerContextValue = ReturnType<typeof createMediaViewerContextValue>;\n\nexport const MediaViewerContext = createContext<MediaViewerContextValue | undefined>(undefined);\n\nexport const useMediaViewerContext = (): MediaViewerContextValue => {\n const context = useContext(MediaViewerContext);\n if (!context) {\n throw new Error('useMediaViewerContext must be used within a MediaViewer');\n }\n return context;\n};\n\nexport interface GalleryItemContextValue {\n (size: { width: number; height: number } | null): void;\n}\nexport const GalleryItemContext = createContext<GalleryItemContextValue | undefined>(undefined);\n\nexport const useGalleryItemContext = (): GalleryItemContextValue => {\n const context = useContext(GalleryItemContext);\n if (!context) {\n throw new Error('useGalleryItemContext must be used within a GalleryItem');\n }\n return context;\n};\n\nexport interface PreviewContextValue {\n activeItemIndex: MotionValue<number>;\n visibleRange: VirtualizationVisibleRange;\n}\n\nexport const PreviewContext = createContext<PreviewContextValue | undefined>(undefined);\n\nexport const usePreviewContext = (): PreviewContextValue => {\n const context = useContext(PreviewContext);\n if (!context) {\n throw new Error('usePreviewContext must be used within a Preview');\n }\n return context;\n};\n\nexport const useMediaViewerInfo = (): {\n currentSlideIndex: number;\n currentSlideDescription: string | undefined;\n currentSlideUrl: string | undefined;\n slidesCount: number;\n} => {\n const globalContext = useMediaViewerContext();\n const [currentSlideIndex, setCurrentItemIndex] = useState(globalContext.currentSlideIndex.get());\n const [currentSlideDescription, setCurrentSlideDescription] = useState<string | undefined>(\n globalContext.currentSlideController.get()?.description.get()\n );\n const [currentSlideUrl, setCurrentSlideUrl] = useState<string | undefined>(\n globalContext.currentSlideController.get()?.url.get()\n );\n const [slidesCount, setSlidesCount] = useState(globalContext.totalSlides.get());\n\n useMotionValueEvent(globalContext.currentSlideController, 'change', (controller) => {\n setCurrentSlideDescription(controller?.description.get());\n setCurrentSlideUrl(controller?.url.get());\n });\n useMotionValueEvent(globalContext.currentSlideIndex, 'change', (newIndex) => {\n setCurrentItemIndex(newIndex);\n });\n useMotionValueEvent(globalContext.totalSlides, 'change', (newCount) => {\n setSlidesCount(newCount);\n });\n\n return {\n currentSlideIndex,\n currentSlideDescription,\n currentSlideUrl,\n slidesCount,\n };\n};\n\nexport const useMediaViewerControls = (): {\n goToSlideIndex: (index: number) => void;\n close: VoidFunction;\n} => {\n const globalContext = useMediaViewerContext();\n const goToSlideIndex = useCallback(\n (index: number) => {\n globalContext.currentSlideIndex.stop();\n globalContext.currentSlideIndex.set(clamp(index, 0, globalContext.totalSlides.get() - 1));\n },\n [globalContext]\n );\n\n return {\n goToSlideIndex,\n close: globalContext.close,\n };\n};\n\nexport interface GalleryItemsContextValue {\n items: ReactElement<GalleryItemProps>[];\n setItems: (items: ReactElement<GalleryItemProps>[]) => void;\n}\nexport const GalleryItemsContext = createContext<GalleryItemsContextValue | undefined>(undefined);\n\nexport const useGalleryItemsContext = (): GalleryItemsContextValue => {\n const context = useContext(GalleryItemsContext);\n if (!context) {\n throw new Error('useGalleryItemsContext must be used within a Gallery');\n }\n return context;\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAutoHideTools.js","sources":["
|
|
1
|
+
{"version":3,"file":"useAutoHideTools.js","sources":["src/internal/hooks/useAutoHideTools.ts"],"sourcesContent":["import { useRef, useCallback, useEffect } from 'react';\nimport { animate } from 'motion/react';\n\nimport { tokenSemanticAnimationTimeLDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { type MediaViewerContextValue } from '@hh.ru/magritte-ui-media-viewer/internal/context';\n\nconst HIDE_TOOL_DELAY_MS = 6000;\n\ninterface UseAutoHideToolsResult {\n onMouseMove: VoidFunction;\n onClick: VoidFunction;\n}\n\nexport const useAutoHideTools = (context: MediaViewerContextValue): UseAutoHideToolsResult => {\n const hideToolTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const { isMobile } = useBreakpoint();\n\n const hideTools = useCallback(\n () =>\n animate(context.hideToolsProgress, 1, {\n duration: tokenSemanticAnimationTimeLDuration / 1000,\n ease: EASE_BASE,\n }),\n [context]\n );\n const showTools = useCallback(() => {\n if (context.hideToolsProgress.isAnimating() || context.hideToolsProgress.get() === 0) {\n return;\n }\n animate(context.hideToolsProgress, 0, {\n duration: tokenSemanticAnimationTimeLDuration / 1000,\n ease: EASE_BASE,\n });\n }, [context]);\n\n const resetTimer = useCallback(() => {\n if (hideToolTimerRef.current) {\n clearTimeout(hideToolTimerRef.current);\n }\n if (!isMobile) {\n hideToolTimerRef.current = setTimeout(hideTools, HIDE_TOOL_DELAY_MS);\n }\n }, [hideTools, isMobile]);\n\n const showOnAction = useCallback(() => {\n showTools();\n resetTimer();\n }, [showTools, resetTimer]);\n\n // Запускаем таймер при монтировании\n useEffect(() => {\n resetTimer();\n return () => {\n if (hideToolTimerRef.current) {\n clearTimeout(hideToolTimerRef.current);\n }\n };\n }, [resetTimer]);\n\n return { onMouseMove: showOnAction, onClick: showOnAction };\n};\n"],"names":[],"mappings":";;;;;;AAQA,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAOnB,MAAA,gBAAgB,GAAG,CAAC,OAAgC,KAA4B;AACzF,IAAA,MAAM,gBAAgB,GAAG,MAAM,CAAuC,IAAI,CAAC,CAAC;AAC5E,IAAA,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,EAAE,CAAC;AAErC,IAAA,MAAM,SAAS,GAAG,WAAW,CACzB,MACI,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,EAAE;QAClC,QAAQ,EAAE,mCAAmC,GAAG,IAAI;AACpD,QAAA,IAAI,EAAE,SAAS;AAClB,KAAA,CAAC,EACN,CAAC,OAAO,CAAC,CACZ,CAAC;AACF,IAAA,MAAM,SAAS,GAAG,WAAW,CAAC,MAAK;AAC/B,QAAA,IAAI,OAAO,CAAC,iBAAiB,CAAC,WAAW,EAAE,IAAI,OAAO,CAAC,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE;YAClF,OAAO;SACV;AACD,QAAA,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,EAAE;YAClC,QAAQ,EAAE,mCAAmC,GAAG,IAAI;AACpD,YAAA,IAAI,EAAE,SAAS;AAClB,SAAA,CAAC,CAAC;AACP,KAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AAEd,IAAA,MAAM,UAAU,GAAG,WAAW,CAAC,MAAK;AAChC,QAAA,IAAI,gBAAgB,CAAC,OAAO,EAAE;AAC1B,YAAA,YAAY,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;SAC1C;QACD,IAAI,CAAC,QAAQ,EAAE;YACX,gBAAgB,CAAC,OAAO,GAAG,UAAU,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;SACxE;AACL,KAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE1B,IAAA,MAAM,YAAY,GAAG,WAAW,CAAC,MAAK;AAClC,QAAA,SAAS,EAAE,CAAC;AACZ,QAAA,UAAU,EAAE,CAAC;AACjB,KAAC,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;;IAG5B,SAAS,CAAC,MAAK;AACX,QAAA,UAAU,EAAE,CAAC;AACb,QAAA,OAAO,MAAK;AACR,YAAA,IAAI,gBAAgB,CAAC,OAAO,EAAE;AAC1B,gBAAA,YAAY,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;aAC1C;AACL,SAAC,CAAC;AACN,KAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;AAChE;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDoubleTapScale.js","sources":["
|
|
1
|
+
{"version":3,"file":"useDoubleTapScale.js","sources":["src/internal/hooks/useDoubleTapScale.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { animate, type HTMLMotionProps } from 'motion/react';\n\nimport { tokenSemanticAnimationTimeSDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { type GalleryItemController } from '@hh.ru/magritte-ui-media-viewer/internal/hooks/useGalleryItemController';\nimport { isClose } from '@hh.ru/magritte-ui-media-viewer/internal/utils';\n\nconst DOUBLE_TAP_DELAY = 300;\n\nexport const useDoubleTapScale = (controller: GalleryItemController): HTMLMotionProps<'div'> => {\n const lastTapRef = useRef(0);\n const pinchingRef = useRef(false);\n const lastDoubleTapRef = useRef(0);\n\n const handleDoubleTap = useCallback(() => {\n // Защита от повторного срабатывания\n const now = Date.now();\n if (now - lastDoubleTapRef.current < DOUBLE_TAP_DELAY) {\n return;\n }\n lastDoubleTapRef.current = now;\n\n if (controller.pinching) {\n return;\n }\n\n const currentScale = controller.scale.get();\n const fitFill = controller.fitFillScales.get();\n if (fitFill === null) {\n return;\n }\n\n controller.scale.stop();\n controller.offsetX.stop();\n controller.offsetY.stop();\n\n const possibleTargets = fitFill[controller.rotation.get() % 2];\n const atFill = isClose(currentScale, possibleTargets.fill);\n const atFit = isClose(currentScale, possibleTargets.fit);\n const closerToFill =\n Math.abs(currentScale - possibleTargets.fill) < Math.abs(currentScale - possibleTargets.fit);\n\n const next = (atFill || atFit) !== closerToFill ? 'fill' : 'fit';\n animate(controller.scale, possibleTargets[next], {\n duration: tokenSemanticAnimationTimeSDuration / 1000,\n ease: EASE_BASE,\n });\n animate(controller.offsetX, 0, { duration: tokenSemanticAnimationTimeSDuration / 1000, ease: EASE_BASE });\n animate(controller.offsetY, 0, { duration: tokenSemanticAnimationTimeSDuration / 1000, ease: EASE_BASE });\n }, [controller]);\n\n const handleTouchStart = useCallback(() => {\n pinchingRef.current = controller.pinching;\n }, [controller]);\n\n const handleTouchEnd = useCallback(() => {\n if (controller.pinching || pinchingRef.current) {\n return;\n }\n const now = Date.now();\n\n if (now - lastTapRef.current < DOUBLE_TAP_DELAY) {\n handleDoubleTap();\n }\n lastTapRef.current = now;\n }, [handleDoubleTap, controller]);\n\n return { onTouchEnd: handleTouchEnd, onDoubleClick: handleDoubleTap, onTouchStart: handleTouchStart };\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGalleryItemController.js","sources":["../../../src/internal/hooks/useGalleryItemController.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport { type MotionValue, motionValue, animate } from 'motion/react';\n\nimport { tokenSemanticAnimationTimeMDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { type MediaViewerContextValue } from '@hh.ru/magritte-ui-media-viewer/internal/context';\nimport { useInitOnce } from '@hh.ru/magritte-ui-media-viewer/internal/utils';\nimport { Size } from '@hh.ru/magritte-ui-media-viewer/public/types';\n\nconst computeFitScale = (container: Size, content: Size): number => {\n return Math.min(container.width / content.width, container.height / content.height);\n};\n\n// fit и fill масштабы для горизонтальной и вертикальной ориентации\nexport type FitFillScales = [{ fit: number; fill: number }, { fit: number; fill: number }] | null;\n\nconst computeFitFill = (containerSize: Size | null, contentSize: Size | null): FitFillScales => {\n if (\n !containerSize ||\n !contentSize ||\n contentSize.width === 0 ||\n contentSize.height === 0 ||\n containerSize.width === 0 ||\n containerSize.height === 0\n ) {\n return null;\n }\n const contentRotatedSize = { width: contentSize.height, height: contentSize.width };\n return [\n {\n fit: computeFitScale(containerSize, contentSize),\n fill: Math.max(3, 1 / computeFitScale(contentSize, containerSize)),\n },\n {\n fit: computeFitScale(containerSize, contentRotatedSize),\n fill: Math.max(3, 1 / computeFitScale(contentRotatedSize, containerSize)),\n },\n ];\n};\n\nconst getCurrentScaleType = (\n controller: {\n scale: MotionValue<number>;\n rotation: MotionValue<number>;\n fitFillScales: MotionValue<FitFillScales>;\n },\n rot?: number\n): 'fit' | 'fill' | null => {\n const fitFill = controller.fitFillScales.get();\n if (fitFill === null) {\n return null;\n }\n\n const rotation = rot ?? controller.rotation.get();\n const fitFillForRotation = fitFill[rotation % 2];\n const currentScale = controller.scale.get();\n\n if (Math.abs(currentScale - fitFillForRotation.fit) < 0.01) {\n return 'fit';\n }\n if (Math.abs(currentScale - fitFillForRotation.fill) < 0.01) {\n return 'fill';\n }\n return null;\n};\n\nexport interface GalleryItemController {\n scale: MotionValue<number>;\n rotation: MotionValue<number>;\n offsetX: MotionValue<number>;\n offsetY: MotionValue<number>;\n contentSize: MotionValue<Size | null>;\n fitFillScales: MotionValue<FitFillScales>;\n index: MotionValue<number>;\n pinching: boolean;\n zoomStops: MotionValue<number[][]>;\n url: MotionValue<string | undefined>;\n description: MotionValue<string | undefined>;\n}\n\nexport const isFullyInvisible = (\n controller: GalleryItemController,\n globalContext: MediaViewerContextValue\n): boolean => {\n const currentIndex = globalContext.currentSlideIndex.get();\n const itemIndex = controller.index.get();\n return itemIndex + 1 <= currentIndex || itemIndex - 1 >= currentIndex;\n};\n\nconst ZOOM_STOPS = [1, 2, 4];\n\nexport const useGalleryItemController = (\n globalContext: MediaViewerContextValue,\n url: string,\n index: number,\n description?: string\n): [(size: Size | null) => void, GalleryItemController] => {\n const controller = useInitOnce(() => {\n const controller: GalleryItemController = {\n scale: motionValue(1),\n rotation: motionValue(0),\n offsetX: motionValue(0),\n offsetY: motionValue(0),\n contentSize: motionValue<Size | null>(null),\n fitFillScales: motionValue<FitFillScales>(null),\n index: motionValue<number>(index),\n pinching: false,\n zoomStops: motionValue<number[][]>([]),\n url: motionValue<string | undefined>(url),\n description: motionValue<string | undefined>(description),\n };\n\n return controller;\n });\n\n useEffect(() => {\n controller.url.set(url);\n controller.description.set(description);\n controller.index.set(index);\n }, [url, controller, description, index]);\n\n const setContentSize = useInitOnce(() => (size: Size | null) => {\n const currentSize = controller.contentSize.get();\n if (\n currentSize === null ||\n size === null ||\n currentSize.width !== size.width ||\n currentSize.height !== size.height\n ) {\n controller.contentSize.set(size);\n }\n });\n\n const resetTransforms = useInitOnce(() => (globalContext: MediaViewerContextValue) => {\n if (!isFullyInvisible(controller, globalContext)) {\n return;\n }\n controller.rotation.stop();\n controller.offsetX.stop();\n controller.offsetY.stop();\n controller.scale.stop();\n controller.rotation.set(0);\n controller.offsetX.set(0);\n controller.offsetY.set(0);\n\n const fitFill = controller.fitFillScales.get();\n if (fitFill === null) {\n return;\n }\n\n const fit = fitFill[controller.rotation.get() % 2].fit;\n controller.scale.set(Math.min(fit, 1));\n });\n\n const updateScaleOnRotation = useInitOnce(() => (globalContext: MediaViewerContextValue) => {\n const fitFill = controller.fitFillScales.get();\n if (fitFill === null) {\n return;\n }\n\n const prevRotation = controller.rotation.get() + 1;\n const scaleType = getCurrentScaleType(controller, prevRotation);\n if (scaleType) {\n const targetScale = fitFill[controller.rotation.get() % 2][scaleType];\n controller.scale.stop();\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n isFullyInvisible(controller, globalContext)\n ? controller.scale.set(targetScale)\n : animate(controller.scale, targetScale, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n }\n });\n\n const attachController = useInitOnce(() => (globalContext: MediaViewerContextValue) => {\n if (Math.round(globalContext.currentSlideIndex.get()) === controller.index.get()) {\n globalContext.currentSlideController.set(controller);\n }\n });\n\n useEffect(() => {\n const updateFitFill = () => {\n const contentSize = controller.contentSize.get();\n const viewportDimensions = globalContext.viewPortDimensions.get();\n const prevFitFill = controller.fitFillScales.get();\n const scaleType = prevFitFill === null ? 'fit' : getCurrentScaleType(controller);\n controller.fitFillScales.set(computeFitFill(viewportDimensions, contentSize));\n const fitFill = controller.fitFillScales.get();\n if (scaleType && fitFill) {\n controller.scale.set(Math.min(fitFill[controller.rotation.get() % 2][scaleType], 1));\n }\n };\n\n const updateZoomStops = () => {\n const fitFill = controller.fitFillScales.get();\n if (!fitFill) {\n return;\n }\n const zoomStops: number[][] = [];\n for (const sizeOrientation of fitFill) {\n let stops = [...ZOOM_STOPS];\n stops.push(sizeOrientation.fit, sizeOrientation.fill);\n stops = [...new Set(stops.sort((a, b) => a - b))];\n zoomStops.push(stops);\n }\n\n controller.zoomStops.set(zoomStops);\n };\n\n const subscriptions = [\n // Обновление fit/fill при изменении размеров контента или вьюпорта\n controller.contentSize.on('change', () => {\n updateFitFill();\n updateZoomStops();\n }),\n globalContext.viewPortDimensions.on('change', () => {\n updateFitFill();\n updateZoomStops();\n }),\n\n // Сброс трансформации при смене слайда\n globalContext.currentSlideIndex.on('change', () => resetTransforms(globalContext)),\n controller.index.on('change', () => resetTransforms(globalContext)),\n\n // Обновление масштаба при изменении поворота\n controller.rotation.on('change', () => {\n updateScaleOnRotation(globalContext);\n updateZoomStops();\n }),\n\n // Установка контроллера активного слайда в глобальный контекст\n globalContext.currentSlideIndex.on('change', () => attachController(globalContext)),\n controller.index.on('change', () => attachController(globalContext)),\n ];\n\n attachController(globalContext);\n updateFitFill();\n updateZoomStops();\n\n return () => subscriptions.forEach((unsub) => unsub());\n }, [controller, globalContext, resetTransforms, updateScaleOnRotation, attachController]);\n\n return [setContentSize, controller] as const;\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useGalleryItemController.js","sources":["src/internal/hooks/useGalleryItemController.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport { type MotionValue, motionValue, animate } from 'motion/react';\n\nimport { tokenSemanticAnimationTimeMDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { type MediaViewerContextValue } from '@hh.ru/magritte-ui-media-viewer/internal/context';\nimport { useInitOnce } from '@hh.ru/magritte-ui-media-viewer/internal/utils';\nimport { Size } from '@hh.ru/magritte-ui-media-viewer/public/types';\n\nconst computeFitScale = (container: Size, content: Size): number => {\n return Math.min(container.width / content.width, container.height / content.height);\n};\n\n// fit и fill масштабы для горизонтальной и вертикальной ориентации\nexport type FitFillScales = [{ fit: number; fill: number }, { fit: number; fill: number }] | null;\n\nconst computeFitFill = (containerSize: Size | null, contentSize: Size | null): FitFillScales => {\n if (\n !containerSize ||\n !contentSize ||\n contentSize.width === 0 ||\n contentSize.height === 0 ||\n containerSize.width === 0 ||\n containerSize.height === 0\n ) {\n return null;\n }\n const contentRotatedSize = { width: contentSize.height, height: contentSize.width };\n return [\n {\n fit: computeFitScale(containerSize, contentSize),\n fill: Math.max(3, 1 / computeFitScale(contentSize, containerSize)),\n },\n {\n fit: computeFitScale(containerSize, contentRotatedSize),\n fill: Math.max(3, 1 / computeFitScale(contentRotatedSize, containerSize)),\n },\n ];\n};\n\nconst getCurrentScaleType = (\n controller: {\n scale: MotionValue<number>;\n rotation: MotionValue<number>;\n fitFillScales: MotionValue<FitFillScales>;\n },\n rot?: number\n): 'fit' | 'fill' | null => {\n const fitFill = controller.fitFillScales.get();\n if (fitFill === null) {\n return null;\n }\n\n const rotation = rot ?? controller.rotation.get();\n const fitFillForRotation = fitFill[rotation % 2];\n const currentScale = controller.scale.get();\n\n if (Math.abs(currentScale - fitFillForRotation.fit) < 0.01) {\n return 'fit';\n }\n if (Math.abs(currentScale - fitFillForRotation.fill) < 0.01) {\n return 'fill';\n }\n return null;\n};\n\nexport interface GalleryItemController {\n scale: MotionValue<number>;\n rotation: MotionValue<number>;\n offsetX: MotionValue<number>;\n offsetY: MotionValue<number>;\n contentSize: MotionValue<Size | null>;\n fitFillScales: MotionValue<FitFillScales>;\n index: MotionValue<number>;\n pinching: boolean;\n zoomStops: MotionValue<number[][]>;\n url: MotionValue<string | undefined>;\n description: MotionValue<string | undefined>;\n}\n\nexport const isFullyInvisible = (\n controller: GalleryItemController,\n globalContext: MediaViewerContextValue\n): boolean => {\n const currentIndex = globalContext.currentSlideIndex.get();\n const itemIndex = controller.index.get();\n return itemIndex + 1 <= currentIndex || itemIndex - 1 >= currentIndex;\n};\n\nconst ZOOM_STOPS = [1, 2, 4];\n\nexport const useGalleryItemController = (\n globalContext: MediaViewerContextValue,\n url: string,\n index: number,\n description?: string\n): [(size: Size | null) => void, GalleryItemController] => {\n const controller = useInitOnce(() => {\n const controller: GalleryItemController = {\n scale: motionValue(1),\n rotation: motionValue(0),\n offsetX: motionValue(0),\n offsetY: motionValue(0),\n contentSize: motionValue<Size | null>(null),\n fitFillScales: motionValue<FitFillScales>(null),\n index: motionValue<number>(index),\n pinching: false,\n zoomStops: motionValue<number[][]>([]),\n url: motionValue<string | undefined>(url),\n description: motionValue<string | undefined>(description),\n };\n\n return controller;\n });\n\n useEffect(() => {\n controller.url.set(url);\n controller.description.set(description);\n controller.index.set(index);\n }, [url, controller, description, index]);\n\n const setContentSize = useInitOnce(() => (size: Size | null) => {\n const currentSize = controller.contentSize.get();\n if (\n currentSize === null ||\n size === null ||\n currentSize.width !== size.width ||\n currentSize.height !== size.height\n ) {\n controller.contentSize.set(size);\n }\n });\n\n const resetTransforms = useInitOnce(() => (globalContext: MediaViewerContextValue) => {\n if (!isFullyInvisible(controller, globalContext)) {\n return;\n }\n controller.rotation.stop();\n controller.offsetX.stop();\n controller.offsetY.stop();\n controller.scale.stop();\n controller.rotation.set(0);\n controller.offsetX.set(0);\n controller.offsetY.set(0);\n\n const fitFill = controller.fitFillScales.get();\n if (fitFill === null) {\n return;\n }\n\n const fit = fitFill[controller.rotation.get() % 2].fit;\n controller.scale.set(Math.min(fit, 1));\n });\n\n const updateScaleOnRotation = useInitOnce(() => (globalContext: MediaViewerContextValue) => {\n const fitFill = controller.fitFillScales.get();\n if (fitFill === null) {\n return;\n }\n\n const prevRotation = controller.rotation.get() + 1;\n const scaleType = getCurrentScaleType(controller, prevRotation);\n if (scaleType) {\n const targetScale = fitFill[controller.rotation.get() % 2][scaleType];\n controller.scale.stop();\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n isFullyInvisible(controller, globalContext)\n ? controller.scale.set(targetScale)\n : animate(controller.scale, targetScale, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n }\n });\n\n const attachController = useInitOnce(() => (globalContext: MediaViewerContextValue) => {\n if (Math.round(globalContext.currentSlideIndex.get()) === controller.index.get()) {\n globalContext.currentSlideController.set(controller);\n }\n });\n\n useEffect(() => {\n const updateFitFill = () => {\n const contentSize = controller.contentSize.get();\n const viewportDimensions = globalContext.viewPortDimensions.get();\n const prevFitFill = controller.fitFillScales.get();\n const scaleType = prevFitFill === null ? 'fit' : getCurrentScaleType(controller);\n controller.fitFillScales.set(computeFitFill(viewportDimensions, contentSize));\n const fitFill = controller.fitFillScales.get();\n if (scaleType && fitFill) {\n controller.scale.set(Math.min(fitFill[controller.rotation.get() % 2][scaleType], 1));\n }\n };\n\n const updateZoomStops = () => {\n const fitFill = controller.fitFillScales.get();\n if (!fitFill) {\n return;\n }\n const zoomStops: number[][] = [];\n for (const sizeOrientation of fitFill) {\n let stops = [...ZOOM_STOPS];\n stops.push(sizeOrientation.fit, sizeOrientation.fill);\n stops = [...new Set(stops.sort((a, b) => a - b))];\n zoomStops.push(stops);\n }\n\n controller.zoomStops.set(zoomStops);\n };\n\n const subscriptions = [\n // Обновление fit/fill при изменении размеров контента или вьюпорта\n controller.contentSize.on('change', () => {\n updateFitFill();\n updateZoomStops();\n }),\n globalContext.viewPortDimensions.on('change', () => {\n updateFitFill();\n updateZoomStops();\n }),\n\n // Сброс трансформации при смене слайда\n globalContext.currentSlideIndex.on('change', () => resetTransforms(globalContext)),\n controller.index.on('change', () => resetTransforms(globalContext)),\n\n // Обновление масштаба при изменении поворота\n controller.rotation.on('change', () => {\n updateScaleOnRotation(globalContext);\n updateZoomStops();\n }),\n\n // Установка контроллера активного слайда в глобальный контекст\n globalContext.currentSlideIndex.on('change', () => attachController(globalContext)),\n controller.index.on('change', () => attachController(globalContext)),\n ];\n\n attachController(globalContext);\n updateFitFill();\n updateZoomStops();\n\n return () => subscriptions.forEach((unsub) => unsub());\n }, [controller, globalContext, resetTransforms, updateScaleOnRotation, attachController]);\n\n return [setContentSize, controller] as const;\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePan.js","sources":["
|
|
1
|
+
{"version":3,"file":"usePan.js","sources":["src/internal/hooks/usePan.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { useDrag } from '@use-gesture/react';\nimport { MotionValue } from 'motion/react';\n\nimport { type GalleryItemController } from '@hh.ru/magritte-ui-media-viewer/internal/hooks/useGalleryItemController';\nimport {\n lerp,\n animateOffsetClamp,\n clampOffset,\n isScaleBiggerThanFit,\n getDimensionsAfterRotation,\n} from '@hh.ru/magritte-ui-media-viewer/internal/utils';\n\nexport const usePan = <T>(\n controller: GalleryItemController,\n dimensions: MotionValue<DOMRectReadOnly | null>\n): ReturnType<typeof useDrag<T>> => {\n const startOffsetRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n\n return useDrag<T>(\n (state) => {\n if (controller.pinching || !isScaleBiggerThanFit(controller)) {\n state.cancel();\n return;\n }\n\n const viewPortDimensions = dimensions.get();\n const contentSize = controller.contentSize.get();\n if (!viewPortDimensions || !contentSize) {\n state.cancel();\n return;\n }\n\n if (state.first) {\n startOffsetRef.current = {\n x: controller.offsetX.get(),\n y: controller.offsetY.get(),\n };\n controller.offsetX.stop();\n controller.offsetY.stop();\n }\n\n const newOffsetX = startOffsetRef.current.x + state.offset[0];\n const newOffsetY = startOffsetRef.current.y + state.offset[1];\n\n const sizeAfterRotation = getDimensionsAfterRotation(contentSize, controller.rotation.get());\n const clampedOffsetX = clampOffset(\n newOffsetX,\n sizeAfterRotation.width * controller.scale.get(),\n viewPortDimensions.width\n );\n const clampedOffsetY = clampOffset(\n newOffsetY,\n sizeAfterRotation.height * controller.scale.get(),\n viewPortDimensions.height\n );\n\n controller.offsetX.set(lerp(clampedOffsetX, newOffsetX, 0.1));\n controller.offsetY.set(lerp(clampedOffsetY, newOffsetY, 0.1));\n\n if (state.last) {\n animateOffsetClamp(controller, dimensions);\n }\n },\n {\n from: () => [0, 0],\n }\n );\n};\n"],"names":[],"mappings":";;;;;;;MAaa,MAAM,GAAG,CAClB,UAAiC,EACjC,UAA+C,KAChB;AAC/B,IAAA,MAAM,cAAc,GAAG,MAAM,CAA2B,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAExE,IAAA,OAAO,OAAO,CACV,CAAC,KAAK,KAAI;QACN,IAAI,UAAU,CAAC,QAAQ,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,EAAE;YAC1D,KAAK,CAAC,MAAM,EAAE,CAAC;YACf,OAAO;SACV;AAED,QAAA,MAAM,kBAAkB,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC;QAC5C,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;AACjD,QAAA,IAAI,CAAC,kBAAkB,IAAI,CAAC,WAAW,EAAE;YACrC,KAAK,CAAC,MAAM,EAAE,CAAC;YACf,OAAO;SACV;AAED,QAAA,IAAI,KAAK,CAAC,KAAK,EAAE;YACb,cAAc,CAAC,OAAO,GAAG;AACrB,gBAAA,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE;AAC3B,gBAAA,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE;aAC9B,CAAC;AACF,YAAA,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;AAC1B,YAAA,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;SAC7B;AAED,QAAA,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC9D,QAAA,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAE9D,QAAA,MAAM,iBAAiB,GAAG,0BAA0B,CAAC,WAAW,EAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;QAC7F,MAAM,cAAc,GAAG,WAAW,CAC9B,UAAU,EACV,iBAAiB,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,EAChD,kBAAkB,CAAC,KAAK,CAC3B,CAAC;QACF,MAAM,cAAc,GAAG,WAAW,CAC9B,UAAU,EACV,iBAAiB,CAAC,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,EACjD,kBAAkB,CAAC,MAAM,CAC5B,CAAC;AAEF,QAAA,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;AAC9D,QAAA,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;AAE9D,QAAA,IAAI,KAAK,CAAC,IAAI,EAAE;AACZ,YAAA,kBAAkB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;SAC9C;AACL,KAAC,EACD;QACI,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;AACrB,KAAA,CACJ,CAAC;AACN;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePinchToZoom.js","sources":["
|
|
1
|
+
{"version":3,"file":"usePinchToZoom.js","sources":["src/internal/hooks/usePinchToZoom.ts"],"sourcesContent":["import { type RefCallback, useCallback, useRef } from 'react';\nimport { usePinch } from '@use-gesture/react';\nimport { MotionValue } from 'motion/react';\n\nimport { type GalleryItemController } from '@hh.ru/magritte-ui-media-viewer/internal/hooks/useGalleryItemController';\nimport { lerp, animateOffsetClamp, calcOriginOffset } from '@hh.ru/magritte-ui-media-viewer/internal/utils';\n\n// pinch to zoom хук, сохраняет позицию точки между пальцами при зуме неподвижной\nexport const usePinchToZoom = (\n controller: GalleryItemController,\n dimensions: MotionValue<DOMRectReadOnly | null>\n): { ref: RefCallback<HTMLDivElement> } => {\n const pinchStartScaleRef = useRef(1);\n const pinchOrigin = useRef({ x: 0, y: 0 });\n const pinchStartOffset = useRef({ x: 0, y: 0 });\n const itemRef = useRef<HTMLDivElement | null>(null);\n const refCallback: RefCallback<HTMLDivElement> = useCallback((el) => (itemRef.current = el), []);\n\n usePinch(\n (state) => {\n const viewPortDimensions = dimensions.get();\n controller.pinching = true;\n if (!viewPortDimensions) {\n return;\n }\n state.event.preventDefault();\n\n if (state.first) {\n controller.offsetX.stop();\n controller.offsetY.stop();\n pinchStartScaleRef.current = controller.scale.get();\n pinchOrigin.current = calcOriginOffset(state.origin, viewPortDimensions);\n pinchStartOffset.current = {\n x: controller.offsetX.get(),\n y: controller.offsetY.get(),\n };\n }\n\n const currentOrigin = calcOriginOffset(state.origin, viewPortDimensions);\n const newScale = pinchStartScaleRef.current * state.offset[0];\n controller.scale.set(newScale);\n controller.offsetX.set(\n lerp(pinchOrigin.current.x, pinchStartOffset.current.x, state.offset[0]) +\n (currentOrigin.x - pinchOrigin.current.x)\n );\n controller.offsetY.set(\n lerp(pinchOrigin.current.y, pinchStartOffset.current.y, state.offset[0]) +\n (currentOrigin.y - pinchOrigin.current.y)\n );\n\n if (state.last) {\n controller.pinching = false;\n animateOffsetClamp(controller, dimensions, [pinchOrigin.current.x, pinchOrigin.current.y]);\n }\n },\n {\n target: itemRef,\n eventOptions: { passive: false },\n filterTaps: true,\n from: () => [1, 0],\n }\n );\n\n return { ref: refCallback };\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSwipe.js","sources":["
|
|
1
|
+
{"version":3,"file":"useSwipe.js","sources":["src/internal/hooks/useSwipe.ts"],"sourcesContent":["import { useDrag } from '@use-gesture/react';\nimport { animate } from 'motion/react';\n\nimport { tokenSemanticAnimationTimeMDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { useMediaViewerContext } from '@hh.ru/magritte-ui-media-viewer/internal/context';\nimport { clamp, isScaleBiggerThanFit } from '@hh.ru/magritte-ui-media-viewer/internal/utils';\n\nexport const useSwipe = <T>(): ReturnType<typeof useDrag<T>> => {\n const globalContext = useMediaViewerContext();\n\n return useDrag<T>(\n (state) => {\n const controller = globalContext.currentSlideController.get();\n if (!controller || isScaleBiggerThanFit(controller) || controller.pinching) {\n state.cancel();\n return;\n }\n\n const viewPortDimensions = globalContext.viewPortDimensions.get();\n if (!viewPortDimensions) {\n return;\n }\n\n globalContext.currentSlideIndex.set(\n clamp(\n globalContext.currentSlideIndex.get() - state.delta[0] / viewPortDimensions.width,\n 0,\n globalContext.totalSlides.get() - 1\n )\n );\n\n if (state.last) {\n const targetIndex = clamp(\n Math.round(globalContext.currentSlideIndex.get()),\n 0,\n globalContext.totalSlides.get() - 1\n );\n const delta = Math.abs(globalContext.currentSlideIndex.get() - targetIndex);\n const animationDuration = tokenSemanticAnimationTimeMDuration * delta;\n animate(\n globalContext.currentSlideIndex,\n clamp(Math.round(globalContext.currentSlideIndex.get()), 0, globalContext.totalSlides.get() - 1),\n {\n duration: animationDuration / 1000,\n ease: EASE_BASE,\n }\n );\n }\n },\n {\n from: () => [0, 0],\n axis: 'x',\n keyboardDisplacement: 0,\n }\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAQO,MAAM,QAAQ,GAAG,MAAuC;AAC3D,IAAA,MAAM,aAAa,GAAG,qBAAqB,EAAE,CAAC;AAE9C,IAAA,OAAO,OAAO,CACV,CAAC,KAAK,KAAI;QACN,MAAM,UAAU,GAAG,aAAa,CAAC,sBAAsB,CAAC,GAAG,EAAE,CAAC;AAC9D,QAAA,IAAI,CAAC,UAAU,IAAI,oBAAoB,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,QAAQ,EAAE;YACxE,KAAK,CAAC,MAAM,EAAE,CAAC;YACf,OAAO;SACV;QAED,MAAM,kBAAkB,GAAG,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC;QAClE,IAAI,CAAC,kBAAkB,EAAE;YACrB,OAAO;SACV;AAED,QAAA,aAAa,CAAC,iBAAiB,CAAC,GAAG,CAC/B,KAAK,CACD,aAAa,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,KAAK,EACjF,CAAC,EACD,aAAa,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CACtC,CACJ,CAAC;AAEF,QAAA,IAAI,KAAK,CAAC,IAAI,EAAE;YACZ,MAAM,WAAW,GAAG,KAAK,CACrB,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,EACjD,CAAC,EACD,aAAa,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CACtC,CAAC;AACF,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,CAAC;AAC5E,YAAA,MAAM,iBAAiB,GAAG,mCAAmC,GAAG,KAAK,CAAC;AACtE,YAAA,OAAO,CACH,aAAa,CAAC,iBAAiB,EAC/B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,EAChG;gBACI,QAAQ,EAAE,iBAAiB,GAAG,IAAI;AAClC,gBAAA,IAAI,EAAE,SAAS;AAClB,aAAA,CACJ,CAAC;SACL;AACL,KAAC,EACD;QACI,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;AAClB,QAAA,IAAI,EAAE,GAAG;AACT,QAAA,oBAAoB,EAAE,CAAC;AAC1B,KAAA,CACJ,CAAC;AACN;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSwipeToClose.js","sources":["
|
|
1
|
+
{"version":3,"file":"useSwipeToClose.js","sources":["src/internal/hooks/useSwipeToClose.ts"],"sourcesContent":["import { useRef, useState } from 'react';\nimport { useDrag } from '@use-gesture/react';\nimport { animate } from 'motion/react';\n\nimport { tokenSemanticAnimationTimeMDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { MediaViewerContextValue } from '@hh.ru/magritte-ui-media-viewer/internal/context';\nimport { clamp, isScaleBiggerThanFit } from '@hh.ru/magritte-ui-media-viewer/internal/utils';\n\nconst PREVIEW_BAR_HEIGHT = 112;\n\nexport const useSwipeToClose = <T>(\n globalContext: MediaViewerContextValue\n): [ReturnType<typeof useDrag<T>>, boolean] => {\n const ignoreGestureRef = useRef<boolean>(true);\n const startCloseProgressRef = useRef<number>(0);\n const [isSwipeClosing, setIsSwipeClosing] = useState(false);\n\n return [\n useDrag<T>(\n (state) => {\n const controller = globalContext.currentSlideController.get();\n if (state.first) {\n controller?.offsetY.stop();\n ignoreGestureRef.current = !controller || isScaleBiggerThanFit(controller);\n startCloseProgressRef.current = globalContext.closeProgress.get();\n }\n\n if (ignoreGestureRef.current || !controller) {\n return;\n }\n\n const viewPortDimensions = globalContext.viewPortDimensions.get();\n if (!viewPortDimensions) {\n return;\n }\n\n setIsSwipeClosing(true);\n globalContext.closeProgress.set(\n clamp(\n Math.abs(state.offset[1]) / (viewPortDimensions.height / 3) + startCloseProgressRef.current,\n 0,\n 1\n )\n );\n\n controller.offsetY.set(state.offset[1]);\n\n if (state.last) {\n if (globalContext.closeProgress.get() >= 1) {\n animate(\n controller.offsetY,\n Math.sign(state.offset[1]) *\n (viewPortDimensions.height / 2 +\n (controller.contentSize.get()?.height ?? 0) / 2 +\n PREVIEW_BAR_HEIGHT),\n {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n onComplete: () => {\n setIsSwipeClosing(false);\n globalContext.close();\n },\n }\n );\n } else {\n ignoreGestureRef.current = true;\n animate(globalContext.closeProgress, 0, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n onComplete: () => setIsSwipeClosing(false),\n });\n animate(controller.offsetY, 0, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n }\n }\n },\n {\n from: () => [0, 0],\n axis: 'y',\n filterTaps: true,\n }\n ),\n isSwipeClosing,\n ];\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTapToToggleTools.js","sources":["
|
|
1
|
+
{"version":3,"file":"useTapToToggleTools.js","sources":["src/internal/hooks/useTapToToggleTools.ts"],"sourcesContent":["import { useRef, useCallback, type TouchEvent, type MouseEvent, useEffect } from 'react';\nimport { animate } from 'motion/react';\n\nimport { tokenSemanticAnimationTimeMDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { type MediaViewerContextValue } from '@hh.ru/magritte-ui-media-viewer/internal/context';\n\nconst DOUBLE_TAP_DELAY_MS = 300;\nconst TAP_MOVE_THRESHOLD = 10;\n\ninterface UseTapToToggleToolsResult {\n onTouchStart: (e: TouchEvent) => void;\n onTouchEnd: (e: TouchEvent) => void;\n onClick: (e: MouseEvent) => void;\n}\n\nconst isInteractiveTarget = (target: EventTarget | null): boolean => {\n return target instanceof Element && !!target.closest('[data-media-viewer-interactive]');\n};\n\nexport const useTapToToggleTools = (context: MediaViewerContextValue): UseTapToToggleToolsResult => {\n const tapTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const touchStartRef = useRef<{ x: number; y: number; target: EventTarget | null } | null>(null);\n const hadTouchRef = useRef<boolean>(false);\n\n const toggleTools = useCallback(() => {\n animate(context.hideToolsProgress, Math.round(context.hideToolsProgress.get()) === 0 ? 1 : 0, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n }, [context]);\n\n const onTouchStart = useCallback((event: TouchEvent) => {\n // Помечаем что было touch-событие, чтобы игнорировать последующий click\n hadTouchRef.current = true;\n\n // Игнорируем multi-touch (pinch zoom)\n if (event.touches.length !== 1) {\n touchStartRef.current = null;\n return;\n }\n\n const touch = event.touches[0];\n touchStartRef.current = { x: touch.clientX, y: touch.clientY, target: event.target };\n }, []);\n\n const onTouchEnd = useCallback(\n (event: TouchEvent) => {\n const touchStart = touchStartRef.current;\n touchStartRef.current = null;\n\n // Если не было валидного touchStart или это multi-touch\n if (!touchStart || event.changedTouches.length !== 1) {\n return;\n }\n\n // Проверяем интерактивный элемент\n if (isInteractiveTarget(touchStart.target)) {\n return;\n }\n\n const touch = event.changedTouches[0];\n const dx = touch.clientX - touchStart.x;\n const dy = touch.clientY - touchStart.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n // Это был свайп, не тап\n if (distance > TAP_MOVE_THRESHOLD) {\n return;\n }\n\n // Это двойной тап - отменяем pending toggle\n if (tapTimerRef.current) {\n clearTimeout(tapTimerRef.current);\n tapTimerRef.current = null;\n return;\n }\n\n // Single tap — ждём возможный второй\n tapTimerRef.current = setTimeout(() => {\n tapTimerRef.current = null;\n toggleTools();\n }, DOUBLE_TAP_DELAY_MS);\n },\n [toggleTools]\n );\n\n const onClick = useCallback(\n (event: MouseEvent) => {\n // Игнорируем click после touch (браузер генерирует оба)\n if (hadTouchRef.current) {\n hadTouchRef.current = false;\n return;\n }\n\n if (isInteractiveTarget(event.target)) {\n return;\n }\n\n // Это двойной клик - отменяем pending toggle\n if (tapTimerRef.current) {\n clearTimeout(tapTimerRef.current);\n tapTimerRef.current = null;\n return;\n }\n\n // Single click - ждём возможный второй\n tapTimerRef.current = setTimeout(() => {\n tapTimerRef.current = null;\n toggleTools();\n }, DOUBLE_TAP_DELAY_MS);\n },\n [toggleTools]\n );\n\n useEffect(\n () => () => {\n tapTimerRef.current && clearTimeout(tapTimerRef.current);\n },\n []\n );\n\n return { onTouchStart, onTouchEnd, onClick };\n};\n"],"names":[],"mappings":";;;;;AAOA,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAQ9B,MAAM,mBAAmB,GAAG,CAAC,MAA0B,KAAa;AAChE,IAAA,OAAO,MAAM,YAAY,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;AAC5F,CAAC,CAAC;AAEW,MAAA,mBAAmB,GAAG,CAAC,OAAgC,KAA+B;AAC/F,IAAA,MAAM,WAAW,GAAG,MAAM,CAAuC,IAAI,CAAC,CAAC;AACvE,IAAA,MAAM,aAAa,GAAG,MAAM,CAA8D,IAAI,CAAC,CAAC;AAChG,IAAA,MAAM,WAAW,GAAG,MAAM,CAAU,KAAK,CAAC,CAAC;AAE3C,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,MAAK;QACjC,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YAC1F,QAAQ,EAAE,mCAAmC,GAAG,IAAI;AACpD,YAAA,IAAI,EAAE,SAAS;AAClB,SAAA,CAAC,CAAC;AACP,KAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AAEd,IAAA,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,KAAiB,KAAI;;AAEnD,QAAA,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;;QAG3B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;AAC5B,YAAA,aAAa,CAAC,OAAO,GAAG,IAAI,CAAC;YAC7B,OAAO;SACV;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/B,aAAa,CAAC,OAAO,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;KACxF,EAAE,EAAE,CAAC,CAAC;AAEP,IAAA,MAAM,UAAU,GAAG,WAAW,CAC1B,CAAC,KAAiB,KAAI;AAClB,QAAA,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC;AACzC,QAAA,aAAa,CAAC,OAAO,GAAG,IAAI,CAAC;;QAG7B,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE;YAClD,OAAO;SACV;;AAGD,QAAA,IAAI,mBAAmB,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;YACxC,OAAO;SACV;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC;QACxC,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC;AACxC,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;;AAG9C,QAAA,IAAI,QAAQ,GAAG,kBAAkB,EAAE;YAC/B,OAAO;SACV;;AAGD,QAAA,IAAI,WAAW,CAAC,OAAO,EAAE;AACrB,YAAA,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAClC,YAAA,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;YAC3B,OAAO;SACV;;AAGD,QAAA,WAAW,CAAC,OAAO,GAAG,UAAU,CAAC,MAAK;AAClC,YAAA,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;AAC3B,YAAA,WAAW,EAAE,CAAC;SACjB,EAAE,mBAAmB,CAAC,CAAC;AAC5B,KAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;AAEF,IAAA,MAAM,OAAO,GAAG,WAAW,CACvB,CAAC,KAAiB,KAAI;;AAElB,QAAA,IAAI,WAAW,CAAC,OAAO,EAAE;AACrB,YAAA,WAAW,CAAC,OAAO,GAAG,KAAK,CAAC;YAC5B,OAAO;SACV;AAED,QAAA,IAAI,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;YACnC,OAAO;SACV;;AAGD,QAAA,IAAI,WAAW,CAAC,OAAO,EAAE;AACrB,YAAA,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAClC,YAAA,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;YAC3B,OAAO;SACV;;AAGD,QAAA,WAAW,CAAC,OAAO,GAAG,UAAU,CAAC,MAAK;AAClC,YAAA,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;AAC3B,YAAA,WAAW,EAAE,CAAC;SACjB,EAAE,mBAAmB,CAAC,CAAC;AAC5B,KAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;AAEF,IAAA,SAAS,CACL,MAAM,MAAK;QACP,WAAW,CAAC,OAAO,IAAI,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;KAC5D,EACD,EAAE,CACL,CAAC;AAEF,IAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AACjD;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVirtualization.js","sources":["
|
|
1
|
+
{"version":3,"file":"useVirtualization.js","sources":["src/internal/hooks/useVirtualization.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { type MotionValue, motionValue, useMotionValueEvent } from 'motion/react';\n\nimport { useInitOnce } from '@hh.ru/magritte-ui-media-viewer/internal/utils';\n\nexport interface VirtualizationVisibleRange {\n startIndex: MotionValue<number>;\n endIndex: MotionValue<number>;\n}\n\nconst calcVisibleRange = (currentIndex: number, batchSize: number): { startIndex: number; endIndex: number } => {\n const batch = Math.floor(currentIndex / batchSize);\n return {\n startIndex: Math.max(0, (batch - 1) * batchSize),\n endIndex: (batch + 2) * batchSize,\n };\n};\n\nexport const useVirtualization = (\n batchSize: number,\n currentSlideIndex: MotionValue<number>\n): VirtualizationVisibleRange => {\n const visibleRange = useInitOnce(() => {\n const initialRange = calcVisibleRange(currentSlideIndex.get(), batchSize);\n return {\n startIndex: motionValue(initialRange.startIndex),\n endIndex: motionValue(initialRange.endIndex),\n };\n });\n\n useMotionValueEvent(currentSlideIndex, 'change', (latest) => {\n const newRange = calcVisibleRange(latest, batchSize);\n visibleRange.startIndex.set(newRange.startIndex);\n visibleRange.endIndex.set(newRange.endIndex);\n });\n\n return visibleRange;\n};\n\nexport const useOnVisibleRangeChange = (\n visibleRange: VirtualizationVisibleRange,\n callback: (startIndex: number, endIndex: number) => void\n): void => {\n const cbRef = useRef(callback);\n cbRef.current = callback;\n const visibleRangeRef = useRef(visibleRange);\n visibleRangeRef.current = visibleRange;\n const lastProcessedRange = useRef({\n startIndex: Number.MAX_SAFE_INTEGER,\n endIndex: Number.MIN_SAFE_INTEGER,\n });\n const onRangeChange = useInitOnce(() => () => {\n const startIndex = visibleRangeRef.current.startIndex.get();\n const endIndex = visibleRangeRef.current.endIndex.get();\n if (lastProcessedRange.current.startIndex === startIndex && lastProcessedRange.current.endIndex === endIndex) {\n return;\n }\n cbRef.current(startIndex, endIndex);\n lastProcessedRange.current = { startIndex, endIndex };\n });\n useEffect(() => {\n onRangeChange();\n }, [visibleRange, onRangeChange]);\n\n useMotionValueEvent(visibleRange.startIndex, 'change', onRangeChange);\n useMotionValueEvent(visibleRange.endIndex, 'change', onRangeChange);\n};\n\nexport const useIsVisible = (index: number, visibleRange: VirtualizationVisibleRange): boolean => {\n const [isVisible, setIsVisible] = useState(\n () => visibleRange.startIndex.get() <= index && index < visibleRange.endIndex.get()\n );\n\n useOnVisibleRangeChange(visibleRange, (startIndex, endIndex) => {\n setIsVisible(startIndex <= index && index < endIndex);\n });\n\n return isVisible;\n};\n"],"names":[],"mappings":";;;;;;AAUA,MAAM,gBAAgB,GAAG,CAAC,YAAoB,EAAE,SAAiB,KAA8C;IAC3G,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;IACnD,OAAO;AACH,QAAA,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,IAAI,SAAS,CAAC;AAChD,QAAA,QAAQ,EAAE,CAAC,KAAK,GAAG,CAAC,IAAI,SAAS;KACpC,CAAC;AACN,CAAC,CAAC;MAEW,iBAAiB,GAAG,CAC7B,SAAiB,EACjB,iBAAsC,KACV;AAC5B,IAAA,MAAM,YAAY,GAAG,WAAW,CAAC,MAAK;QAClC,MAAM,YAAY,GAAG,gBAAgB,CAAC,iBAAiB,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;QAC1E,OAAO;AACH,YAAA,UAAU,EAAE,WAAW,CAAC,YAAY,CAAC,UAAU,CAAC;AAChD,YAAA,QAAQ,EAAE,WAAW,CAAC,YAAY,CAAC,QAAQ,CAAC;SAC/C,CAAC;AACN,KAAC,CAAC,CAAC;IAEH,mBAAmB,CAAC,iBAAiB,EAAE,QAAQ,EAAE,CAAC,MAAM,KAAI;QACxD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACrD,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACjD,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACjD,KAAC,CAAC,CAAC;AAEH,IAAA,OAAO,YAAY,CAAC;AACxB,EAAE;MAEW,uBAAuB,GAAG,CACnC,YAAwC,EACxC,QAAwD,KAClD;AACN,IAAA,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC/B,IAAA,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAC;AACzB,IAAA,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAC7C,IAAA,eAAe,CAAC,OAAO,GAAG,YAAY,CAAC;IACvC,MAAM,kBAAkB,GAAG,MAAM,CAAC;QAC9B,UAAU,EAAE,MAAM,CAAC,gBAAgB;QACnC,QAAQ,EAAE,MAAM,CAAC,gBAAgB;AACpC,KAAA,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,MAAK;QACzC,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;QAC5D,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;AACxD,QAAA,IAAI,kBAAkB,CAAC,OAAO,CAAC,UAAU,KAAK,UAAU,IAAI,kBAAkB,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE;YAC1G,OAAO;SACV;AACD,QAAA,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACpC,kBAAkB,CAAC,OAAO,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;AAC1D,KAAC,CAAC,CAAC;IACH,SAAS,CAAC,MAAK;AACX,QAAA,aAAa,EAAE,CAAC;AACpB,KAAC,EAAE,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC;IAElC,mBAAmB,CAAC,YAAY,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IACtE,mBAAmB,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;AACxE,EAAE;MAEW,YAAY,GAAG,CAAC,KAAa,EAAE,YAAwC,KAAa;AAC7F,IAAA,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CACtC,MAAM,YAAY,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,KAAK,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,EAAE,CACtF,CAAC;IAEF,uBAAuB,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,QAAQ,KAAI;QAC3D,YAAY,CAAC,UAAU,IAAI,KAAK,IAAI,KAAK,GAAG,QAAQ,CAAC,CAAC;AAC1D,KAAC,CAAC,CAAC;AAEH,IAAA,OAAO,SAAS,CAAC;AACrB;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWheelToZoom.js","sources":["
|
|
1
|
+
{"version":3,"file":"useWheelToZoom.js","sources":["src/internal/hooks/useWheelToZoom.ts"],"sourcesContent":["import { useEffect, useRef, WheelEventHandler } from 'react';\nimport { MotionValue } from 'motion/react';\n\nimport { type GalleryItemController } from '@hh.ru/magritte-ui-media-viewer/internal/hooks/useGalleryItemController';\nimport {\n lerp,\n animateOffsetClamp,\n useInitOnce,\n clamp,\n calcOriginOffset,\n} from '@hh.ru/magritte-ui-media-viewer/internal/utils';\n\nexport const useWheelToZoom = (\n controller: GalleryItemController,\n dimensions: MotionValue<DOMRectReadOnly | null>\n): { onWheel: WheelEventHandler } => {\n const centerAnimRef = useRef<ReturnType<typeof setTimeout>>();\n const onWheel = useInitOnce<WheelEventHandler>(() => (event) => {\n centerAnimRef.current && clearTimeout(centerAnimRef.current);\n const dimensionsValue = dimensions.get();\n const zoomStops = controller.zoomStops.get()[(controller.rotation.get() ?? 0) % 2];\n if (controller.pinching || !dimensionsValue || !zoomStops || zoomStops.length === 0) {\n return;\n }\n\n const currentOrigin = calcOriginOffset([event.clientX, event.clientY], dimensionsValue);\n const newScale = clamp(\n controller.scale.get() - event.deltaY / 100,\n zoomStops[0],\n zoomStops[zoomStops.length - 1]\n );\n controller.offsetX.set(lerp(currentOrigin.x, controller.offsetX.get(), newScale / controller.scale.get()));\n controller.offsetY.set(lerp(currentOrigin.y, controller.offsetY.get(), newScale / controller.scale.get()));\n controller.scale.set(newScale);\n centerAnimRef.current = setTimeout(() => animateOffsetClamp(controller, dimensions), 300);\n });\n\n useEffect(() => () => centerAnimRef.current && clearTimeout(centerAnimRef.current), []);\n\n return { onWheel };\n};\n"],"names":[],"mappings":";;;;;;MAYa,cAAc,GAAG,CAC1B,UAAiC,EACjC,UAA+C,KACf;AAChC,IAAA,MAAM,aAAa,GAAG,MAAM,EAAiC,CAAC;IAC9D,MAAM,OAAO,GAAG,WAAW,CAAoB,MAAM,CAAC,KAAK,KAAI;QAC3D,aAAa,CAAC,OAAO,IAAI,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AAC7D,QAAA,MAAM,eAAe,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACnF,QAAA,IAAI,UAAU,CAAC,QAAQ,IAAI,CAAC,eAAe,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;YACjF,OAAO;SACV;AAED,QAAA,MAAM,aAAa,GAAG,gBAAgB,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC;AACxF,QAAA,MAAM,QAAQ,GAAG,KAAK,CAClB,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,MAAM,GAAG,GAAG,EAC3C,SAAS,CAAC,CAAC,CAAC,EACZ,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAClC,CAAC;AACF,QAAA,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAC3G,QAAA,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAC3G,QAAA,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC/B,QAAA,aAAa,CAAC,OAAO,GAAG,UAAU,CAAC,MAAM,kBAAkB,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;AAC9F,KAAC,CAAC,CAAC;IAEH,SAAS,CAAC,MAAM,MAAM,aAAa,CAAC,OAAO,IAAI,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAExF,OAAO,EAAE,OAAO,EAAE,CAAC;AACvB;;;;"}
|
package/internal/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../src/internal/utils.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { type MotionValue, animate, useMotionValueEvent } from 'motion/react';\n\nimport { tokenSemanticAnimationTimeMDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { type GalleryItemController } from '@hh.ru/magritte-ui-media-viewer/internal/hooks/useGalleryItemController';\nimport { type FitFillValues } from '@hh.ru/magritte-ui-media-viewer/public/types';\n\nexport const useInitOnce = <T>(initializer: () => T): T => {\n const ref = useRef<{ initialized: boolean; value?: T }>({ initialized: false });\n\n if (!ref.current.initialized) {\n ref.current.value = initializer();\n ref.current.initialized = true;\n }\n\n return ref.current.value as T;\n};\n\nconst SCALE_EPSILON = 0.001;\n\nexport function isClose(a: number, b: number, epsilon: number = SCALE_EPSILON): boolean {\n return Math.abs(a - b) < epsilon;\n}\n\nexport function matchesFitOrFill(scale: number, fitFill: FitFillValues): 'fit' | 'fill' | null {\n if (isClose(scale, fitFill.fit)) {\n return 'fit';\n }\n if (isClose(scale, fitFill.fill)) {\n return 'fill';\n }\n return null;\n}\n\nexport const clamp = (value: number, min: number, max: number): number => {\n return Math.min(Math.max(value, min), max);\n};\n\nexport const useDetectDiscreteChange = (value: MotionValue<number>): (() => boolean) => {\n const prevValueRef = useRef<number>(value.get());\n const isLastChangeDiscreteRef = useRef<boolean>(false);\n useMotionValueEvent(value, 'change', (newValue) => {\n isLastChangeDiscreteRef.current = Math.abs(newValue - prevValueRef.current) >= 1;\n prevValueRef.current = newValue;\n });\n const check = useInitOnce(() => () => isLastChangeDiscreteRef.current);\n return check;\n};\n\nexport const lerp = (from: number, to: number, progress: number): number => from + (to - from) * progress;\n\nexport const getDimensionsAfterRotation = (\n size: { width: number; height: number },\n rotation: number\n): { width: number; height: number } => {\n if (rotation % 2 === 0) {\n return size;\n }\n return { width: size.height, height: size.width };\n};\n\nexport const clampOffset = (offset: number, imageSize: number, containerSize: number): number => {\n const maxOffset = Math.max(0, (imageSize - containerSize) / 2);\n return clamp(offset, -maxOffset, maxOffset);\n};\n\nexport const animateOffsetClamp = (\n controller: GalleryItemController,\n dimensions: MotionValue<DOMRectReadOnly | null>,\n anchorPoint?: [number, number]\n): void => {\n const contentSize = controller.contentSize.get();\n const rotation = controller.rotation.get() ?? 0;\n const zoomStops = controller.zoomStops.get()[rotation % 2];\n const viewPortDimensions = dimensions.get();\n if (!viewPortDimensions || !contentSize) {\n return;\n }\n\n const sizeAfterRotation = getDimensionsAfterRotation(contentSize, rotation);\n const scale = clamp(controller.scale.get(), zoomStops[0], zoomStops[zoomStops.length - 1]);\n const offset = anchorPoint\n ? {\n x: lerp(anchorPoint[0], controller.offsetX.get(), scale / controller.scale.get()),\n y: lerp(anchorPoint[1], controller.offsetY.get(), scale / controller.scale.get()),\n }\n : {\n x: controller.offsetX.get(),\n y: controller.offsetY.get(),\n };\n const clampedOffsetX = clampOffset(offset.x, sizeAfterRotation.width * scale, viewPortDimensions.width);\n const clampedOffsetY = clampOffset(offset.y, sizeAfterRotation.height * scale, viewPortDimensions.height);\n\n if (!isClose(controller.offsetX.get(), clampedOffsetX)) {\n animate(controller.offsetX, clampedOffsetX, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n }\n\n if (!isClose(controller.offsetY.get(), clampedOffsetY)) {\n animate(controller.offsetY, clampedOffsetY, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n }\n\n if (!isClose(controller.scale.get(), scale)) {\n animate(controller.scale, scale, { duration: tokenSemanticAnimationTimeMDuration / 1000, ease: EASE_BASE });\n }\n};\n\nexport const isScaleBiggerThanFit = (controller: GalleryItemController): boolean => {\n const fitFill = controller.fitFillScales.get();\n if (fitFill === null) {\n return false;\n }\n const rotation = controller.rotation.get();\n const fitFillForRotation = fitFill[rotation % 2];\n return controller.scale.get() > fitFillForRotation.fit + SCALE_EPSILON;\n};\n\nexport const findNextValue = (values: number[], current: number, bigger: boolean): number => {\n if (bigger) {\n for (const value of values) {\n if (value > current) {\n return value;\n }\n }\n return values[values.length - 1];\n }\n for (let i = values.length - 1; i >= 0; i--) {\n const value = values[i];\n if (value < current) {\n return value;\n }\n }\n\n return values[0];\n};\n\nexport const calcOriginOffset = (\n origin: [number, number],\n viewportDimensions: DOMRectReadOnly\n): { x: number; y: number } => {\n return {\n x: origin[0] - viewportDimensions.left - viewportDimensions.width / 2,\n y: origin[1] - viewportDimensions.top - viewportDimensions.height / 2,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["src/internal/utils.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { type MotionValue, animate, useMotionValueEvent } from 'motion/react';\n\nimport { tokenSemanticAnimationTimeMDuration } from '@hh.ru/magritte-design-tokens/types';\nimport { EASE_BASE } from '@hh.ru/magritte-ui-media-viewer/internal/animations';\nimport { type GalleryItemController } from '@hh.ru/magritte-ui-media-viewer/internal/hooks/useGalleryItemController';\nimport { type FitFillValues } from '@hh.ru/magritte-ui-media-viewer/public/types';\n\nexport const useInitOnce = <T>(initializer: () => T): T => {\n const ref = useRef<{ initialized: boolean; value?: T }>({ initialized: false });\n\n if (!ref.current.initialized) {\n ref.current.value = initializer();\n ref.current.initialized = true;\n }\n\n return ref.current.value as T;\n};\n\nconst SCALE_EPSILON = 0.001;\n\nexport function isClose(a: number, b: number, epsilon: number = SCALE_EPSILON): boolean {\n return Math.abs(a - b) < epsilon;\n}\n\nexport function matchesFitOrFill(scale: number, fitFill: FitFillValues): 'fit' | 'fill' | null {\n if (isClose(scale, fitFill.fit)) {\n return 'fit';\n }\n if (isClose(scale, fitFill.fill)) {\n return 'fill';\n }\n return null;\n}\n\nexport const clamp = (value: number, min: number, max: number): number => {\n return Math.min(Math.max(value, min), max);\n};\n\nexport const useDetectDiscreteChange = (value: MotionValue<number>): (() => boolean) => {\n const prevValueRef = useRef<number>(value.get());\n const isLastChangeDiscreteRef = useRef<boolean>(false);\n useMotionValueEvent(value, 'change', (newValue) => {\n isLastChangeDiscreteRef.current = Math.abs(newValue - prevValueRef.current) >= 1;\n prevValueRef.current = newValue;\n });\n const check = useInitOnce(() => () => isLastChangeDiscreteRef.current);\n return check;\n};\n\nexport const lerp = (from: number, to: number, progress: number): number => from + (to - from) * progress;\n\nexport const getDimensionsAfterRotation = (\n size: { width: number; height: number },\n rotation: number\n): { width: number; height: number } => {\n if (rotation % 2 === 0) {\n return size;\n }\n return { width: size.height, height: size.width };\n};\n\nexport const clampOffset = (offset: number, imageSize: number, containerSize: number): number => {\n const maxOffset = Math.max(0, (imageSize - containerSize) / 2);\n return clamp(offset, -maxOffset, maxOffset);\n};\n\nexport const animateOffsetClamp = (\n controller: GalleryItemController,\n dimensions: MotionValue<DOMRectReadOnly | null>,\n anchorPoint?: [number, number]\n): void => {\n const contentSize = controller.contentSize.get();\n const rotation = controller.rotation.get() ?? 0;\n const zoomStops = controller.zoomStops.get()[rotation % 2];\n const viewPortDimensions = dimensions.get();\n if (!viewPortDimensions || !contentSize) {\n return;\n }\n\n const sizeAfterRotation = getDimensionsAfterRotation(contentSize, rotation);\n const scale = clamp(controller.scale.get(), zoomStops[0], zoomStops[zoomStops.length - 1]);\n const offset = anchorPoint\n ? {\n x: lerp(anchorPoint[0], controller.offsetX.get(), scale / controller.scale.get()),\n y: lerp(anchorPoint[1], controller.offsetY.get(), scale / controller.scale.get()),\n }\n : {\n x: controller.offsetX.get(),\n y: controller.offsetY.get(),\n };\n const clampedOffsetX = clampOffset(offset.x, sizeAfterRotation.width * scale, viewPortDimensions.width);\n const clampedOffsetY = clampOffset(offset.y, sizeAfterRotation.height * scale, viewPortDimensions.height);\n\n if (!isClose(controller.offsetX.get(), clampedOffsetX)) {\n animate(controller.offsetX, clampedOffsetX, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n }\n\n if (!isClose(controller.offsetY.get(), clampedOffsetY)) {\n animate(controller.offsetY, clampedOffsetY, {\n duration: tokenSemanticAnimationTimeMDuration / 1000,\n ease: EASE_BASE,\n });\n }\n\n if (!isClose(controller.scale.get(), scale)) {\n animate(controller.scale, scale, { duration: tokenSemanticAnimationTimeMDuration / 1000, ease: EASE_BASE });\n }\n};\n\nexport const isScaleBiggerThanFit = (controller: GalleryItemController): boolean => {\n const fitFill = controller.fitFillScales.get();\n if (fitFill === null) {\n return false;\n }\n const rotation = controller.rotation.get();\n const fitFillForRotation = fitFill[rotation % 2];\n return controller.scale.get() > fitFillForRotation.fit + SCALE_EPSILON;\n};\n\nexport const findNextValue = (values: number[], current: number, bigger: boolean): number => {\n if (bigger) {\n for (const value of values) {\n if (value > current) {\n return value;\n }\n }\n return values[values.length - 1];\n }\n for (let i = values.length - 1; i >= 0; i--) {\n const value = values[i];\n if (value < current) {\n return value;\n }\n }\n\n return values[0];\n};\n\nexport const calcOriginOffset = (\n origin: [number, number],\n viewportDimensions: DOMRectReadOnly\n): { x: number; y: number } => {\n return {\n x: origin[0] - viewportDimensions.left - viewportDimensions.width / 2,\n y: origin[1] - viewportDimensions.top - viewportDimensions.height / 2,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
var styles = {"media-viewer":"magritte-media-viewer___KnrXP_1-2-3","mediaViewer":"magritte-media-viewer___KnrXP_1-2-3","gallery-placeholder":"magritte-gallery-placeholder___rUoGL_1-2-3","galleryPlaceholder":"magritte-gallery-placeholder___rUoGL_1-2-3","media-viewer-gallery":"magritte-media-viewer-gallery___P0SnN_1-2-3","mediaViewerGallery":"magritte-media-viewer-gallery___P0SnN_1-2-3","gallery-item":"magritte-gallery-item___Js0Z5_1-2-3","galleryItem":"magritte-gallery-item___Js0Z5_1-2-3","gallery-item-transform-container":"magritte-gallery-item-transform-container___N8-sA_1-2-3","galleryItemTransformContainer":"magritte-gallery-item-transform-container___N8-sA_1-2-3","preview-counter":"magritte-preview-counter___uP2Hc_1-2-3","previewCounter":"magritte-preview-counter___uP2Hc_1-2-3","with-description":"magritte-with-description___-w7ld_1-2-3","withDescription":"magritte-with-description___-w7ld_1-2-3","counter-number":"magritte-counter-number___gUpMp_1-2-3","counterNumber":"magritte-counter-number___gUpMp_1-2-3","no-description-placeholder":"magritte-no-description-placeholder___qc6h2_1-2-3","noDescriptionPlaceholder":"magritte-no-description-placeholder___qc6h2_1-2-3","preview-zoom-control":"magritte-preview-zoom-control___026jA_1-2-3","previewZoomControl":"magritte-preview-zoom-control___026jA_1-2-3","preview-container":"magritte-preview-container___nwjNY_1-2-3","previewContainer":"magritte-preview-container___nwjNY_1-2-3","preview":"magritte-preview___0Ge4C_1-2-3","preview-list":"magritte-preview-list___SAXLZ_1-2-3","previewList":"magritte-preview-list___SAXLZ_1-2-3","preview-item":"magritte-preview-item___gz5f2_1-2-3","previewItem":"magritte-preview-item___gz5f2_1-2-3","preview-item-container":"magritte-preview-item-container___JDVsk_1-2-3","previewItemContainer":"magritte-preview-item-container___JDVsk_1-2-3","media-viewer-toolbar":"magritte-media-viewer-toolbar___2C8nr_1-2-3","mediaViewerToolbar":"magritte-media-viewer-toolbar___2C8nr_1-2-3","no-description":"magritte-no-description___NebrT_1-2-3","noDescription":"magritte-no-description___NebrT_1-2-3","media-viewer-toolbar-left":"magritte-media-viewer-toolbar-left___YzkJt_1-2-3","mediaViewerToolbarLeft":"magritte-media-viewer-toolbar-left___YzkJt_1-2-3","media-viewer-toolbar-right":"magritte-media-viewer-toolbar-right___kBER9_1-2-3","mediaViewerToolbarRight":"magritte-media-viewer-toolbar-right___kBER9_1-2-3","prev-button":"magritte-prev-button___WMYjR_1-2-3","prevButton":"magritte-prev-button___WMYjR_1-2-3","next-button":"magritte-next-button___f8hJT_1-2-3","nextButton":"magritte-next-button___f8hJT_1-2-3","slide-button":"magritte-slide-button___sY8LB_1-2-3","slideButton":"magritte-slide-button___sY8LB_1-2-3","preview-placeholder":"magritte-preview-placeholder___yuhW1_1-2-3","previewPlaceholder":"magritte-preview-placeholder___yuhW1_1-2-3","gallery-item-loader":"magritte-gallery-item-loader___70TDe_1-2-3","galleryItemLoader":"magritte-gallery-item-loader___70TDe_1-2-3","gallery-item-error-container":"magritte-gallery-item-error-container___Z-HyZ_1-2-3","galleryItemErrorContainer":"magritte-gallery-item-error-container___Z-HyZ_1-2-3","description-bottom-sheet-content":"magritte-description-bottom-sheet-content___swnEV_1-2-3","descriptionBottomSheetContent":"magritte-description-bottom-sheet-content___swnEV_1-2-3","header":"magritte-header___egZXt_1-2-3","footer":"magritte-footer___rOH-M_1-2-3","description":"magritte-description___dYc-E_1-2-3"};
|
|
3
|
+
|
|
4
|
+
export { styles as s };
|
|
5
|
+
//# sourceMappingURL=media-viewer-DhN96vgd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-viewer-DhN96vgd.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|