{"version":3,"file":"ModelViewer.mjs","sources":["../../src/ModelViewer.tsx"],"sourcesContent":["import {useState, useEffect, useCallback} from 'react';\nimport {useLoadScript} from './load-script.js';\nimport type {Model3d} from './storefront-api-types.js';\nimport type {PartialDeep} from 'type-fest';\nimport type {ModelViewerElement} from '@google/model-viewer/lib/model-viewer.js';\n\ntype PropsWeControl = 'src';\n\ndeclare global {\n  // eslint-disable-next-line @typescript-eslint/no-namespace\n  namespace JSX {\n    interface IntrinsicElements {\n      'model-viewer': PartialDeep<\n        ModelViewerElement,\n        {recurseIntoArrays: true}\n      >;\n    }\n  }\n}\n\ntype ModelViewerProps = Omit<\n  PartialDeep<JSX.IntrinsicElements['model-viewer'], {recurseIntoArrays: true}>,\n  PropsWeControl\n> & {\n  /** An object with fields that correspond to the Storefront API's [Model3D object](https://shopify.dev/api/storefront/latest/objects/model3d). */\n  data: PartialDeep<Model3d, {recurseIntoArrays: true}>;\n  /** The callback to invoke when the 'error' event is triggered. Refer to [error in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-error). */\n  onError?: (event: Event) => void;\n  /** The callback to invoke when the `load` event is triggered. Refer to [load in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-load). */\n  onLoad?: (event: Event) => void;\n  /** The callback to invoke when the 'preload' event is triggered. Refer to [preload in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-preload). */\n  onPreload?: (event: Event) => void;\n  /** The callback to invoke when the 'model-visibility' event is triggered. Refer to [model-visibility in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-modelVisibility). */\n  onModelVisibility?: (event: Event) => void;\n  /** The callback to invoke when the 'progress' event is triggered. Refer to [progress in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-loading-events-progress). */\n  onProgress?: (event: Event) => void;\n  /** The callback to invoke when the 'ar-status' event is triggered. Refer to [ar-status in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-augmentedreality-events-arStatus). */\n  onArStatus?: (event: Event) => void;\n  /** The callback to invoke when the 'ar-tracking' event is triggered. Refer to [ar-tracking in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-augmentedreality-events-arTracking). */\n  onArTracking?: (event: Event) => void;\n  /** The callback to invoke when the 'quick-look-button-tapped' event is triggered. Refer to [quick-look-button-tapped in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-augmentedreality-events-quickLookButtonTapped). */\n  onQuickLookButtonTapped?: (event: Event) => void;\n  /** The callback to invoke when the 'camera-change' event is triggered. Refer to [camera-change in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-stagingandcameras-events-cameraChange). */\n  onCameraChange?: (event: Event) => void;\n  /** The callback to invoke when the 'environment-change' event is triggered. Refer to [environment-change in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-lightingandenv-events-environmentChange).  */\n  onEnvironmentChange?: (event: Event) => void;\n  /**  The callback to invoke when the 'play' event is triggered. Refer to [play in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-animation-events-play). */\n  onPlay?: (event: Event) => void;\n  /**  The callback to invoke when the 'pause' event is triggered. Refer to [pause in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-animation-events-pause). */\n  onPause?: (event: Event) => void;\n  /** The callback to invoke when the 'scene-graph-ready' event is triggered. Refer to [scene-graph-ready in the <model-viewer> documentation](https://modelviewer.dev/docs/index.html#entrydocs-scenegraph-events-sceneGraphReady). */\n  onSceneGraphReady?: (event: Event) => void;\n};\n\n/**\n * The `ModelViewer` component renders a 3D model (with the `model-viewer` custom element) for\n * the Storefront API's [Model3d object](https://shopify.dev/api/storefront/reference/products/model3d).\n *\n * The `model-viewer` custom element is lazily downloaded through a dynamically-injected `<script type=\"module\">` tag when the `<ModelViewer />` component is rendered\n *\n * ModelViewer is using version `1.21.1` of the `@google/model-viewer` library.\n */\nexport function ModelViewer(props: ModelViewerProps) {\n  const [modelViewer, setModelViewer] = useState<undefined | HTMLElement>(\n    undefined\n  );\n  const callbackRef = useCallback((node: HTMLElement) => {\n    setModelViewer(node);\n  }, []);\n  const {data, children, className, ...passthroughProps} = props;\n\n  const modelViewerLoadedStatus = useLoadScript(\n    'https://unpkg.com/@google/model-viewer@v1.12.1/dist/model-viewer.min.js',\n    {\n      module: true,\n    }\n  );\n\n  useEffect(() => {\n    if (!modelViewer) {\n      return;\n    }\n    if (passthroughProps.onError)\n      modelViewer.addEventListener('error', passthroughProps.onError);\n    if (passthroughProps.onLoad)\n      modelViewer.addEventListener('load', passthroughProps.onLoad);\n    if (passthroughProps.onPreload)\n      modelViewer.addEventListener('preload', passthroughProps.onPreload);\n    if (passthroughProps.onModelVisibility)\n      modelViewer.addEventListener(\n        'model-visibility',\n        passthroughProps.onModelVisibility\n      );\n    if (passthroughProps.onProgress)\n      modelViewer.addEventListener('progress', passthroughProps.onProgress);\n    if (passthroughProps.onArStatus)\n      modelViewer.addEventListener('ar-status', passthroughProps.onArStatus);\n    if (passthroughProps.onArTracking)\n      modelViewer.addEventListener(\n        'ar-tracking',\n        passthroughProps.onArTracking\n      );\n    if (passthroughProps.onQuickLookButtonTapped)\n      modelViewer.addEventListener(\n        'quick-look-button-tapped',\n        passthroughProps.onQuickLookButtonTapped\n      );\n    if (passthroughProps.onCameraChange)\n      modelViewer.addEventListener(\n        'camera-change',\n        passthroughProps.onCameraChange\n      );\n    if (passthroughProps.onEnvironmentChange)\n      modelViewer.addEventListener(\n        'environment-change',\n        passthroughProps.onEnvironmentChange\n      );\n    if (passthroughProps.onPlay)\n      modelViewer.addEventListener('play', passthroughProps.onPlay);\n    if (passthroughProps.onPause)\n      modelViewer.addEventListener('ar-status', passthroughProps.onPause);\n    if (passthroughProps.onSceneGraphReady)\n      modelViewer.addEventListener(\n        'scene-graph-ready',\n        passthroughProps.onSceneGraphReady\n      );\n\n    return () => {\n      if (modelViewer == null) {\n        return;\n      }\n      if (passthroughProps.onError)\n        modelViewer.removeEventListener('error', passthroughProps.onError);\n      if (passthroughProps.onLoad)\n        modelViewer.removeEventListener('load', passthroughProps.onLoad);\n      if (passthroughProps.onPreload)\n        modelViewer.removeEventListener('preload', passthroughProps.onPreload);\n      if (passthroughProps.onModelVisibility)\n        modelViewer.removeEventListener(\n          'model-visibility',\n          passthroughProps.onModelVisibility\n        );\n      if (passthroughProps.onProgress)\n        modelViewer.removeEventListener(\n          'progress',\n          passthroughProps.onProgress\n        );\n      if (passthroughProps.onArStatus)\n        modelViewer.removeEventListener(\n          'ar-status',\n          passthroughProps.onArStatus\n        );\n      if (passthroughProps.onArTracking)\n        modelViewer.removeEventListener(\n          'ar-tracking',\n          passthroughProps.onArTracking\n        );\n      if (passthroughProps.onQuickLookButtonTapped)\n        modelViewer.removeEventListener(\n          'quick-look-button-tapped',\n          passthroughProps.onQuickLookButtonTapped\n        );\n      if (passthroughProps.onCameraChange)\n        modelViewer.removeEventListener(\n          'camera-change',\n          passthroughProps.onCameraChange\n        );\n      if (passthroughProps.onEnvironmentChange)\n        modelViewer.removeEventListener(\n          'environment-change',\n          passthroughProps.onEnvironmentChange\n        );\n      if (passthroughProps.onPlay)\n        modelViewer.removeEventListener('play', passthroughProps.onPlay);\n      if (passthroughProps.onPause)\n        modelViewer.removeEventListener('ar-status', passthroughProps.onPause);\n      if (passthroughProps.onSceneGraphReady)\n        modelViewer.removeEventListener(\n          'scene-graph-ready',\n          passthroughProps.onSceneGraphReady\n        );\n    };\n  }, [\n    modelViewer,\n    passthroughProps.onArStatus,\n    passthroughProps.onArTracking,\n    passthroughProps.onCameraChange,\n    passthroughProps.onEnvironmentChange,\n    passthroughProps.onError,\n    passthroughProps.onLoad,\n    passthroughProps.onModelVisibility,\n    passthroughProps.onPause,\n    passthroughProps.onPlay,\n    passthroughProps.onPreload,\n    passthroughProps.onProgress,\n    passthroughProps.onQuickLookButtonTapped,\n    passthroughProps.onSceneGraphReady,\n  ]);\n\n  if (modelViewerLoadedStatus !== 'done') {\n    // TODO: What do we want to display while the model-viewer library loads?\n    return null;\n  }\n\n  if (!data.sources?.[0]?.url) {\n    const sourcesUrlError = `<ModelViewer/> requires 'data.sources' prop to be an array, with an object that has a property 'url' on it. Rendering 'null'`;\n    if (__HYDROGEN_DEV__) {\n      throw new Error(sourcesUrlError);\n    } else {\n      console.error(sourcesUrlError);\n      return null;\n    }\n  }\n\n  if (__HYDROGEN_DEV__ && !data.alt) {\n    console.warn(\n      `<ModelViewer/> requires the 'data.alt' prop for accessibility`\n    );\n  }\n\n  return (\n    <model-viewer\n      // @ts-expect-error ref should exist\n      ref={callbackRef}\n      {...passthroughProps}\n      className={className}\n      id={passthroughProps.id ?? data.id}\n      src={data.sources[0].url}\n      alt={data.alt ?? null}\n      camera-controls={passthroughProps.cameraControls ?? true}\n      poster={(passthroughProps.poster || data.previewImage?.url) ?? null}\n      autoplay={passthroughProps.autoplay ?? true}\n      loading={passthroughProps.loading}\n      reveal={passthroughProps.reveal}\n      ar={passthroughProps.ar}\n      ar-modes={passthroughProps.arModes}\n      ar-scale={passthroughProps.arScale}\n      // @ts-expect-error arPlacement should exist as a type, not sure why it doesn't. https://modelviewer.dev/docs/index.html#entrydocs-augmentedreality-attributes-arPlacement\n      ar-placement={passthroughProps.arPlacement}\n      ios-src={passthroughProps.iosSrc}\n      touch-action={passthroughProps.touchAction}\n      disable-zoom={passthroughProps.disableZoom}\n      orbit-sensitivity={passthroughProps.orbitSensitivity}\n      auto-rotate={passthroughProps.autoRotate}\n      auto-rotate-delay={passthroughProps.autoRotateDelay}\n      // @ts-expect-error rotationPerSecond should exist as a type, not sure why it doesn't. https://modelviewer.dev/docs/index.html#entrydocs-stagingandcameras-attributes-rotationPerSecond\n      rotation-per-second={passthroughProps.rotationPerSecond}\n      interaction-policy={passthroughProps.interactionPolicy}\n      interaction-prompt={passthroughProps.interactionPrompt}\n      interaction-prompt-style={passthroughProps.interactionPromptStyle}\n      interaction-prompt-threshold={passthroughProps.interactionPromptThreshold}\n      camera-orbit={passthroughProps.cameraOrbit}\n      camera-target={passthroughProps.cameraTarget}\n      field-of-view={passthroughProps.fieldOfView}\n      max-camera-orbit={passthroughProps.maxCameraOrbit}\n      min-camera-orbit={passthroughProps.minCameraOrbit}\n      max-field-of-view={passthroughProps.maxFieldOfView}\n      min-field-of-view={passthroughProps.minFieldOfView}\n      bounds={passthroughProps.bounds}\n      interpolation-decay={passthroughProps.interpolationDecay ?? 100}\n      skybox-image={passthroughProps.skyboxImage}\n      environment-image={passthroughProps.environmentImage}\n      exposure={passthroughProps.exposure}\n      shadow-intensity={passthroughProps.shadowIntensity ?? 0}\n      shadow-softness={passthroughProps.shadowSoftness ?? 0}\n      animation-name={passthroughProps.animationName}\n      animation-crossfade-duration={passthroughProps.animationCrossfadeDuration}\n      variant-name={passthroughProps.variantName}\n      orientation={passthroughProps.orientation}\n      scale={passthroughProps.scale}\n    >\n      {children}\n    </model-viewer>\n  );\n}\n"],"names":["ModelViewer","props","modelViewer","setModelViewer","useState","undefined","callbackRef","useCallback","node","data","children","className","passthroughProps","modelViewerLoadedStatus","useLoadScript","module","useEffect","onError","addEventListener","onLoad","onPreload","onModelVisibility","onProgress","onArStatus","onArTracking","onQuickLookButtonTapped","onCameraChange","onEnvironmentChange","onPlay","onPause","onSceneGraphReady","removeEventListener","sources","url","sourcesUrlError","Error","__HYDROGEN_DEV__","alt","console","warn","id","cameraControls","poster","previewImage","autoplay","loading","reveal","ar","arModes","arScale","arPlacement","iosSrc","touchAction","disableZoom","orbitSensitivity","autoRotate","autoRotateDelay","rotationPerSecond","interactionPolicy","interactionPrompt","interactionPromptStyle","interactionPromptThreshold","cameraOrbit","cameraTarget","fieldOfView","maxCameraOrbit","minCameraOrbit","maxFieldOfView","minFieldOfView","bounds","interpolationDecay","skyboxImage","environmentImage","exposure","shadowIntensity","shadowSoftness","animationName","animationCrossfadeDuration","variantName","orientation","scale"],"mappings":"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"}