{"version":3,"file":"index.cjs","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    initOnClick,\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      initOnClick,\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      initOnClick,\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","initOnClick","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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,EACA,YAAAC,EACF,aAAAC,EACA,aAAAC,EACE,QAAAC,EAGA,WAAAC,EACA,UAAAC,EACA,YAAAC,EACA,UAAAC,EACA,QAAAC,EACA,SAAAC,EACA,aAAAC,EACA,qBAAAC,EACA,WAAAC,EACA,aAAAC,EACA,mBAAAC,EACA,iBAAAC,EACA,YAAAC,EACA,QAAAC,EACA,UAAAC,EACA,MAAAC,GACA,MAAAC,GACA,YAAAC,GACA,WAAAC,GAGA,QAAAC,GACA,UAAAC,GACA,iBAAAC,GACA,gBAAAC,GACA,YAAAC,GAGA,SAAAC,GAGA,SAAAC,GACA,eAAAC,GACA,uBAAAC,GACA,YAAAC,GAGA,YAAAC,GAGA,QAAAC,GACA,OAAAC,GACA,OAAAC,GACA,gBAAAC,GACA,eAAAC,GACA,iBAAAC,GACA,kBAAAC,GACA,SAAAC,GACA,UAAAC,GACA,YAAAC,GACA,UAAAC,GACA,cAAAC,GACA,eAAAC,GACA,eAAAC,GACA,WAAAC,GACA,QAAAC,EAAA,GAEF,CAEEvE,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EAGAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACFC,EACAC,EACEC,EAGAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,GACAC,GACAC,GACAC,GAGAC,GACAC,GACAC,GACAC,GACAC,GAGAC,GAGAC,GACAC,GACAC,GACAC,GAGAC,GAGAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,GACAC,EAAA,CACF,EAGI,CAAE,UAAA/E,CAAA,EAAclB,EAASC,GAAcC,EAAM,EAKnDkG,OAAAA,EAAAA,oBACE9E,EACA,KAAO,CACL,SAAU,CAAC+E,EAAQ,IAAA,OAAM,OAAArF,EAAAE,MAAA,YAAAF,EAAa,SAAS,GAAOqF,IACtD,UAAW,CAACA,EAAQ,IAAA,OAAM,OAAArF,EAAAE,MAAA,YAAAF,EAAa,UAAU,GAAOqF,IACxD,QAAS,CAACA,EAAQ,IAAA,OAAM,OAAArF,EAAAE,MAAA,YAAAF,EAAa,QAAQ,GAAOqF,IACpD,WAAY,CAACA,EAAQ,IAAA,OAAM,OAAArF,EAAAE,MAAA,YAAAF,EAAa,WAAW,GAAOqF,IAC1D,KAAM,IAAA,OAAM,OAAArF,EAAAE,EAAA,IAAA,YAAAF,EAAa,QACzB,KAAM,IAAA,OAAM,OAAAA,EAAAE,EAAA,IAAA,YAAAF,EAAa,gBACzB,OAAQ,IAAA,SAAM,OAAAsF,GAAAtF,EAAAE,MAAA,YAAAF,EAAa,UAAb,YAAAsF,EAAsB,UACpC,QAAS,IAAA,SAAM,OAAAA,GAAAtF,EAAAE,MAAA,YAAAF,EAAa,UAAb,YAAAsF,EAAsB,WACrC,UAAW,IAAA,SAAM,OAAAA,GAAAtF,EAAAE,MAAA,YAAAF,EAAa,UAAb,YAAAsF,EAAsB,aACvC,QAAUC,GAAA,SAAkB,OAAAD,GAAAtF,EAAAE,MAAA,YAAAF,EAAa,UAAb,YAAAsF,EAAsB,QAAQC,IAC1D,UAAW,CAACC,EAAeC,IAAA,OACzB,OAAAzF,EAAAE,MAAA,YAAAF,EAAa,eAAewF,EAAOC,IACrC,UAAW,IAAMvF,EAAA,CAAU,GAE7B,CAACA,CAAS,CAAA,EAIVwF,GAAAA,IAAC,MAAA,CACC,IAAKzG,GACL,GAAAsB,EACA,UAAAC,EACA,MAAAC,EACC,GAAGyE,EAAA,CAAA,CAGV,EAEaS,EAAcC,EAAAA,WAAWxF,EAAoB,EAC1DuF,EAAY,YAAc"}