js-cloudimage-360-view 4.8.0 → 4.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -3
- package/dist/js-cloudimage-360-view.min.js +7 -7
- package/dist/react/ci360-B2r9u7br.js +65 -0
- package/dist/react/ci360-B2r9u7br.js.map +1 -0
- package/dist/react/{ci360-BJ_JCEiA.mjs → ci360-BFobl9uu.mjs} +1076 -859
- package/dist/react/ci360-BFobl9uu.mjs.map +1 -0
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.ts +10 -0
- package/dist/react/index.js +182 -165
- package/dist/react/index.js.map +1 -1
- package/dist/react/style.css +1 -1
- package/package.json +2 -1
- package/src/react/types.d.ts +10 -0
- package/dist/react/ci360-BJ_JCEiA.mjs.map +0 -1
- package/dist/react/ci360-DdSVW_xW.js +0 -65
- package/dist/react/ci360-DdSVW_xW.js.map +0 -1
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/react/useCI360.ts","../../src/react/CI360Viewer.tsx"],"sourcesContent":["import { useEffect, useRef, useState, useId, useCallback, type RefObject } from 'react';\nimport type {\n CI360Config,\n CI360ViewerInstance,\n UseCI360Return,\n UseCI360Options,\n} from './types';\n\n// Import CI360 class dynamically to avoid SSR issues\nlet CI360Class: any = null;\n\n/**\n * Custom hook for integrating CI360 viewer with React\n *\n * @param containerRef - React ref to the container element\n * @param config - CI360 configuration options\n * @returns Object containing viewer instance and ready state\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const containerRef = useRef<HTMLDivElement>(null);\n * const { viewer, isReady } = useCI360(containerRef, {\n * folder: 'https://example.com/images/',\n * filenameX: 'image-{index}.jpg',\n * amountX: 36,\n * });\n *\n * return <div ref={containerRef} />;\n * }\n * ```\n */\nexport function useCI360(\n containerRef: RefObject<HTMLDivElement | null>,\n config: UseCI360Options\n): UseCI360Return {\n const [isReady, setIsReady] = useState(false);\n const viewerRef = useRef<CI360ViewerInstance | null>(null);\n const ci360Ref = useRef<any>(null);\n const uniqueId = useId();\n\n // Initialize viewer\n useEffect(() => {\n // SSR guard\n if (typeof window === 'undefined') return;\n if (!containerRef.current) return;\n if (config.autoInit === false) return;\n\n let isMounted = true;\n const container = containerRef.current;\n\n const initViewer = async () => {\n try {\n // Dynamically import CI360 to avoid SSR issues\n if (!CI360Class) {\n const module = await import('../ci360');\n CI360Class = module.default;\n }\n\n if (!container || !isMounted) return;\n\n // Set a unique ID on the container if not present\n if (!container.id) {\n container.id = `ci360-${uniqueId.replace(/:/g, '')}`;\n }\n\n // Wrap user callbacks to update React state\n const wrappedConfig: CI360Config = {\n ...config,\n onReady: (data) => {\n if (isMounted) {\n setIsReady(true);\n config.onReady?.(data);\n }\n },\n };\n\n // Create CI360 instance and initialize viewer\n ci360Ref.current = new CI360Class();\n viewerRef.current = ci360Ref.current.init(container, wrappedConfig);\n } catch (error) {\n console.error('Failed to initialize CI360 viewer:', error);\n }\n };\n\n initViewer();\n\n // Cleanup on unmount or when dependencies change\n return () => {\n isMounted = false;\n if (viewerRef.current) {\n try {\n viewerRef.current.destroy();\n } catch (e) {\n // Ignore errors during cleanup - element may already be detached\n }\n viewerRef.current = null;\n }\n ci360Ref.current = null;\n setIsReady(false);\n };\n }, [\n config.folder,\n config.filenameX,\n config.filenameY,\n config.imageListX,\n config.imageListY,\n config.amountX,\n config.amountY,\n config.hotspots,\n config.theme,\n config.aspectRatio,\n config.cropAspectRatio,\n config.cropGravity,\n uniqueId,\n ]);\n\n // Stable getter to always return current viewer (avoids stale closures)\n const getViewer = useCallback(() => viewerRef.current, []);\n\n return {\n viewer: viewerRef.current,\n isReady,\n getViewer,\n };\n}\n\nexport default useCI360;\n","import {\n useRef,\n useImperativeHandle,\n forwardRef,\n useMemo,\n type ForwardRefRenderFunction,\n} from 'react';\nimport { useCI360 } from './useCI360';\nimport type {\n CI360ViewerProps,\n CI360ViewerRef,\n CI360Config,\n} from './types';\n\n/**\n * CI360Viewer React Component\n *\n * A declarative React wrapper for the CI360 360-degree image viewer.\n *\n * @example\n * ```tsx\n * import { CI360Viewer } from 'js-cloudimage-360-view/react';\n * import 'js-cloudimage-360-view/css';\n *\n * function ProductView() {\n * return (\n * <CI360Viewer\n * folder=\"https://example.com/images/\"\n * filenameX=\"product-{index}.jpg\"\n * amountX={36}\n * autoplay\n * fullscreen\n * />\n * );\n * }\n * ```\n *\n * @example With ref for imperative control\n * ```tsx\n * import { useRef } from 'react';\n * import { CI360Viewer, CI360ViewerRef } from 'js-cloudimage-360-view/react';\n *\n * function ProductView() {\n * const viewerRef = useRef<CI360ViewerRef>(null);\n *\n * return (\n * <>\n * <CI360Viewer\n * ref={viewerRef}\n * folder=\"https://example.com/images/\"\n * filenameX=\"{index}.jpg\"\n * amountX={36}\n * onSpin={(e) => console.log(`Frame: ${e.activeImageX}`)}\n * />\n * <button onClick={() => viewerRef.current?.play()}>Play</button>\n * <button onClick={() => viewerRef.current?.stop()}>Stop</button>\n * </>\n * );\n * }\n * ```\n */\nconst CI360ViewerComponent: ForwardRefRenderFunction<\n CI360ViewerRef,\n CI360ViewerProps\n> = (props, ref) => {\n const {\n // Container props\n id,\n className,\n style,\n\n // Image source\n folder,\n apiVersion,\n filenameX,\n filenameY,\n imageListX,\n imageListY,\n indexZeroBase,\n amountX,\n amountY,\n\n // Behavior\n draggable,\n swipeable,\n keys,\n keysReverse,\n autoplay,\n autoplayBehavior,\n playOnce,\n speed,\n autoplayReverse,\n dragSpeed,\n dragReverse,\n stopAtEdges,\n inertia,\n\n // UI Features\n fullscreen,\n magnifier,\n pointerZoom,\n pinchZoom,\n zoomMax,\n zoomStep,\n zoomControls,\n zoomControlsPosition,\n scrollHint,\n bottomCircle,\n bottomCircleOffset,\n initialIconShown,\n hide360Logo,\n logoSrc,\n imageInfo,\n hints,\n theme,\n markerTheme,\n brandColor,\n\n // Cloudimage CDN\n ciToken,\n ciFilters,\n ciTransformation,\n cropAspectRatio,\n cropGravity,\n\n // Loading\n lazyload,\n\n // Hotspots\n hotspots,\n hotspotTrigger,\n hotspotTimelineOnClick,\n\n // Container\n aspectRatio,\n\n // Event callbacks\n onReady,\n onLoad,\n onSpin,\n onAutoplayStart,\n onAutoplayStop,\n onFullscreenOpen,\n onFullscreenClose,\n onZoomIn,\n onZoomOut,\n onDragStart,\n onDragEnd,\n onHotspotOpen,\n onHotspotClose,\n onProductClick,\n onError,\n\n ...restProps\n } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Memoize config to prevent unnecessary re-initializations\n const config = useMemo<CI360Config>(\n () => ({\n // Image source\n folder,\n apiVersion,\n filenameX,\n filenameY,\n imageListX,\n imageListY,\n indexZeroBase,\n amountX,\n amountY,\n\n // Behavior\n draggable,\n swipeable,\n keys,\n keysReverse,\n autoplay,\n autoplayBehavior,\n playOnce,\n speed,\n autoplayReverse,\n dragSpeed,\n dragReverse,\n stopAtEdges,\n inertia,\n\n // UI Features\n fullscreen,\n magnifier,\n pointerZoom,\n pinchZoom,\n zoomMax,\n zoomStep,\n zoomControls,\n zoomControlsPosition,\n scrollHint,\n bottomCircle,\n bottomCircleOffset,\n initialIconShown,\n hide360Logo,\n logoSrc,\n imageInfo,\n hints,\n theme,\n markerTheme,\n brandColor,\n\n // Cloudimage CDN\n ciToken,\n ciFilters,\n ciTransformation,\n cropAspectRatio,\n cropGravity,\n\n // Loading\n lazyload,\n\n // Hotspots\n hotspots,\n hotspotTrigger,\n hotspotTimelineOnClick,\n\n // Container\n aspectRatio,\n\n // Event callbacks\n onReady,\n onLoad,\n onSpin,\n onAutoplayStart,\n onAutoplayStop,\n onFullscreenOpen,\n onFullscreenClose,\n onZoomIn,\n onZoomOut,\n onDragStart,\n onDragEnd,\n onHotspotOpen,\n onHotspotClose,\n onProductClick,\n onError,\n }),\n [\n // Image source\n folder,\n apiVersion,\n filenameX,\n filenameY,\n imageListX,\n imageListY,\n indexZeroBase,\n amountX,\n amountY,\n\n // Behavior\n draggable,\n swipeable,\n keys,\n keysReverse,\n autoplay,\n autoplayBehavior,\n playOnce,\n speed,\n autoplayReverse,\n dragSpeed,\n dragReverse,\n stopAtEdges,\n inertia,\n\n // UI Features\n fullscreen,\n magnifier,\n pointerZoom,\n pinchZoom,\n zoomMax,\n zoomStep,\n zoomControls,\n zoomControlsPosition,\n scrollHint,\n bottomCircle,\n bottomCircleOffset,\n initialIconShown,\n hide360Logo,\n logoSrc,\n imageInfo,\n hints,\n theme,\n markerTheme,\n brandColor,\n\n // Cloudimage CDN\n ciToken,\n ciFilters,\n ciTransformation,\n cropAspectRatio,\n cropGravity,\n\n // Loading\n lazyload,\n\n // Hotspots\n hotspots,\n hotspotTrigger,\n hotspotTimelineOnClick,\n\n // Container\n aspectRatio,\n\n // Event callbacks\n onReady,\n onLoad,\n onSpin,\n onAutoplayStart,\n onAutoplayStop,\n onFullscreenOpen,\n onFullscreenClose,\n onZoomIn,\n onZoomOut,\n onDragStart,\n onDragEnd,\n onHotspotOpen,\n onHotspotClose,\n onProductClick,\n onError,\n ]\n );\n\n const { getViewer } = useCI360(containerRef, config);\n\n // Expose imperative methods via ref\n // Use getViewer() inside methods to always get the current viewer instance,\n // avoiding stale closure issues when the viewer initializes after first render\n useImperativeHandle(\n ref,\n () => ({\n moveLeft: (steps = 1) => getViewer()?.moveLeft(false, steps),\n moveRight: (steps = 1) => getViewer()?.moveRight(false, steps),\n moveTop: (steps = 1) => getViewer()?.moveTop(false, steps),\n moveBottom: (steps = 1) => getViewer()?.moveBottom(false, steps),\n play: () => getViewer()?.play(),\n stop: () => getViewer()?.stopAutoplay(),\n zoomIn: () => getViewer()?.zoomPan?.zoomIn(),\n zoomOut: () => getViewer()?.zoomPan?.zoomOut(),\n resetZoom: () => getViewer()?.zoomPan?.resetZoom(),\n setZoom: (level: number) => getViewer()?.zoomPan?.setZoom(level),\n goToFrame: (frame: number, hotspotId?: string) =>\n getViewer()?.animateToFrame(frame, hotspotId),\n getViewer: () => getViewer(),\n }),\n [getViewer]\n );\n\n return (\n <div\n ref={containerRef}\n id={id}\n className={className}\n style={style}\n {...restProps}\n />\n );\n};\n\nexport const CI360Viewer = forwardRef(CI360ViewerComponent);\nCI360Viewer.displayName = 'CI360Viewer';\n\nexport default CI360Viewer;\n"],"names":["CI360Class","useCI360","containerRef","config","isReady","setIsReady","useState","viewerRef","useRef","ci360Ref","uniqueId","useId","useEffect","isMounted","container","wrappedConfig","data","_a","error","getViewer","useCallback","CI360ViewerComponent","props","ref","id","className","style","folder","apiVersion","filenameX","filenameY","imageListX","imageListY","indexZeroBase","amountX","amountY","draggable","swipeable","keys","keysReverse","autoplay","autoplayBehavior","playOnce","speed","autoplayReverse","dragSpeed","dragReverse","stopAtEdges","inertia","fullscreen","magnifier","pointerZoom","pinchZoom","zoomMax","zoomStep","zoomControls","zoomControlsPosition","scrollHint","bottomCircle","bottomCircleOffset","initialIconShown","hide360Logo","logoSrc","imageInfo","hints","theme","markerTheme","brandColor","ciToken","ciFilters","ciTransformation","cropAspectRatio","cropGravity","lazyload","hotspots","hotspotTrigger","hotspotTimelineOnClick","aspectRatio","onReady","onLoad","onSpin","onAutoplayStart","onAutoplayStop","onFullscreenOpen","onFullscreenClose","onZoomIn","onZoomOut","onDragStart","onDragEnd","onHotspotOpen","onHotspotClose","onProductClick","onError","restProps","useMemo","useImperativeHandle","steps","_b","level","frame","hotspotId","jsx","CI360Viewer","forwardRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/react/useCI360.ts","../../src/react/CI360Viewer.tsx"],"sourcesContent":["import { useEffect, useRef, useState, useId, useCallback, type RefObject } from 'react';\nimport type {\n CI360Config,\n CI360ViewerInstance,\n UseCI360Return,\n UseCI360Options,\n} from './types';\n\n// Import CI360 class dynamically to avoid SSR issues\nlet CI360Class: any = null;\n\n/**\n * Custom hook for integrating CI360 viewer with React\n *\n * @param containerRef - React ref to the container element\n * @param config - CI360 configuration options\n * @returns Object containing viewer instance and ready state\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const containerRef = useRef<HTMLDivElement>(null);\n * const { viewer, isReady } = useCI360(containerRef, {\n * folder: 'https://example.com/images/',\n * filenameX: 'image-{index}.jpg',\n * amountX: 36,\n * });\n *\n * return <div ref={containerRef} />;\n * }\n * ```\n */\nexport function useCI360(\n containerRef: RefObject<HTMLDivElement | null>,\n config: UseCI360Options\n): UseCI360Return {\n const [isReady, setIsReady] = useState(false);\n const viewerRef = useRef<CI360ViewerInstance | null>(null);\n const ci360Ref = useRef<any>(null);\n const uniqueId = useId();\n\n // Initialize viewer\n useEffect(() => {\n // SSR guard\n if (typeof window === 'undefined') return;\n if (!containerRef.current) return;\n if (config.autoInit === false) return;\n\n let isMounted = true;\n const container = containerRef.current;\n\n const initViewer = async () => {\n try {\n // Dynamically import CI360 to avoid SSR issues\n if (!CI360Class) {\n const module = await import('../ci360');\n CI360Class = module.default;\n }\n\n if (!container || !isMounted) return;\n\n // Set a unique ID on the container if not present\n if (!container.id) {\n container.id = `ci360-${uniqueId.replace(/:/g, '')}`;\n }\n\n // Wrap user callbacks to update React state\n const wrappedConfig: CI360Config = {\n ...config,\n onReady: (data) => {\n if (isMounted) {\n setIsReady(true);\n config.onReady?.(data);\n }\n },\n };\n\n // Create CI360 instance and initialize viewer\n ci360Ref.current = new CI360Class();\n viewerRef.current = ci360Ref.current.init(container, wrappedConfig);\n } catch (error) {\n console.error('Failed to initialize CI360 viewer:', error);\n }\n };\n\n initViewer();\n\n // Cleanup on unmount or when dependencies change\n return () => {\n isMounted = false;\n if (viewerRef.current) {\n try {\n viewerRef.current.destroy();\n } catch (e) {\n // Ignore errors during cleanup - element may already be detached\n }\n viewerRef.current = null;\n }\n ci360Ref.current = null;\n setIsReady(false);\n };\n }, [\n config.folder,\n config.filenameX,\n config.filenameY,\n config.filenameGrid,\n config.imageListX,\n config.imageListY,\n config.imageListGrid,\n config.amountX,\n config.amountY,\n config.hotspots,\n config.theme,\n config.aspectRatio,\n config.cropAspectRatio,\n config.cropGravity,\n uniqueId,\n ]);\n\n // Stable getter to always return current viewer (avoids stale closures)\n const getViewer = useCallback(() => viewerRef.current, []);\n\n return {\n viewer: viewerRef.current,\n isReady,\n getViewer,\n };\n}\n\nexport default useCI360;\n","import {\n useRef,\n useImperativeHandle,\n forwardRef,\n useMemo,\n type ForwardRefRenderFunction,\n} from 'react';\nimport { useCI360 } from './useCI360';\nimport type {\n CI360ViewerProps,\n CI360ViewerRef,\n CI360Config,\n} from './types';\n\n/**\n * CI360Viewer React Component\n *\n * A declarative React wrapper for the CI360 360-degree image viewer.\n *\n * @example\n * ```tsx\n * import { CI360Viewer } from 'js-cloudimage-360-view/react';\n * import 'js-cloudimage-360-view/css';\n *\n * function ProductView() {\n * return (\n * <CI360Viewer\n * folder=\"https://example.com/images/\"\n * filenameX=\"product-{index}.jpg\"\n * amountX={36}\n * autoplay\n * fullscreen\n * />\n * );\n * }\n * ```\n *\n * @example With ref for imperative control\n * ```tsx\n * import { useRef } from 'react';\n * import { CI360Viewer, CI360ViewerRef } from 'js-cloudimage-360-view/react';\n *\n * function ProductView() {\n * const viewerRef = useRef<CI360ViewerRef>(null);\n *\n * return (\n * <>\n * <CI360Viewer\n * ref={viewerRef}\n * folder=\"https://example.com/images/\"\n * filenameX=\"{index}.jpg\"\n * amountX={36}\n * onSpin={(e) => console.log(`Frame: ${e.activeImageX}`)}\n * />\n * <button onClick={() => viewerRef.current?.play()}>Play</button>\n * <button onClick={() => viewerRef.current?.stop()}>Stop</button>\n * </>\n * );\n * }\n * ```\n */\nconst CI360ViewerComponent: ForwardRefRenderFunction<\n CI360ViewerRef,\n CI360ViewerProps\n> = (props, ref) => {\n const {\n // Container props\n id,\n className,\n style,\n\n // Image source\n folder,\n apiVersion,\n filenameX,\n filenameY,\n filenameGrid,\n imageListX,\n imageListY,\n imageListGrid,\n indexZeroBase,\n amountX,\n amountY,\n\n // Behavior\n draggable,\n swipeable,\n keys,\n keysReverse,\n autoplay,\n autoplayBehavior,\n playOnce,\n speed,\n autoplayReverse,\n dragSpeed,\n dragReverse,\n stopAtEdges,\n stopAtEdgesX,\n stopAtEdgesY,\n inertia,\n\n // UI Features\n fullscreen,\n magnifier,\n pointerZoom,\n pinchZoom,\n zoomMax,\n zoomStep,\n zoomControls,\n zoomControlsPosition,\n scrollHint,\n bottomCircle,\n bottomCircleOffset,\n initialIconShown,\n hide360Logo,\n logoSrc,\n imageInfo,\n hints,\n theme,\n markerTheme,\n brandColor,\n\n // Cloudimage CDN\n ciToken,\n ciFilters,\n ciTransformation,\n cropAspectRatio,\n cropGravity,\n\n // Loading\n lazyload,\n\n // Hotspots\n hotspots,\n hotspotTrigger,\n hotspotTimelineOnClick,\n\n // Container\n aspectRatio,\n\n // Event callbacks\n onReady,\n onLoad,\n onSpin,\n onAutoplayStart,\n onAutoplayStop,\n onFullscreenOpen,\n onFullscreenClose,\n onZoomIn,\n onZoomOut,\n onDragStart,\n onDragEnd,\n onHotspotOpen,\n onHotspotClose,\n onProductClick,\n onNavigate,\n onError,\n\n ...restProps\n } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Memoize config to prevent unnecessary re-initializations\n const config = useMemo<CI360Config>(\n () => ({\n // Image source\n folder,\n apiVersion,\n filenameX,\n filenameY,\n filenameGrid,\n imageListX,\n imageListY,\n imageListGrid,\n indexZeroBase,\n amountX,\n amountY,\n\n // Behavior\n draggable,\n swipeable,\n keys,\n keysReverse,\n autoplay,\n autoplayBehavior,\n playOnce,\n speed,\n autoplayReverse,\n dragSpeed,\n dragReverse,\n stopAtEdges,\n stopAtEdgesX,\n stopAtEdgesY,\n inertia,\n\n // UI Features\n fullscreen,\n magnifier,\n pointerZoom,\n pinchZoom,\n zoomMax,\n zoomStep,\n zoomControls,\n zoomControlsPosition,\n scrollHint,\n bottomCircle,\n bottomCircleOffset,\n initialIconShown,\n hide360Logo,\n logoSrc,\n imageInfo,\n hints,\n theme,\n markerTheme,\n brandColor,\n\n // Cloudimage CDN\n ciToken,\n ciFilters,\n ciTransformation,\n cropAspectRatio,\n cropGravity,\n\n // Loading\n lazyload,\n\n // Hotspots\n hotspots,\n hotspotTrigger,\n hotspotTimelineOnClick,\n\n // Container\n aspectRatio,\n\n // Event callbacks\n onReady,\n onLoad,\n onSpin,\n onAutoplayStart,\n onAutoplayStop,\n onFullscreenOpen,\n onFullscreenClose,\n onZoomIn,\n onZoomOut,\n onDragStart,\n onDragEnd,\n onHotspotOpen,\n onHotspotClose,\n onProductClick,\n onNavigate,\n onError,\n }),\n [\n // Image source\n folder,\n apiVersion,\n filenameX,\n filenameY,\n filenameGrid,\n imageListX,\n imageListY,\n imageListGrid,\n indexZeroBase,\n amountX,\n amountY,\n\n // Behavior\n draggable,\n swipeable,\n keys,\n keysReverse,\n autoplay,\n autoplayBehavior,\n playOnce,\n speed,\n autoplayReverse,\n dragSpeed,\n dragReverse,\n stopAtEdges,\n stopAtEdgesX,\n stopAtEdgesY,\n inertia,\n\n // UI Features\n fullscreen,\n magnifier,\n pointerZoom,\n pinchZoom,\n zoomMax,\n zoomStep,\n zoomControls,\n zoomControlsPosition,\n scrollHint,\n bottomCircle,\n bottomCircleOffset,\n initialIconShown,\n hide360Logo,\n logoSrc,\n imageInfo,\n hints,\n theme,\n markerTheme,\n brandColor,\n\n // Cloudimage CDN\n ciToken,\n ciFilters,\n ciTransformation,\n cropAspectRatio,\n cropGravity,\n\n // Loading\n lazyload,\n\n // Hotspots\n hotspots,\n hotspotTrigger,\n hotspotTimelineOnClick,\n\n // Container\n aspectRatio,\n\n // Event callbacks\n onReady,\n onLoad,\n onSpin,\n onAutoplayStart,\n onAutoplayStop,\n onFullscreenOpen,\n onFullscreenClose,\n onZoomIn,\n onZoomOut,\n onDragStart,\n onDragEnd,\n onHotspotOpen,\n onHotspotClose,\n onProductClick,\n onNavigate,\n onError,\n ]\n );\n\n const { getViewer } = useCI360(containerRef, config);\n\n // Expose imperative methods via ref\n // Use getViewer() inside methods to always get the current viewer instance,\n // avoiding stale closure issues when the viewer initializes after first render\n useImperativeHandle(\n ref,\n () => ({\n moveLeft: (steps = 1) => getViewer()?.moveLeft(false, steps),\n moveRight: (steps = 1) => getViewer()?.moveRight(false, steps),\n moveTop: (steps = 1) => getViewer()?.moveTop(false, steps),\n moveBottom: (steps = 1) => getViewer()?.moveBottom(false, steps),\n play: () => getViewer()?.play(),\n stop: () => getViewer()?.stopAutoplay(),\n zoomIn: () => getViewer()?.zoomPan?.zoomIn(),\n zoomOut: () => getViewer()?.zoomPan?.zoomOut(),\n resetZoom: () => getViewer()?.zoomPan?.resetZoom(),\n setZoom: (level: number) => getViewer()?.zoomPan?.setZoom(level),\n goToFrame: (frame: number, hotspotId?: string) =>\n getViewer()?.animateToFrame(frame, hotspotId),\n getViewer: () => getViewer(),\n }),\n [getViewer]\n );\n\n return (\n <div\n ref={containerRef}\n id={id}\n className={className}\n style={style}\n {...restProps}\n />\n );\n};\n\nexport const CI360Viewer = forwardRef(CI360ViewerComponent);\nCI360Viewer.displayName = 'CI360Viewer';\n\nexport default CI360Viewer;\n"],"names":["CI360Class","useCI360","containerRef","config","isReady","setIsReady","useState","viewerRef","useRef","ci360Ref","uniqueId","useId","useEffect","isMounted","container","wrappedConfig","data","_a","error","getViewer","useCallback","CI360ViewerComponent","props","ref","id","className","style","folder","apiVersion","filenameX","filenameY","filenameGrid","imageListX","imageListY","imageListGrid","indexZeroBase","amountX","amountY","draggable","swipeable","keys","keysReverse","autoplay","autoplayBehavior","playOnce","speed","autoplayReverse","dragSpeed","dragReverse","stopAtEdges","stopAtEdgesX","stopAtEdgesY","inertia","fullscreen","magnifier","pointerZoom","pinchZoom","zoomMax","zoomStep","zoomControls","zoomControlsPosition","scrollHint","bottomCircle","bottomCircleOffset","initialIconShown","hide360Logo","logoSrc","imageInfo","hints","theme","markerTheme","brandColor","ciToken","ciFilters","ciTransformation","cropAspectRatio","cropGravity","lazyload","hotspots","hotspotTrigger","hotspotTimelineOnClick","aspectRatio","onReady","onLoad","onSpin","onAutoplayStart","onAutoplayStop","onFullscreenOpen","onFullscreenClose","onZoomIn","onZoomOut","onDragStart","onDragEnd","onHotspotOpen","onHotspotClose","onProductClick","onNavigate","onError","restProps","useMemo","useImperativeHandle","steps","_b","level","frame","hotspotId","jsx","CI360Viewer","forwardRef"],"mappings":"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"}
|
package/dist/react/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--ci360-button-bg: rgba(255, 255, 255, .9);--ci360-button-bg-hover: rgba(255, 255, 255, 1);--ci360-button-size: 40px;--ci360-button-border-radius: 6px;--ci360-button-shadow: 0 2px 8px rgba(0, 0, 0, .15);--ci360-icon-color: #505050;--ci360-icon-color-hover: #333333;--ci360-icon-size: 20px;--ci360-initial-icon-bg: rgba(255, 255, 255, .15);--ci360-initial-icon-color: #ffffff;--ci360-initial-icon-size: 100px;--ci360-initial-icon-shadow: 0 2px 16px rgba(0, 0, 0, .08);--ci360-initial-icon-border-radius: 16px;--ci360-spinner-color: rgba(0, 0, 0, .2);--ci360-spinner-accent: #505050;--ci360-spinner-size: 30px;--ci360-fullscreen-bg: #ffffff;--ci360-zoom-controls-border-radius: 8px;--ci360-scroll-hint-bg: rgba(0, 0, 0, .7);--ci360-scroll-hint-color: #ffffff;--ci360-scroll-hint-border-radius: 20px;--ci360-focus-color: #0066cc;--ci360-hotspot-marker-size: 24px;--ci360-hotspot-marker-bg: rgba(255, 255, 255, .8);--ci360-hotspot-marker-color: #1a1a1a;--ci360-hotspot-marker-border-width: 2px;--ci360-hotspot-marker-border-color: rgba(255, 255, 255, .4);--ci360-hotspot-marker-border: var(--ci360-hotspot-marker-border-width) solid var(--ci360-hotspot-marker-border-color);--ci360-hotspot-marker-shadow: 0 2px 8px rgba(0, 0, 0, .15);--ci360-hotspot-pulse-color: rgba(0, 0, 0, .15);--ci360-hotspot-pulse-size: 40px;--ci360-hotspot-pulse-duration: 1.8s;--ci360-hotspot-brand-color: #00aaff;--ci360-popper-bg: #ffffff;--ci360-popper-color: #1a1a1a;--ci360-popper-border: 1px solid rgba(0, 0, 0, .1);--ci360-popper-border-radius: 12px;--ci360-popper-shadow: 0 8px 32px rgba(0, 0, 0, .12);--ci360-popper-padding: 16px;--ci360-popper-max-width: 320px;--ci360-popper-font-size: 14px;--ci360-popper-line-height: 1.5;--ci360-popper-title-font-size: 16px;--ci360-popper-title-font-weight: 600;--ci360-popper-title-color: #1a1a1a;--ci360-popper-price-color: #2d8c3c;--ci360-popper-price-font-size: 18px;--ci360-popper-price-font-weight: 700;--ci360-popper-original-price-color: #999999;--ci360-popper-description-color: #666666;--ci360-popper-cta-bg: #0058a3;--ci360-popper-cta-color: #fff;--ci360-popper-cta-border-radius: 8px;--ci360-popper-cta-padding: 8px 16px;--ci360-hints-bg: rgba(255, 255, 255, .9);--ci360-hints-color: #333333;--ci360-hints-font-size: 13px;--ci360-hints-border-radius: 20px;--ci360-hints-shadow: 0 2px 12px rgba(0, 0, 0, .1);--ci360-circle-color: #888888;--ci360-timeline-height: 6px;--ci360-timeline-track-bg: rgba(255, 255, 255, .4);--ci360-timeline-dot-size: 18px;--ci360-timeline-dot-color: var(--ci360-hotspot-marker-bg);--ci360-timeline-dot-active-color: var(--ci360-hotspot-brand-color);--ci360-timeline-dot-border: 2px solid #fff;--ci360-timeline-indicator-size: 12px;--ci360-timeline-indicator-color: var(--ci360-hotspot-brand-color);--ci360-timeline-tooltip-bg: rgba(255, 255, 255, .95);--ci360-timeline-tooltip-color: #333333}.ci360-theme-dark{--ci360-button-bg: rgba(40, 40, 45, .9);--ci360-button-bg-hover: rgba(55, 55, 60, .95);--ci360-button-shadow: 0 2px 8px rgba(0, 0, 0, .4);--ci360-icon-color: #e0e0e0;--ci360-icon-color-hover: #ffffff;--ci360-spinner-color: rgba(255, 255, 255, .2);--ci360-spinner-accent: #e0e0e0;--ci360-fullscreen-bg: #1a1a1f;--ci360-zoom-controls-bg: rgba(40, 40, 45, .9);--ci360-zoom-controls-bg-hover: rgba(55, 55, 60, .95);--ci360-zoom-controls-color: #e0e0e0;--ci360-zoom-controls-color-hover: #ffffff;--ci360-zoom-controls-shadow: 0 2px 8px rgba(0, 0, 0, .4);--ci360-scroll-hint-bg: rgba(255, 255, 255, .15);--ci360-scroll-hint-color: #e0e0e0;--ci360-popper-bg: #1a1a1a;--ci360-popper-color: #f0f0f0;--ci360-popper-border: 1px solid rgba(255, 255, 255, .1);--ci360-popper-shadow: 0 8px 32px rgba(0, 0, 0, .4);--ci360-popper-title-color: #f0f0f0;--ci360-popper-description-color: #aaaaaa;--ci360-popper-original-price-color: #777777;--ci360-hints-bg: rgba(40, 40, 45, .9);--ci360-hints-color: #e0e0e0;--ci360-hints-shadow: 0 2px 12px rgba(0, 0, 0, .3);--ci360-circle-color: #b0b0b0;--ci360-timeline-track-bg: rgba(255, 255, 255, .4);--ci360-timeline-dot-border: 2px solid rgba(255, 255, 255, .9);--ci360-timeline-indicator-color: var(--ci360-hotspot-brand-color);--ci360-timeline-tooltip-bg: rgba(40, 40, 45, .95);--ci360-timeline-tooltip-color: #e0e0e0;--ci360-loader-bg: rgba(40, 40, 45, .9);--ci360-loader-color: #e0e0e0;--ci360-loader-shadow: 0 4px 20px rgba(0, 0, 0, .4);--ci360-hotspot-marker-bg: rgba(0, 0, 0, .6);--ci360-hotspot-marker-color: #ffffff;--ci360-hotspot-marker-border-color: rgba(255, 255, 255, .6);--ci360-hotspot-pulse-color: rgba(255, 255, 255, .15);--ci360-timeline-dot-color: var(--ci360-hotspot-marker-bg)}.ci360-hotspot-marker-inverted{--ci360-hotspot-marker-bg: rgba(0, 0, 0, .6);--ci360-hotspot-marker-color: #ffffff;--ci360-hotspot-marker-border-color: rgba(255, 255, 255, .8);--ci360-hotspot-marker-shadow: 0 2px 8px rgba(0, 0, 0, .3);--ci360-hotspot-pulse-color: rgba(0, 0, 0, .2)}.ci360-theme-dark.ci360-hotspot-marker-inverted{--ci360-hotspot-marker-bg: rgba(255, 255, 255, .8);--ci360-hotspot-marker-color: #1a1a1a;--ci360-hotspot-marker-border-color: rgba(255, 255, 255, .4);--ci360-hotspot-pulse-color: rgba(255, 255, 255, .2)}.ci360-hotspot-marker-brand{--ci360-hotspot-marker-bg: var(--ci360-hotspot-brand-color);--ci360-hotspot-marker-color: #ffffff;--ci360-hotspot-marker-border-color: rgba(255, 255, 255, .9);--ci360-hotspot-marker-shadow: 0 2px 8px rgba(0, 0, 0, .25);--ci360-hotspot-pulse-color: var(--ci360-hotspot-brand-color)}@keyframes rotation{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.cloudimage-360{width:100%;position:relative}.cloudimage-360-inner-box{width:100%;position:relative;overflow:hidden}.cloudimage-360-icons-container{position:absolute;display:flex;top:15px;right:10px;height:100%;flex-direction:column;align-items:center;z-index:100;gap:8px}.cloudimage-360-button{width:var(--ci360-button-size);height:var(--ci360-button-size);cursor:pointer;transition:transform .15s ease-out,background-color .15s ease-out,box-shadow .15s ease-out;display:flex;align-items:center;justify-content:center;border-radius:var(--ci360-button-border-radius);border:none;background-color:var(--ci360-button-bg);box-shadow:var(--ci360-button-shadow);padding:6px;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cloudimage-360-button:hover{transform:scale(1.05);background-color:var(--ci360-button-bg-hover)}.cloudimage-360-button:focus{outline:none}.cloudimage-360-button:focus-visible{outline:2px solid var(--ci360-focus-color);outline-offset:2px}.cloudimage-360-button svg{width:var(--ci360-icon-size);height:var(--ci360-icon-size);stroke:var(--ci360-icon-color);transition:stroke .15s ease-out}.cloudimage-360-button:hover svg{stroke:var(--ci360-icon-color-hover)}.cloudimage-initial-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:var(--ci360-initial-icon-size);aspect-ratio:150 / 87;border-radius:var(--ci360-initial-icon-border-radius);background-color:var(--ci360-initial-icon-bg);box-shadow:var(--ci360-initial-icon-shadow);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);transition:all .3s ease;color:var(--ci360-initial-icon-color);display:flex;align-items:center;justify-content:center;z-index:21;-webkit-user-select:none;-moz-user-select:none;user-select:none;padding:12px 16px}.cloudimage-initial-icon svg{width:100%;height:auto;color:var(--ci360-initial-icon-color);fill:var(--ci360-initial-icon-color)}.cloudimage-initial-icon:hover{transform:translate(-50%,-50%) scale(1.08)}.cloudimage-360-loader{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:var(--ci360-loader-size, 70px);height:var(--ci360-loader-size, 70px);border-radius:50%;background-color:var(--ci360-loader-bg, rgba(255, 255, 255, .9));box-shadow:var(--ci360-loader-shadow, 0 4px 20px rgba(0, 0, 0, .15));transition:all .3s ease;color:var(--ci360-loader-color, #505050);display:flex;align-items:center;justify-content:center;z-index:2;-webkit-user-select:none;-moz-user-select:none;user-select:none;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);font-family:system-ui,-apple-system,sans-serif;font-size:14px;font-weight:600}.cloudimage-loading-spinner{width:var(--ci360-spinner-size);height:var(--ci360-spinner-size);transform:translate(-50%,-50%);border:3px solid var(--ci360-spinner-color);position:absolute;top:15px;left:15px;border-bottom-color:var(--ci360-spinner-accent);border-radius:50%;display:inline-block;box-sizing:border-box;opacity:0;animation:rotation .7s linear infinite}.cloudimage-360-view-360-circle{position:absolute;left:0;bottom:0;width:100%;height:auto;margin:auto;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;transition:.2s all;z-index:2;color:var(--ci360-circle-color)}.cloudimage-360-view-360-circle svg{display:block;width:100%;height:auto}.cloudimage-360--fullscreen{width:100%;height:100%;background-color:var(--ci360-fullscreen-bg)}.cloudimage-360--fullscreen .cloudimage-360-inner-box{height:100%;display:flex;justify-content:center;align-items:center}.cloudimage-360--fullscreen canvas{width:auto!important;max-width:100%;max-height:100%}.cloudimage-360-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.cloudimage-360-hints-overlay{position:absolute;bottom:0;left:0;width:100%;display:flex;align-items:flex-end;justify-content:center;padding-bottom:16px;z-index:50;pointer-events:none;opacity:0;transition:opacity .3s ease}.cloudimage-360-hints-overlay.visible{opacity:1}.cloudimage-360-hints-overlay.hiding{opacity:0}.cloudimage-360-hints-container{display:flex;flex-direction:row;gap:20px;padding:10px 20px;background:var(--ci360-hints-bg);border-radius:var(--ci360-hints-border-radius);box-shadow:var(--ci360-hints-shadow);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cloudimage-360-hint-item{display:flex;align-items:center;gap:8px;color:var(--ci360-hints-color);font-size:var(--ci360-hints-font-size);font-family:system-ui,-apple-system,sans-serif;white-space:nowrap}.cloudimage-360-hint-item svg{width:16px;height:16px;flex-shrink:0;stroke:var(--ci360-hints-color)}.cloudimage-360-hint-item span{opacity:.9}@media (max-width: 480px){.cloudimage-360-hints-container{flex-direction:column;gap:8px;padding:12px 16px;border-radius:12px}.cloudimage-360-hint-item{font-size:12px}.cloudimage-360-hint-item svg{width:14px;height:14px}.cloudimage-360-initial-icon{width:calc(var(--ci360-initial-icon-size) * .8);height:calc(var(--ci360-initial-icon-size) * .8)}}.cloudimage-360-inner-box.has-hotspot-timeline .cloudimage-360-hints-overlay{padding-bottom:56px}.cloudimage-360-zoom-controls{position:absolute;display:flex;flex-direction:row;gap:4px;z-index:100;opacity:0;pointer-events:none;transition:opacity .2s ease;background:var(--ci360-zoom-controls-bg, var(--ci360-button-bg));border-radius:var(--ci360-zoom-controls-border-radius);box-shadow:var(--ci360-zoom-controls-shadow, var(--ci360-button-shadow));padding:4px;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cloudimage-360-zoom-controls.visible{opacity:1;pointer-events:auto}.cloudimage-360-zoom-controls[data-position=bottom-left]{bottom:12px;left:12px}.cloudimage-360-zoom-controls[data-position=bottom-right]{bottom:12px;right:12px}.cloudimage-360-zoom-controls[data-position=top-left]{top:12px;left:12px}.cloudimage-360-zoom-controls[data-position=top-right]{top:12px;right:12px}.cloudimage-360-zoom-controls[data-position=top-center]{top:12px;left:50%;transform:translate(-50%)}.cloudimage-360-zoom-controls[data-position=bottom-center]{bottom:12px;left:50%;transform:translate(-50%)}.cloudimage-360-zoom-btn{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;background:transparent;border-radius:calc(var(--ci360-zoom-controls-border-radius) - 2px);cursor:pointer;padding:0;color:var(--ci360-zoom-controls-color, var(--ci360-icon-color));transition:background-color .15s ease,color .15s ease}.cloudimage-360-zoom-btn:hover:not(:disabled){background:var(--ci360-zoom-controls-bg-hover, var(--ci360-button-bg-hover));color:var(--ci360-zoom-controls-color-hover, var(--ci360-icon-color-hover))}.cloudimage-360-zoom-btn:disabled{opacity:.3;cursor:default}.cloudimage-360-zoom-btn:focus{outline:none}.cloudimage-360-zoom-btn:focus-visible{outline:2px solid var(--ci360-focus-color);outline-offset:-2px}.cloudimage-360-zoom-btn svg{width:18px;height:18px;stroke:currentColor}.cloudimage-360-zoom-btn-reset{border-left:1px solid rgba(128,128,128,.2);padding-left:4px;margin-left:0}.cloudimage-360-scroll-hint{position:absolute;bottom:50%;left:50%;transform:translate(-50%,50%);background:var(--ci360-scroll-hint-bg);color:var(--ci360-scroll-hint-color);padding:8px 16px;border-radius:var(--ci360-scroll-hint-border-radius);font-size:13px;font-family:system-ui,-apple-system,sans-serif;font-weight:500;white-space:nowrap;pointer-events:none;z-index:200;opacity:0;transition:opacity .3s ease;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cloudimage-360-scroll-hint.visible{opacity:1}.cloudimage-360-hotspot-timeline{position:absolute;bottom:0;left:0;right:0;width:100%;padding:20px;opacity:0;transition:opacity .3s ease;pointer-events:none;z-index:30;background:linear-gradient(to top,rgba(0,0,0,.45) 0%,rgba(0,0,0,.2) 60%,transparent 100%)}.cloudimage-360-hotspot-timeline.visible{opacity:1;pointer-events:auto}.cloudimage-360-hotspot-timeline-track{position:relative;width:100%;max-width:500px;margin:0 auto;height:var(--ci360-timeline-height);background:var(--ci360-timeline-track-bg);border-radius:calc(var(--ci360-timeline-height) / 2)}.cloudimage-360-hotspot-timeline-indicator{position:absolute;top:50%;left:0;width:var(--ci360-timeline-indicator-size);height:var(--ci360-timeline-indicator-size);background:var(--ci360-timeline-indicator-color);border-radius:50%;transform:translate(-50%,-50%);transition:left .1s ease-out;pointer-events:none;box-shadow:0 2px 4px #0003}.cloudimage-360-hotspot-timeline-dot{position:absolute;top:50%;width:var(--ci360-timeline-dot-size);height:var(--ci360-timeline-dot-size);background:var(--ci360-timeline-dot-color);border:var(--ci360-timeline-dot-border);border-radius:50%;transform:translate(-50%,-50%);cursor:pointer;transition:transform .15s ease,background .2s ease,box-shadow .2s ease;box-shadow:0 1px 4px #00000026;padding:0;font:inherit;outline:none}.cloudimage-360-hotspot-timeline-dot:hover{transform:translate(-50%,-50%) scale(1.15);box-shadow:0 2px 8px #0003}.cloudimage-360-hotspot-timeline-dot.active{background:var(--ci360-timeline-dot-color);box-shadow:0 1px 4px #00000026}.cloudimage-360-hotspot-timeline-dot:focus-visible{outline:2px solid var(--ci360-focus-color);outline-offset:2px}.cloudimage-360-hotspot-timeline-tooltip{position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%);background:var(--ci360-timeline-tooltip-bg);color:var(--ci360-timeline-tooltip-color);padding:6px 12px;border-radius:6px;font-size:13px;font-weight:500;white-space:nowrap;opacity:0;visibility:hidden;transition:opacity .2s ease,visibility .2s ease;pointer-events:none;box-shadow:0 2px 8px #00000026;z-index:10}.cloudimage-360-hotspot-timeline-tooltip:after{content:"";position:absolute;top:100%;left:50%;transform:translate(-50%);border:6px solid transparent;border-top-color:var(--ci360-timeline-tooltip-bg)}.cloudimage-360-hotspot-timeline-tooltip.visible{opacity:1;visibility:visible}@media (max-width: 480px){.cloudimage-360-hotspot-timeline{padding:14px 16px}}.cloudimage-360--fullscreen .cloudimage-360-hotspot-timeline{bottom:0}.cloudimage-360--fullscreen .cloudimage-360-hints-overlay{padding-bottom:32px}.cloudimage-360--fullscreen .cloudimage-360-zoom-controls[data-position^=bottom]{bottom:38px}.cloudimage-360--fullscreen .cloudimage-360-inner-box.has-hotspot-timeline .cloudimage-360-hints-overlay{padding-bottom:72px}.cloudimage-360--fullscreen .cloudimage-360-inner-box.has-hotspot-timeline .cloudimage-360-zoom-controls[data-position^=bottom]{bottom:72px}.cloudimage-360-hotspot-container{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:20}.cloudimage-360-hotspot{display:inline-block;position:absolute;top:0;right:0;bottom:0;left:0;transform:translate(-50%,-50%);background:var(--ci360-hotspot-marker-bg);border:var(--ci360-hotspot-marker-border);border-radius:50%;height:var(--ci360-hotspot-marker-size);width:var(--ci360-hotspot-marker-size);box-shadow:var(--ci360-hotspot-marker-shadow);opacity:0;transition:transform .2s ease,box-shadow .2s ease;padding:0;cursor:pointer;font:inherit;outline:none}.cloudimage-360-hotspot:focus-visible{outline:2px solid var(--ci360-focus-color, #0066cc);outline-offset:2px}.cloudimage-360-hotspot--pulse{overflow:visible}.cloudimage-360-hotspot--pulse:before{content:"";position:absolute;top:50%;left:50%;width:var(--ci360-hotspot-pulse-size);height:var(--ci360-hotspot-pulse-size);border-radius:50%;background:var(--ci360-hotspot-pulse-color);transform:translate(-50%,-50%) scale(1);animation:ci360-pulse-ring var(--ci360-hotspot-pulse-duration) ease-out infinite;pointer-events:none}@keyframes ci360-pulse-ring{0%{transform:translate(-50%,-50%) scale(1);opacity:1}to{transform:translate(-50%,-50%) scale(1.8);opacity:0}}.cloudimage-360-hotspot--pulse{animation:ci360-breathe 2.4s ease-in-out infinite}@keyframes ci360-breathe{0%,to{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.15)}}.cloudimage-360-hotspot--pulse:hover,.cloudimage-360-hotspot--pulse:focus-visible{animation:none}.cloudimage-360-hotspot--dot-label{animation:none}.cloudimage-360-hotspot-label{position:absolute;left:calc(50% + var(--ci360-hotspot-marker-size) / 2 + 4px);top:50%;transform:translateY(-50%);padding:3px 10px;font-size:11px;font-weight:600;white-space:nowrap;color:var(--ci360-hotspot-marker-color);background:var(--ci360-hotspot-marker-bg);border:var(--ci360-hotspot-marker-border);border-radius:100px;box-shadow:var(--ci360-hotspot-marker-shadow);pointer-events:none}.cloudimage-360-hotspot--navigate{display:inline-flex;align-items:center;justify-content:center;background:var(--ci360-hotspot-navigate-bg, #6366f1);border-color:var(--ci360-hotspot-navigate-border-color, rgba(255, 255, 255, .9))}.ci360-navigate-icon{width:14px;height:14px;color:#fff;pointer-events:none}.cloudimage-360-hotspot--navigate.cloudimage-360-hotspot--pulse{animation:none}.cloudimage-360-hotspot--navigate:hover,.cloudimage-360-hotspot--navigate:focus-visible{transform:translate(-50%,-50%) scale(1.15);box-shadow:0 0 0 3px #6366f166}.cloudimage-360-hotspot--dot-label:hover{transform:translate(-50%,-50%);box-shadow:0 4px 12px #0006}.cloudimage-360-hotspot:hover{transform:translate(-50%,-50%) scale(1.2);box-shadow:0 4px 12px #0006}@media (prefers-reduced-motion: reduce){.cloudimage-360-hotspot--pulse{animation:none}.cloudimage-360-hotspot--pulse:before{animation:none}}.cloudimage-360-popper{background:var(--ci360-popper-bg);color:var(--ci360-popper-color);border:var(--ci360-popper-border);padding:var(--ci360-popper-padding);border-radius:var(--ci360-popper-border-radius);box-shadow:var(--ci360-popper-shadow);font-family:system-ui,-apple-system,sans-serif;font-size:var(--ci360-popper-font-size);line-height:var(--ci360-popper-line-height);max-width:var(--ci360-popper-max-width);z-index:9999;text-align:left;transition:opacity .2s ease;opacity:0}.cloudimage-360-popper[data-show]{opacity:1}.ci360-popper-image-wrapper{aspect-ratio:16 / 9;overflow:hidden;border-radius:calc(var(--ci360-popper-border-radius) - 4px) calc(var(--ci360-popper-border-radius) - 4px) 0 0;margin:calc(var(--ci360-popper-padding) * -1);margin-bottom:12px;width:calc(100% + var(--ci360-popper-padding) * 2)}.ci360-popper-image{display:block;width:100%;height:100%;-o-object-fit:cover;object-fit:cover}.ci360-popper-body{line-height:1.5;text-align:left}.ci360-popper-title{margin:0 0 4px;font-size:var(--ci360-popper-title-font-size);font-weight:var(--ci360-popper-title-font-weight);color:var(--ci360-popper-title-color);line-height:1.3}.ci360-popper-price-row{display:inline-flex;align-items:baseline;gap:6px;margin-bottom:8px;flex-wrap:wrap}.ci360-popper-price{font-size:var(--ci360-popper-price-font-size);font-weight:var(--ci360-popper-price-font-weight);color:var(--ci360-popper-price-color)}.ci360-popper-price-row .ci360-popper-price{margin-bottom:0}.ci360-popper-original-price{font-size:calc(var(--ci360-popper-price-font-size) - 2px);font-weight:500;color:var(--ci360-popper-original-price-color);text-decoration:line-through}.ci360-popper-description{margin:0 0 12px;color:var(--ci360-popper-description-color)}.ci360-popper-cta{display:inline-block;padding:var(--ci360-popper-cta-padding);background:var(--ci360-popper-cta-bg);color:var(--ci360-popper-cta-color);border-radius:var(--ci360-popper-cta-border-radius);text-decoration:none;font-weight:600;font-size:14px;transition:opacity .2s ease}.ci360-popper-cta:hover{opacity:.9}button.ci360-popper-cta{cursor:pointer;border:none;font:inherit;width:100%}.ci360-popper-cta:focus-visible{outline:3px solid var(--ci360-focus-color, #0066cc);outline-offset:2px}
|
|
1
|
+
:root{--ci360-button-bg: rgba(255, 255, 255, .9);--ci360-button-bg-hover: rgba(255, 255, 255, 1);--ci360-button-size: 40px;--ci360-button-border-radius: 6px;--ci360-button-shadow: 0 2px 8px rgba(0, 0, 0, .15);--ci360-icon-color: #505050;--ci360-icon-color-hover: #333333;--ci360-icon-size: 20px;--ci360-initial-icon-bg: rgba(255, 255, 255, .15);--ci360-initial-icon-color: #ffffff;--ci360-initial-icon-size: 100px;--ci360-initial-icon-shadow: 0 2px 16px rgba(0, 0, 0, .08);--ci360-initial-icon-border-radius: 16px;--ci360-spinner-color: rgba(0, 0, 0, .2);--ci360-spinner-accent: #505050;--ci360-spinner-size: 30px;--ci360-fullscreen-bg: #ffffff;--ci360-zoom-controls-border-radius: 8px;--ci360-scroll-hint-bg: rgba(0, 0, 0, .7);--ci360-scroll-hint-color: #ffffff;--ci360-scroll-hint-border-radius: 20px;--ci360-focus-color: #0066cc;--ci360-hotspot-marker-size: 24px;--ci360-hotspot-marker-bg: rgba(255, 255, 255, .8);--ci360-hotspot-marker-color: #1a1a1a;--ci360-hotspot-marker-border-width: 2px;--ci360-hotspot-marker-border-color: rgba(255, 255, 255, .4);--ci360-hotspot-marker-border: var(--ci360-hotspot-marker-border-width) solid var(--ci360-hotspot-marker-border-color);--ci360-hotspot-marker-shadow: 0 2px 8px rgba(0, 0, 0, .15);--ci360-hotspot-pulse-color: rgba(0, 0, 0, .15);--ci360-hotspot-pulse-size: 40px;--ci360-hotspot-pulse-duration: 1.8s;--ci360-hotspot-brand-color: #00aaff;--ci360-popper-bg: #ffffff;--ci360-popper-color: #1a1a1a;--ci360-popper-border: 1px solid rgba(0, 0, 0, .1);--ci360-popper-border-radius: 12px;--ci360-popper-shadow: 0 8px 32px rgba(0, 0, 0, .12);--ci360-popper-padding: 16px;--ci360-popper-max-width: 320px;--ci360-popper-font-size: 14px;--ci360-popper-line-height: 1.5;--ci360-popper-title-font-size: 16px;--ci360-popper-title-font-weight: 600;--ci360-popper-title-color: #1a1a1a;--ci360-popper-price-color: #2d8c3c;--ci360-popper-price-font-size: 18px;--ci360-popper-price-font-weight: 700;--ci360-popper-original-price-color: #999999;--ci360-popper-description-color: #666666;--ci360-popper-cta-bg: #0058a3;--ci360-popper-cta-color: #fff;--ci360-popper-cta-border-radius: 8px;--ci360-popper-cta-padding: 8px 16px;--ci360-hints-bg: rgba(255, 255, 255, .9);--ci360-hints-color: #333333;--ci360-hints-font-size: 13px;--ci360-hints-border-radius: 20px;--ci360-hints-shadow: 0 2px 12px rgba(0, 0, 0, .1);--ci360-circle-color: #888888;--ci360-timeline-height: 6px;--ci360-timeline-track-bg: rgba(255, 255, 255, .4);--ci360-timeline-dot-size: 18px;--ci360-timeline-dot-color: var(--ci360-hotspot-marker-bg);--ci360-timeline-dot-active-color: var(--ci360-hotspot-brand-color);--ci360-timeline-dot-border: 2px solid #fff;--ci360-timeline-indicator-size: 12px;--ci360-timeline-indicator-color: var(--ci360-hotspot-brand-color);--ci360-timeline-tooltip-bg: rgba(255, 255, 255, .95);--ci360-timeline-tooltip-color: #333333}.ci360-theme-dark{--ci360-button-bg: rgba(40, 40, 45, .9);--ci360-button-bg-hover: rgba(55, 55, 60, .95);--ci360-button-shadow: 0 2px 8px rgba(0, 0, 0, .4);--ci360-icon-color: #e0e0e0;--ci360-icon-color-hover: #ffffff;--ci360-spinner-color: rgba(255, 255, 255, .2);--ci360-spinner-accent: #e0e0e0;--ci360-fullscreen-bg: #1a1a1f;--ci360-zoom-controls-bg: rgba(40, 40, 45, .9);--ci360-zoom-controls-bg-hover: rgba(55, 55, 60, .95);--ci360-zoom-controls-color: #e0e0e0;--ci360-zoom-controls-color-hover: #ffffff;--ci360-zoom-controls-shadow: 0 2px 8px rgba(0, 0, 0, .4);--ci360-scroll-hint-bg: rgba(255, 255, 255, .15);--ci360-scroll-hint-color: #e0e0e0;--ci360-popper-bg: #1a1a1a;--ci360-popper-color: #f0f0f0;--ci360-popper-border: 1px solid rgba(255, 255, 255, .1);--ci360-popper-shadow: 0 8px 32px rgba(0, 0, 0, .4);--ci360-popper-title-color: #f0f0f0;--ci360-popper-description-color: #aaaaaa;--ci360-popper-original-price-color: #777777;--ci360-hints-bg: rgba(40, 40, 45, .9);--ci360-hints-color: #e0e0e0;--ci360-hints-shadow: 0 2px 12px rgba(0, 0, 0, .3);--ci360-circle-color: #b0b0b0;--ci360-timeline-track-bg: rgba(255, 255, 255, .4);--ci360-timeline-dot-border: 2px solid rgba(255, 255, 255, .9);--ci360-timeline-indicator-color: var(--ci360-hotspot-brand-color);--ci360-timeline-tooltip-bg: rgba(40, 40, 45, .95);--ci360-timeline-tooltip-color: #e0e0e0;--ci360-loader-bg: rgba(40, 40, 45, .9);--ci360-loader-color: #e0e0e0;--ci360-loader-shadow: 0 4px 20px rgba(0, 0, 0, .4);--ci360-hotspot-marker-bg: rgba(0, 0, 0, .6);--ci360-hotspot-marker-color: #ffffff;--ci360-hotspot-marker-border-color: rgba(255, 255, 255, .6);--ci360-hotspot-pulse-color: rgba(255, 255, 255, .15);--ci360-timeline-dot-color: var(--ci360-hotspot-marker-bg)}.ci360-hotspot-marker-inverted{--ci360-hotspot-marker-bg: rgba(0, 0, 0, .6);--ci360-hotspot-marker-color: #ffffff;--ci360-hotspot-marker-border-color: rgba(255, 255, 255, .8);--ci360-hotspot-marker-shadow: 0 2px 8px rgba(0, 0, 0, .3);--ci360-hotspot-pulse-color: rgba(0, 0, 0, .2)}.ci360-theme-dark.ci360-hotspot-marker-inverted{--ci360-hotspot-marker-bg: rgba(255, 255, 255, .8);--ci360-hotspot-marker-color: #1a1a1a;--ci360-hotspot-marker-border-color: rgba(255, 255, 255, .4);--ci360-hotspot-pulse-color: rgba(255, 255, 255, .2)}.ci360-hotspot-marker-brand{--ci360-hotspot-marker-bg: var(--ci360-hotspot-brand-color);--ci360-hotspot-marker-color: #ffffff;--ci360-hotspot-marker-border-color: rgba(255, 255, 255, .9);--ci360-hotspot-marker-shadow: 0 2px 8px rgba(0, 0, 0, .25);--ci360-hotspot-pulse-color: var(--ci360-hotspot-brand-color)}@keyframes rotation{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.cloudimage-360{width:100%;position:relative}.cloudimage-360-inner-box{width:100%;position:relative;overflow:hidden}.cloudimage-360-icons-container{position:absolute;display:flex;top:15px;right:10px;height:100%;flex-direction:column;align-items:center;z-index:100;gap:8px}.cloudimage-360-button{width:var(--ci360-button-size);height:var(--ci360-button-size);cursor:pointer;transition:transform .15s ease-out,background-color .15s ease-out,box-shadow .15s ease-out;display:flex;align-items:center;justify-content:center;border-radius:var(--ci360-button-border-radius);border:none;background-color:var(--ci360-button-bg);box-shadow:var(--ci360-button-shadow);padding:6px;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cloudimage-360-button:hover{transform:scale(1.05);background-color:var(--ci360-button-bg-hover)}.cloudimage-360-button:focus{outline:none}.cloudimage-360-button:focus-visible{outline:2px solid var(--ci360-focus-color);outline-offset:2px}.cloudimage-360-button svg{width:var(--ci360-icon-size);height:var(--ci360-icon-size);stroke:var(--ci360-icon-color);transition:stroke .15s ease-out}.cloudimage-360-button:hover svg{stroke:var(--ci360-icon-color-hover)}.cloudimage-initial-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:var(--ci360-initial-icon-size);aspect-ratio:150 / 87;border-radius:var(--ci360-initial-icon-border-radius);background-color:var(--ci360-initial-icon-bg);box-shadow:var(--ci360-initial-icon-shadow);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);transition:all .3s ease;color:var(--ci360-initial-icon-color);display:flex;align-items:center;justify-content:center;z-index:21;-webkit-user-select:none;-moz-user-select:none;user-select:none;padding:12px 16px}.cloudimage-initial-icon svg{width:100%;height:auto;color:var(--ci360-initial-icon-color);fill:var(--ci360-initial-icon-color)}.cloudimage-initial-icon:hover{transform:translate(-50%,-50%) scale(1.08)}.cloudimage-360-loader{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:var(--ci360-loader-size, 70px);height:var(--ci360-loader-size, 70px);border-radius:50%;background-color:var(--ci360-loader-bg, rgba(255, 255, 255, .9));box-shadow:var(--ci360-loader-shadow, 0 4px 20px rgba(0, 0, 0, .15));transition:all .3s ease;color:var(--ci360-loader-color, #505050);display:flex;align-items:center;justify-content:center;z-index:2;-webkit-user-select:none;-moz-user-select:none;user-select:none;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);font-family:system-ui,-apple-system,sans-serif;font-size:14px;font-weight:600}.cloudimage-loading-spinner{width:var(--ci360-spinner-size);height:var(--ci360-spinner-size);transform:translate(-50%,-50%);border:3px solid var(--ci360-spinner-color);position:absolute;top:15px;left:15px;border-bottom-color:var(--ci360-spinner-accent);border-radius:50%;display:inline-block;box-sizing:border-box;opacity:0;animation:rotation .7s linear infinite}.cloudimage-360-view-360-circle{position:absolute;left:0;bottom:0;width:100%;height:auto;margin:auto;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;transition:.2s all;z-index:2;color:var(--ci360-circle-color)}.cloudimage-360-view-360-circle svg{display:block;width:100%;height:auto}.cloudimage-360--fullscreen{width:100%;height:100%;background-color:var(--ci360-fullscreen-bg)}.cloudimage-360--fullscreen .cloudimage-360-inner-box{height:100%;display:flex;justify-content:center;align-items:center}.cloudimage-360--fullscreen canvas{width:auto!important;max-width:100%;max-height:100%}.cloudimage-360-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.cloudimage-360-hints-overlay{position:absolute;bottom:0;left:0;width:100%;display:flex;align-items:flex-end;justify-content:center;padding-bottom:16px;z-index:50;pointer-events:none;opacity:0;transition:opacity .3s ease}.cloudimage-360-hints-overlay.visible{opacity:1}.cloudimage-360-hints-overlay.hiding{opacity:0}.cloudimage-360-hints-container{display:flex;flex-direction:row;gap:20px;padding:10px 20px;background:var(--ci360-hints-bg);border-radius:var(--ci360-hints-border-radius);box-shadow:var(--ci360-hints-shadow);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cloudimage-360-hint-item{display:flex;align-items:center;gap:8px;color:var(--ci360-hints-color);font-size:var(--ci360-hints-font-size);font-family:system-ui,-apple-system,sans-serif;white-space:nowrap}.cloudimage-360-hint-item svg{width:16px;height:16px;flex-shrink:0;stroke:var(--ci360-hints-color)}.cloudimage-360-hint-item span{opacity:.9}@media (max-width: 480px){.cloudimage-360-hints-container{flex-direction:column;gap:8px;padding:12px 16px;border-radius:12px}.cloudimage-360-hint-item{font-size:12px}.cloudimage-360-hint-item svg{width:14px;height:14px}.cloudimage-360-initial-icon{width:calc(var(--ci360-initial-icon-size) * .8);height:calc(var(--ci360-initial-icon-size) * .8)}}.cloudimage-360-inner-box.has-hotspot-timeline .cloudimage-360-hints-overlay{padding-bottom:56px}.cloudimage-360-zoom-controls{position:absolute;display:flex;flex-direction:row;gap:4px;z-index:100;opacity:0;pointer-events:none;transition:opacity .2s ease;background:var(--ci360-zoom-controls-bg, var(--ci360-button-bg));border-radius:var(--ci360-zoom-controls-border-radius);box-shadow:var(--ci360-zoom-controls-shadow, var(--ci360-button-shadow));padding:4px;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cloudimage-360-zoom-controls.visible{opacity:1;pointer-events:auto}.cloudimage-360-zoom-controls[data-position=bottom-left]{bottom:12px;left:12px}.cloudimage-360-zoom-controls[data-position=bottom-right]{bottom:12px;right:12px}.cloudimage-360-zoom-controls[data-position=top-left]{top:12px;left:12px}.cloudimage-360-zoom-controls[data-position=top-right]{top:12px;right:12px}.cloudimage-360-zoom-controls[data-position=top-center]{top:12px;left:50%;transform:translate(-50%)}.cloudimage-360-zoom-controls[data-position=bottom-center]{bottom:12px;left:50%;transform:translate(-50%)}.cloudimage-360-zoom-btn{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;background:transparent;border-radius:calc(var(--ci360-zoom-controls-border-radius) - 2px);cursor:pointer;padding:0;color:var(--ci360-zoom-controls-color, var(--ci360-icon-color));transition:background-color .15s ease,color .15s ease}.cloudimage-360-zoom-btn:hover:not(:disabled){background:var(--ci360-zoom-controls-bg-hover, var(--ci360-button-bg-hover));color:var(--ci360-zoom-controls-color-hover, var(--ci360-icon-color-hover))}.cloudimage-360-zoom-btn:disabled{opacity:.3;cursor:default}.cloudimage-360-zoom-btn:focus{outline:none}.cloudimage-360-zoom-btn:focus-visible{outline:2px solid var(--ci360-focus-color);outline-offset:-2px}.cloudimage-360-zoom-btn svg{width:18px;height:18px;stroke:currentColor}.cloudimage-360-zoom-separator{width:1px;align-self:stretch;margin:6px 0;background:#80808033}.cloudimage-360-scroll-hint{position:absolute;bottom:50%;left:50%;transform:translate(-50%,50%);background:var(--ci360-scroll-hint-bg);color:var(--ci360-scroll-hint-color);padding:8px 16px;border-radius:var(--ci360-scroll-hint-border-radius);font-size:13px;font-family:system-ui,-apple-system,sans-serif;font-weight:500;white-space:nowrap;pointer-events:none;z-index:200;opacity:0;transition:opacity .3s ease;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.cloudimage-360-scroll-hint.visible{opacity:1}.cloudimage-360-hotspot-timeline{position:absolute;bottom:0;left:0;right:0;width:100%;padding:20px;opacity:0;transition:opacity .3s ease;pointer-events:none;z-index:30;background:linear-gradient(to top,rgba(0,0,0,.45) 0%,rgba(0,0,0,.2) 60%,transparent 100%)}.cloudimage-360-hotspot-timeline.visible{opacity:1;pointer-events:auto}.cloudimage-360-hotspot-timeline-track{position:relative;width:100%;max-width:500px;margin:0 auto;height:var(--ci360-timeline-height);background:var(--ci360-timeline-track-bg);border-radius:calc(var(--ci360-timeline-height) / 2)}.cloudimage-360-hotspot-timeline-indicator{position:absolute;top:50%;left:0;width:var(--ci360-timeline-indicator-size);height:var(--ci360-timeline-indicator-size);background:var(--ci360-timeline-indicator-color);border-radius:50%;transform:translate(-50%,-50%);transition:left .1s ease-out;pointer-events:none;box-shadow:0 2px 4px #0003}.cloudimage-360-hotspot-timeline-dot{position:absolute;top:50%;width:var(--ci360-timeline-dot-size);height:var(--ci360-timeline-dot-size);background:var(--ci360-timeline-dot-color);border:var(--ci360-timeline-dot-border);border-radius:50%;transform:translate(-50%,-50%);cursor:pointer;transition:transform .15s ease,background .2s ease,box-shadow .2s ease;box-shadow:0 1px 4px #00000026;padding:0;font:inherit;outline:none}.cloudimage-360-hotspot-timeline-dot:hover{transform:translate(-50%,-50%) scale(1.15);box-shadow:0 2px 8px #0003}.cloudimage-360-hotspot-timeline-dot.active{background:var(--ci360-timeline-dot-color);box-shadow:0 1px 4px #00000026}.cloudimage-360-hotspot-timeline-dot:focus-visible{outline:2px solid var(--ci360-focus-color);outline-offset:2px}.cloudimage-360-hotspot-timeline-tooltip{position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%);background:var(--ci360-timeline-tooltip-bg);color:var(--ci360-timeline-tooltip-color);padding:6px 12px;border-radius:6px;font-size:13px;font-weight:500;white-space:nowrap;opacity:0;visibility:hidden;transition:opacity .2s ease,visibility .2s ease;pointer-events:none;box-shadow:0 2px 8px #00000026;z-index:10}.cloudimage-360-hotspot-timeline-tooltip:after{content:"";position:absolute;top:100%;left:50%;transform:translate(-50%);border:6px solid transparent;border-top-color:var(--ci360-timeline-tooltip-bg)}.cloudimage-360-hotspot-timeline-tooltip.visible{opacity:1;visibility:visible}@media (max-width: 480px){.cloudimage-360-hotspot-timeline{padding:14px 16px}}.cloudimage-360--fullscreen .cloudimage-360-hotspot-timeline{bottom:0}.cloudimage-360--fullscreen .cloudimage-360-hints-overlay{padding-bottom:32px}.cloudimage-360--fullscreen .cloudimage-360-zoom-controls[data-position^=bottom]{bottom:38px}.cloudimage-360--fullscreen .cloudimage-360-inner-box.has-hotspot-timeline .cloudimage-360-hints-overlay{padding-bottom:72px}.cloudimage-360--fullscreen .cloudimage-360-inner-box.has-hotspot-timeline .cloudimage-360-zoom-controls[data-position^=bottom]{bottom:72px}.cloudimage-360-hotspot-container{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:20}.cloudimage-360-hotspot{display:inline-block;position:absolute;top:0;right:0;bottom:0;left:0;transform:translate(-50%,-50%);background:var(--ci360-hotspot-marker-bg);border:var(--ci360-hotspot-marker-border);border-radius:50%;height:var(--ci360-hotspot-marker-size);width:var(--ci360-hotspot-marker-size);box-shadow:var(--ci360-hotspot-marker-shadow);opacity:0;transition:transform .2s ease,box-shadow .2s ease;padding:0;cursor:pointer;font:inherit;outline:none}.cloudimage-360-hotspot:focus-visible{outline:2px solid var(--ci360-focus-color, #0066cc);outline-offset:2px}.cloudimage-360-hotspot--pulse{overflow:visible}.cloudimage-360-hotspot--pulse:before{content:"";position:absolute;top:50%;left:50%;width:var(--ci360-hotspot-pulse-size);height:var(--ci360-hotspot-pulse-size);border-radius:50%;background:var(--ci360-hotspot-pulse-color);transform:translate(-50%,-50%) scale(1);animation:ci360-pulse-ring var(--ci360-hotspot-pulse-duration) ease-out infinite;pointer-events:none}@keyframes ci360-pulse-ring{0%{transform:translate(-50%,-50%) scale(1);opacity:1}to{transform:translate(-50%,-50%) scale(1.8);opacity:0}}.cloudimage-360-hotspot--pulse{animation:ci360-breathe 2.4s ease-in-out infinite}@keyframes ci360-breathe{0%,to{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.15)}}.cloudimage-360-hotspot--pulse:hover,.cloudimage-360-hotspot--pulse:focus-visible{animation:none}.cloudimage-360-hotspot--dot-label{animation:none}.cloudimage-360-hotspot-label{position:absolute;left:calc(50% + var(--ci360-hotspot-marker-size) / 2 + 4px);top:50%;transform:translateY(-50%);padding:3px 10px;font-size:11px;font-weight:600;white-space:nowrap;color:var(--ci360-hotspot-marker-color);background:var(--ci360-hotspot-marker-bg);border:var(--ci360-hotspot-marker-border);border-radius:100px;box-shadow:var(--ci360-hotspot-marker-shadow);pointer-events:none}.cloudimage-360-hotspot--navigate{display:inline-flex;align-items:center;justify-content:center;background:var(--ci360-hotspot-navigate-bg, #6366f1);border-color:var(--ci360-hotspot-navigate-border-color, rgba(255, 255, 255, .9))}.ci360-navigate-icon{width:14px;height:14px;color:#fff;pointer-events:none}.cloudimage-360-hotspot--navigate.cloudimage-360-hotspot--pulse{animation:none}.cloudimage-360-hotspot--navigate:hover,.cloudimage-360-hotspot--navigate:focus-visible{transform:translate(-50%,-50%) scale(1.15);box-shadow:0 0 0 3px #6366f166}.cloudimage-360-hotspot--dot-label:hover{transform:translate(-50%,-50%);box-shadow:0 4px 12px #0006}.cloudimage-360-hotspot:hover{transform:translate(-50%,-50%) scale(1.2);box-shadow:0 4px 12px #0006}@media (prefers-reduced-motion: reduce){.cloudimage-360-hotspot--pulse{animation:none}.cloudimage-360-hotspot--pulse:before{animation:none}}.cloudimage-360-popper{background:var(--ci360-popper-bg);color:var(--ci360-popper-color);border:var(--ci360-popper-border);padding:var(--ci360-popper-padding);border-radius:var(--ci360-popper-border-radius);box-shadow:var(--ci360-popper-shadow);font-family:system-ui,-apple-system,sans-serif;font-size:var(--ci360-popper-font-size);line-height:var(--ci360-popper-line-height);max-width:var(--ci360-popper-max-width);z-index:9999;text-align:left;transition:opacity .2s ease;opacity:0}.cloudimage-360-popper[data-show]{opacity:1}.ci360-popper-image-wrapper{aspect-ratio:16 / 9;overflow:hidden;border-radius:calc(var(--ci360-popper-border-radius) - 4px) calc(var(--ci360-popper-border-radius) - 4px) 0 0;margin:calc(var(--ci360-popper-padding) * -1);margin-bottom:12px;width:calc(100% + var(--ci360-popper-padding) * 2)}.ci360-popper-image{display:block;width:100%;height:100%;-o-object-fit:cover;object-fit:cover}.ci360-popper-body{line-height:1.5;text-align:left}.ci360-popper-title{margin:0 0 4px;font-size:var(--ci360-popper-title-font-size);font-weight:var(--ci360-popper-title-font-weight);color:var(--ci360-popper-title-color);line-height:1.3}.ci360-popper-price-row{display:inline-flex;align-items:baseline;gap:6px;margin-bottom:8px;flex-wrap:wrap}.ci360-popper-price{font-size:var(--ci360-popper-price-font-size);font-weight:var(--ci360-popper-price-font-weight);color:var(--ci360-popper-price-color)}.ci360-popper-price-row .ci360-popper-price{margin-bottom:0}.ci360-popper-original-price{font-size:calc(var(--ci360-popper-price-font-size) - 2px);font-weight:500;color:var(--ci360-popper-original-price-color);text-decoration:line-through}.ci360-popper-description{margin:0 0 12px;color:var(--ci360-popper-description-color)}.ci360-popper-cta{display:inline-block;padding:var(--ci360-popper-cta-padding);background:var(--ci360-popper-cta-bg);color:var(--ci360-popper-cta-color);border-radius:var(--ci360-popper-cta-border-radius);text-decoration:none;font-weight:600;font-size:14px;transition:opacity .2s ease}.ci360-popper-cta:hover{opacity:.9}button.ci360-popper-cta{cursor:pointer;border:none;font:inherit;width:100%}.ci360-popper-cta:focus-visible{outline:3px solid var(--ci360-focus-color, #0066cc);outline-offset:2px}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js-cloudimage-360-view",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.9.2",
|
|
4
4
|
"main": "dist/js-cloudimage-360-view.min.js",
|
|
5
5
|
"types": "src/types/ci360.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
"@babel/plugin-transform-runtime": "^7.16.5",
|
|
84
84
|
"@babel/preset-env": "^7.16.5",
|
|
85
85
|
"@eslint/js": "^9.12.0",
|
|
86
|
+
"@playwright/test": "^1.58.2",
|
|
86
87
|
"@types/react": "^18.2.0",
|
|
87
88
|
"@types/react-dom": "^18.2.0",
|
|
88
89
|
"@vitejs/plugin-react": "^4.2.0",
|
package/src/react/types.d.ts
CHANGED
|
@@ -76,6 +76,8 @@ export interface Hotspot {
|
|
|
76
76
|
content?: string;
|
|
77
77
|
data?: PopoverData;
|
|
78
78
|
className?: string;
|
|
79
|
+
/** Scene ID to navigate to when this hotspot is clicked. */
|
|
80
|
+
navigateTo?: string;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
/**
|
|
@@ -93,6 +95,7 @@ export interface SpinEventData {
|
|
|
93
95
|
activeImageY: number;
|
|
94
96
|
amountX: number;
|
|
95
97
|
amountY: number;
|
|
98
|
+
isGridMode: boolean;
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
/**
|
|
@@ -102,6 +105,7 @@ export interface LoadEventData {
|
|
|
102
105
|
viewerId: string;
|
|
103
106
|
imagesX: number;
|
|
104
107
|
imagesY: number;
|
|
108
|
+
imagesGrid?: number;
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
/**
|
|
@@ -140,6 +144,8 @@ export interface CI360Config {
|
|
|
140
144
|
filenameY?: string | null;
|
|
141
145
|
imageListX?: string | string[] | null;
|
|
142
146
|
imageListY?: string | string[] | null;
|
|
147
|
+
filenameGrid?: string | null;
|
|
148
|
+
imageListGrid?: string | string[] | string[][] | null;
|
|
143
149
|
indexZeroBase?: number;
|
|
144
150
|
amountX?: number;
|
|
145
151
|
amountY?: number;
|
|
@@ -155,6 +161,8 @@ export interface CI360Config {
|
|
|
155
161
|
dragSpeed?: number;
|
|
156
162
|
dragReverse?: boolean;
|
|
157
163
|
stopAtEdges?: boolean;
|
|
164
|
+
stopAtEdgesX?: boolean | null;
|
|
165
|
+
stopAtEdgesY?: boolean | null;
|
|
158
166
|
inertia?: boolean;
|
|
159
167
|
fullscreen?: boolean;
|
|
160
168
|
/** @deprecated Use zoomMax instead. Will be ignored. */
|
|
@@ -201,6 +209,7 @@ export interface CI360Config {
|
|
|
201
209
|
onHotspotOpen?: (hotspotId: string) => void;
|
|
202
210
|
onHotspotClose?: (hotspotId: string) => void;
|
|
203
211
|
onProductClick?: (productId: string, hotspotId: string) => void;
|
|
212
|
+
onNavigate?: (targetSceneId: string) => void;
|
|
204
213
|
onError?: (data: ErrorEventData) => void;
|
|
205
214
|
}
|
|
206
215
|
|
|
@@ -234,6 +243,7 @@ export interface CI360ViewerInstance {
|
|
|
234
243
|
amountX: number;
|
|
235
244
|
amountY: number;
|
|
236
245
|
isZoomed: boolean;
|
|
246
|
+
isGridMode: boolean;
|
|
237
247
|
viewerConfig: CI360Config;
|
|
238
248
|
}
|
|
239
249
|
|