import { default as default_2 } from 'react'; import * as React_2 from 'react'; import * as THREE from 'three'; /** * A soft, shadowless directional light used for the fill and rim/back roles of * a studio three-point rig. Same direction semantics as the key, but it never * casts shadows (only the key does — see `findDirectionalLight`, which resolves * the first directional as the shadow/contact-shadow source). */ export declare interface AccentLightOptions { color?: string | number; intensity?: number; /** Direction is position → origin; distance does not attenuate. */ position?: Vec3Like | [number, number, number]; } /** Uniform fill from every direction; lifts shadows, adds no shading. */ export declare interface AmbientLightOptions { color?: string | number; intensity?: number; } export declare interface AnimationOptions { /** * Start playback when a model with clips loads: `true` plays ALL clips * (looped), a string plays the clip with that name. */ autoplay?: boolean | string; /** Playback rate multiplier (1 = authored speed). Applied live. */ speed?: number; } /** * AR handoff configuration: a small button over the canvas that opens the * model in the platform's native AR viewer — AR Quick Look on iOS, Scene * Viewer on Android. UI-only: the button never touches the WebGL viewer, and * toggling it never rebuilds anything. The button only renders on devices * that can actually hand off (never on desktop). */ export declare interface AROptions { /** * USDZ counterpart of the model, for iOS AR Quick Look — Quick Look cannot * read GLB, so without this the button stays hidden on iOS. Android Scene * Viewer instead reuses the loaded model's own URL and needs nothing here * (but requires the model to be loaded from a network URL — a dropped * `blob:` file has no address a native app could fetch). */ iosSrc?: string; /** Title shown on Android Scene Viewer's info card. */ title?: string; /** * Corner the button floats in (default `bottom-left`). When the built-in * preset picker is enabled, a bottom-placed button lifts above the chip * row on its own — pick a top corner if it must clear other chrome (e.g. * a `bottom-left` gizmo). */ placement?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; } export declare interface AxesHelperOptions { size?: number; } /** Perspective camera setup. World units are meters (see `units`). */ export declare interface CameraOptions { /** Starting camera position as `[x, y, z]`. */ position?: [number, number, number]; /** Point the camera looks at and the controls orbit around. */ target?: [number, number, number]; /** Vertical field of view in degrees. */ fov?: number; /** Near clipping plane distance. */ near?: number; /** Far clipping plane distance. */ far?: number; /** * Frame the loaded model automatically (default `true`): the camera moves * to a standard product-shot view — left-front, slightly elevated — around * the model's center, at a distance computed from its bounds, and the * controls re-target the center. This OVERRIDES `position`/`target`; * disable it to keep your configured view exactly. */ autoFitToObject?: boolean; } /** * Output size for `captureStill`, in pixels. When only one dimension is given * the other follows the canvas aspect ratio; when both are omitted the still * matches the canvas drawing buffer. */ export declare interface CaptureStillOptions { width?: number; height?: number; } export declare interface CaptureVideoOptions { /** Capture length in seconds. Default 3. */ duration?: number; /** Frame rate handed to `canvas.captureStream()`. Default 30. */ fps?: number; /** * Preferred container/codec (e.g. `'video/webm;codecs=vp9'`). When omitted * or unsupported the best supported WebM flavor is picked, falling back to * MP4 (Safari) and finally the browser default. */ mimeType?: string; /** Encoder bitrate hint in bits per second. */ videoBitsPerSecond?: number; } export declare type ControlsInstance = { enabled: boolean; update(): void; dispose(): void; target: THREE.Vector3; getThreeControls?(): unknown; }; /** Mouse/touch camera controls (three.js OrbitControls semantics). */ export declare interface ControlsOptions { /** * `OrbitControls` (default) orbits around the model like a turntable; * `MapControls` pans on drag instead — the map/floor-plan idiom. */ type?: ControlType; /** Master switch: `false` freezes all user camera input. */ enabled?: boolean; /** Inertial easing after a drag ends, instead of an instant stop. */ enableDamping?: boolean; /** Damping strength: lower = longer glide (softbox default 0.25). */ dampingFactor?: number; /** Allow dolly/zoom (wheel, pinch). */ enableZoom?: boolean; /** Allow orbiting (primary-button drag). */ enableRotate?: boolean; /** Allow panning (secondary-button or two-finger drag). */ enablePan?: boolean; /** * Turntable mode: the camera orbits the model on its own. Runtime-tunable * via `updateOptions`. While spinning, a path-traced `captureStill()` * rejects — the accumulation resets every frame and can never converge. */ autoRotate?: boolean; /** Turntable speed: 2.0 ≈ one full orbit in 30 s at 60 fps. */ autoRotateSpeed?: number; /** Closest dolly distance to the target. */ minDistance?: number; /** Farthest dolly distance from the target. */ maxDistance?: number; /** Lowest vertical orbit angle in radians (0 = looking straight down from above). */ minPolarAngle?: number; /** Highest vertical orbit angle in radians (π = from below; π/2 stops at the horizon). */ maxPolarAngle?: number; } export declare enum ControlType { MapControls = "MapControls", OrbitControls = "OrbitControls" } /** * Photographic PBR maps for the outdoor concrete ground (CC0, Poly Haven; * ~600 KB total, same CDN and override/self-host contract as the HDRI). * Captured micro-structure is what reads as real concrete; the procedural * generator stays as the offline fallback when these fail to fetch. */ export declare const DEFAULT_OUTDOOR_CONCRETE_TEXTURES: { readonly texture: "https://dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/concrete_floor_02/concrete_floor_02_diff_1k.jpg"; readonly normalMap: "https://dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/concrete_floor_02/concrete_floor_02_nor_gl_1k.jpg"; readonly roughnessMap: "https://dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/concrete_floor_02/concrete_floor_02_rough_1k.jpg"; }; /** * The daylight HDRI `outdoor_concrete` lights with when no explicit * `environment.url` is given: a bright partly-cloudy sky (CC0, Poly Haven; * the projection shows its soft open terrain at the horizon), fetched on * demand from their CDN — the one network request the outdoor scene makes. * Pass your own `environment.url` to override or self-host, exactly like * the DRACO/KTX2 decoder paths. (Urban candidates — potsdamer_platz, * quarry_01 — were rejected visually: dusk-dark and olive-tinted grounds.) */ export declare const DEFAULT_OUTDOOR_HDRI_URL = "https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/2k/kloofendal_48d_partly_cloudy_puresky_2k.hdr"; /** The scene every viewer stands in when none is set. */ export declare const DEFAULT_SCENE: ViewerScene; /** The grade the studio environment is built with when none is set. */ export declare const DEFAULT_STUDIO_LOOK: StudioLook; /** * Default options using the new format structure */ export declare const defaultOptions: SimpleViewerOptions; /** * The key light: parallel rays from `position` toward the origin. The only * light that casts shadows — the contact-shadow bake samples it as an area * light, so its direction sets where the floor shadow falls. */ export declare interface DirectionalLightOptions { color?: string | number; intensity?: number; /** Direction is position → origin; distance does not attenuate. */ position?: Vec3Like | [number, number, number]; /** Cast real-time shadows (and feed the baked contact shadow). */ castShadow?: boolean; /** three.js DirectionalLight.shadow tuning; the shadow camera is auto-fitted to the model on load. */ shadow?: { /** Shadow map resolution — higher is crisper and costs GPU memory. */ mapSize?: { width: number; height: number; }; /** * Orthographic frustum: every plane (left/right/top/bottom AND near/far) * is overridden by the auto-fit on load, so the shadow-map texel density * and the bias's world-space offset both scale with the model. */ camera?: { near?: number; far?: number; left?: number; right?: number; top?: number; bottom?: number; }; /** Depth offset against shadow acne (self-shadowing stripes). */ bias?: number; /** * WORLD-SPACE offset along the receiver's normal against shadow acne. * Unlike `bias` (normalized depth, whose world effect scales with the * fitted camera range), this is absolute — the scale-correct escape hatch * if acne ever shows on a model's own surfaces. */ normalBias?: number; /** Shadow edge blur in shadow-map texels. */ radius?: number; }; } /** * Image-based lighting and background. Without a `url` the viewer lights the * scene with its built-in procedural studio environment — zero network * requests. */ export declare interface EnvironmentOptions { /** * Equirectangular environment map (`.hdr`, `.exr`, or an LDR image) used * for both lighting and the background. */ url?: string; /** Blurs the background rendering only (0–1); lighting stays sharp. */ backgroundBlurriness?: number; /** Brightness multiplier for the background rendering only. */ backgroundIntensity?: number; /** * Lighting intensity multiplier the environment applies to materials. * Runtime-tunable via `updateOptions` — presets drive this live. */ environmentIntensity?: number; /** Grade of the built-in studio environment; ignored when `url` is set. */ studioLook?: StudioLook; /** * Project the environment map onto a virtual ground plane so the model * appears to STAND in the environment instead of floating in front of it — * the outdoor scenes' horizon treatment (three's GroundedSkybox). `true` * uses the defaults (height 2m — a typical eye-level HDRI shot — and a * 120m world radius); pass numbers to match an HDRI shot from another * height or a larger set. Only applies when `url` is set. Structural — * changing it rebuilds the viewer. * * While active the projection mesh IS the visible backdrop, so * `backgroundBlurriness` has no effect (`backgroundIntensity` is emulated * by dimming the projection). */ groundProjection?: boolean | { height?: number; radius?: number; }; } export declare enum ErrorCode { SCENE_INIT_FAILED = "SCENE_INIT_FAILED", RENDERER_INIT_FAILED = "RENDERER_INIT_FAILED", RENDERER_NOT_INITIALIZED = "RENDERER_NOT_INITIALIZED", CAMERA_INIT_FAILED = "CAMERA_INIT_FAILED", WEBGL_NOT_SUPPORTED = "WEBGL_NOT_SUPPORTED", INITIALIZATION_FAILED = "INITIALIZATION_FAILED", PATH_TRACING_INIT_FAILED = "PATH_TRACING_INIT_FAILED", MODEL_LOAD_FAILED = "MODEL_LOAD_FAILED", TEXTURE_LOAD_FAILED = "TEXTURE_LOAD_FAILED", RESOURCE_NOT_FOUND = "RESOURCE_NOT_FOUND", UNSUPPORTED_FORMAT = "UNSUPPORTED_FORMAT", INVALID_CONFIGURATION = "INVALID_CONFIGURATION", RENDER_ERROR = "RENDER_ERROR", RENDER_FAILED = "RENDER_FAILED", SCENE_OPERATION_FAILED = "SCENE_OPERATION_FAILED", COMPONENT_NOT_MOUNTED = "COMPONENT_NOT_MOUNTED", INVALID_STATE = "INVALID_STATE", INVALID_PARAMETER = "INVALID_PARAMETER", OPERATION_FAILED = "OPERATION_FAILED", POST_PROCESSING_FAILED = "POST_PROCESSING_FAILED", UNKNOWN = "UNKNOWN" } export declare interface ErrorContext { [key: string]: unknown; } export declare interface GizmoOptions { placement?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; size?: number; } export declare interface GridHelperOptions { size?: number; divisions?: number; colorCenterLine?: string | number; colorGrid?: string | number; type?: 'shadow_floor' | 'concrete_disc' | 'square_wire' | 'hexagonal_wire' | 'hexagonal_glass' | 'stone_tiles'; opacity?: number; styleOptions?: { hexRadius?: number; tileSize?: number; texture?: string; normalMap?: string; roughnessMap?: string; metalness?: number; roughness?: number; transmission?: number; thickness?: number; ior?: number; height?: number; bevelSize?: number; randomHeight?: boolean; randomRotation?: boolean; }; } export declare interface HelperOptions { grid?: boolean | GridHelperOptions; axes?: boolean | AxesHelperOptions; stats?: boolean; gizmo?: boolean | GizmoOptions; studioEnvironment?: boolean; darkStudioMode?: boolean; } /** * Two-tone gradient fill: one color arriving from above, another bouncing up * from below. The default rig uses a warm pale-yellow sky over a dark navy * ground. */ export declare interface HemisphereLightOptions { /** Color arriving from above. */ skyColor?: string | number; /** Color bouncing up from below. */ groundColor?: string | number; intensity?: number; } /** * A DOM annotation anchored to a world-space point of the scene. Render it as * a child of `SimpleViewer`; the anchor is projected through the camera after * every rendered frame, so it tracks orbiting, zooming and resizes. Points * behind the camera are hidden; `occlude` also hides it when the model covers * the anchor. The projection math lives behind the viewer's anchor-projection * port — this component only wires events to DOM styles. */ export declare function Hotspot({ position, occlude, children }: HotspotProps): default_2.JSX.Element; export declare interface HotspotProps { /** World-space anchor point, e.g. a `point` from the `object:selected` event. */ position: [number, number, number]; /** * Hide the hotspot when the model occludes its anchor point (a raycast per * rendered frame). Off by default. */ occlude?: boolean; /** Pin content; without children a default dot pin is rendered. */ children?: default_2.ReactNode; } /** * The studio rig. Every light is optional; the defaults are a balanced * product-shot three-point setup (see `defaultOptions.lighting`): a shadow- * casting key, a soft opposite-side fill that opens the shadow, and a rim/back * light behind the subject that separates its silhouette from the background. * Ambient + hemisphere add a gentle omnidirectional base. */ export declare interface LightingOptions { ambientLight?: AmbientLightOptions; hemisphereLight?: HemisphereLightOptions; directionalLight?: DirectionalLightOptions; /** Soft opposite-side fill; opens the shadow side without a second shadow. */ fillLight?: AccentLightOptions; /** Rim/back light behind the subject; separates the silhouette from the backdrop. */ rimLight?: AccentLightOptions; } /** * Compression-decoder configuration for the built-in glTF/GLB loader. * * DRACO (geometry), KTX2/Basis (textures) and Meshopt (geometry) are all wired * into the loader by default, so compressed assets exported by Blender, * `gltfpack`, `gltf-transform`, etc. load without any extra setup. * * Meshopt is bundled and needs no external file. DRACO and KTX2 require a small * WebAssembly decoder that is fetched **on demand** — only the first time an * asset actually uses that compression — from a version-pinned CDN by default. * Point `dracoDecoderPath` / `ktx2TranscoderPath` at a self-hosted copy (e.g. * `three/examples/jsm/libs/draco/` and `.../basis/` copied into your public dir) * for a fully offline, no-CDN setup. */ export declare interface LoaderOptions { /** Decode DRACO-compressed geometry. Default: `true`. */ draco?: boolean; /** Decode KTX2 / Basis-compressed textures. Default: `true`. */ ktx2?: boolean; /** Decode Meshopt-compressed geometry. Default: `true`. */ meshopt?: boolean; /** * Directory holding the DRACO decoder (`draco_wasm_wrapper.js` + * `draco_decoder.wasm`). Must end with a trailing slash. Defaults to a * version-pinned jsDelivr URL matching the installed Three.js revision. */ dracoDecoderPath?: string; /** * Directory holding the KTX2 Basis transcoder (`basis_transcoder.js` + * `basis_transcoder.wasm`). Must end with a trailing slash. Defaults to a * version-pinned jsDelivr URL matching the installed Three.js revision. */ ktx2TranscoderPath?: string; } /** * Configuration for the built-in loading overlay shown while a model loads. * * Pass a boolean on `SimpleViewerOptions.loadingIndicator` to toggle the * default overlay, or this object to customize it. Set `loadingIndicator: false` * to render your own using the `model:loading` / `model:loaded` / `model:error` * events on the viewer handle. */ export declare interface LoadingIndicatorOptions { /** Show the built-in overlay. Default: `true`. */ enabled?: boolean; /** Text under the spinner while loading. Default: `'Loading…'`. */ label?: string; /** Message shown if the model fails to load. Default: the error message. */ errorLabel?: string; /** Spinner and text color. Default: `'#ffffff'`. */ color?: string; /** Backdrop scrim behind the spinner. Default: a subtle dark scrim. */ backdrop?: string; } /** Length unit the model's geometry is authored in. */ export declare type ModelUnits = 'meters' | 'centimeters' | 'millimeters' | 'feet' | 'inches'; /** * Progressive path tracing for photoreal rendering (three-gpu-pathtracer). * Interactive: while the camera moves you see a fast preview, and whenever it * rests the tracer re-accumulates to a converged frame — orbiting after * convergence starts a fresh accumulation from the new viewpoint. The tracer * stays warm for the viewer's lifetime; it ships in a lazy chunk that loads * only when enabled. While animations play, accumulation is suspended (the * raster renderer shows the motion) and resumes on the paused pose. * * The whole object is structural in ``: changing ANY field * rebuilds the viewer (and reloads the model). */ export declare interface PathTracingOptions { /** Builds the tracer at viewer construction. */ enabled?: boolean; /** * Samples to accumulate before the frame counts as converged * (`pathtracing:complete`, and what a path-traced `captureStill()` awaits). * More samples = cleaner image, linearly more GPU time. */ maxSamples?: number; /** Light-path depth: how many surface bounces each ray may take. */ bounces?: number; /** Extra ray depth through transmissive (glass-like) materials. */ transmissiveBounces?: number; /** Accumulation resolution as a fraction of canvas size (0.5 = quarter pixels, 4× faster). */ renderScale?: number; /** Resolution fraction of the fast preview shown while the camera moves. */ lowResScale?: number; /** Drop to the low-res preview during interaction instead of stalling. */ dynamicLowRes?: boolean; } export declare interface RendererOptions { antialias?: boolean; alpha?: boolean; premultipliedAlpha?: boolean; /** * Note: the viewer forces this ON regardless — a completed path-traced * frame must survive on the canvas for captureStill to read back. */ preserveDrawingBuffer?: boolean; powerPreference?: 'high-performance' | 'low-power' | 'default'; shadowMapEnabled?: boolean; pixelRatio?: number; /** A `THREE.ShadowMapType` constant (e.g. `THREE.PCFShadowMap` === 1). */ shadowMapType?: number; /** A `THREE.ToneMapping` constant (e.g. `THREE.ACESFilmicToneMapping` === 6). */ toneMapping?: number; toneMappingExposure?: number; /** A `THREE.ColorSpace` value (e.g. `'srgb'`, `'srgb-linear'`). */ outputColorSpace?: string; /** Opt-in soft glow on bright highlights (UnrealBloom). */ bloom?: boolean; /** Opt-in edge darkening that focuses attention on the subject. */ vignette?: boolean; /** Opt-in subtle photographic film grain. */ filmGrain?: boolean; /** * Opt-in contrast + saturation grade applied after tone mapping — adds punch * (a more "hero" read) while keeping the tone-mapping operator's hue. Pass * `true` for a balanced default, or an object to tune each amount (roughly * `-1..1`, `0` = no change). Off by default. */ colorGrade?: boolean | { contrast?: number; saturation?: number; }; } /** * Rendering behavior options */ export declare interface RenderingOptions { /** * Enable idle detection to stop rendering when inactive * @default true for static scenes, false for non-static scenes */ enableIdleDetection?: boolean; /** * Time in milliseconds before entering idle state * @default 1000 */ idleDelay?: number; /** * Target frames per second * @default 60 */ targetFPS?: number; /** * Enable frame rate limiting * @default true */ enableFrameRateLimiting?: boolean; } /** The partial options for a preset, or an empty object when none is set. */ export declare function resolvePreset(preset?: ViewerPreset): Partial; /** The partial options for a scene, or an empty object when none is set. */ export declare function resolveScene(scene?: ViewerScene): Partial; /** * Click-picking and hotspot-occlusion raycast options. */ export declare interface SelectionOptions { /** * Build a BVH (bounding volume hierarchy) for each loaded model, making * raycasts logarithmic instead of linear — noticeable on high-poly models. * Costs one synchronous build pass at load time (or on the first click for * models passed as raw objects) and ~25% extra geometry memory. The build * sorts each geometry's index in place (triangle order changes; rendering * is unaffected) and adds an index to non-indexed geometry. Disable on * memory-constrained targets or when the index order matters. Default on. */ bvh?: boolean; } /** * Public entry component for the viewer. Thin forwardRef pass-through to the * clean-architecture SimpleViewer implementation. */ export declare const SimpleViewer: default_2.ForwardRefExoticComponent>; /** * Imperative handle exposed via `ref` on the `SimpleViewer` component. Lives in a * dedicated type module (not the component file) so cross-cutting modules such as * `events/ViewerEvents` can reference it without depending on a React component. */ export declare interface SimpleViewerHandle { scene: THREE.Scene | null; camera: THREE.Camera | null; renderer: THREE.WebGLRenderer | null; controls: ControlsInstance | null; events: TypedEventEmitter; loadModel: (source: string | THREE.Object3D) => Promise; /** * Capture a PNG still of the current scene (data URL). Pass `width`/`height` * for a high-resolution raster capture; in path-traced mode omit them — the * still is taken at canvas resolution once the accumulation completes. */ captureStill: (options?: CaptureStillOptions) => Promise; /** * Record the live canvas for a few seconds (default 3) and resolve with the * encoded clip — WebM in Chromium/Firefox, MP4 in Safari. Motion (turntable, * animations, user orbiting) is captured as it happens. */ captureVideo: (options?: CaptureVideoOptions) => Promise; /** Clip names of the loaded model, in file order (empty when none). */ getAnimationNames: () => string[]; /** KHR_materials_variants names of the loaded model (empty when none). */ getVariantNames: () => string[]; /** * Switch the loaded model to a material variant; `null` restores the * authored materials. Applies live (no reload). Throws `INVALID_PARAMETER` * on a variant name the model does not carry. */ setVariant: (variant: string | null) => void; /** * Plays one clip by name, or ALL clips when no name is given (looped). * Throws `INVALID_PARAMETER` on a clip name the model does not carry. */ playAnimations: (clipName?: string) => void; /** Freezes playback on the current pose; playAnimations() resumes. */ pauseAnimations: () => void; /** * Replace the environment map (reflections + background) at runtime with the * equirectangular HDRI/LDR image at `url`. Cached by URL, so re-applying is cheap. * * Like the capture APIs, the environment APIs throw (async ones reject) with * INVALID_STATE when the viewer was disposed — including a dispose that lands * while the map is still loading. Fire-and-forget callers should attach a * `.catch` if unmount races are possible (e.g. React StrictMode in dev). */ setEnvironmentMap: (url: string) => Promise; /** Restore the built-in studio environment and clean gradient background. */ resetEnvironment: () => void; /** * Paint an uploaded image (URL, File, or HTMLImageElement) as the scene backdrop * without changing the environment lighting. Clear it with setBackgroundColor. */ setBackgroundImage: (source: string | File | HTMLImageElement) => Promise; /** Set a solid background color (also clears a background image). */ setBackgroundColor: (color: string | number) => void; dispose: () => void; } export declare interface SimpleViewerOptions { /** * A one-word visual preset (`studio`, `product`, `neutral`, `dark`, `outdoor`) * that sets a cohesive lighting/environment/tone look. Any other option you * pass overrides the preset's values. */ preset?: ViewerPreset; /** * A one-word scene (`studio_dome`, `studio_soft`) that selects the physical * set — floor, backdrop and how the studio environment is built. The * structural counterpart of `preset`: switching a scene rebuilds the viewer. * Any other option you pass overrides the scene's values. */ scene?: ViewerScene; /** * KHR_materials_variants variant to show (e.g. a product colorway baked * into the GLB). Applies LIVE — switching never rebuilds the viewer or * reloads the model. `null` shows the authored default materials; leaving * the option out is "uncontrolled" (an imperative `handle.setVariant()` * pick survives other option changes); an unknown name warns and keeps * the defaults. Enumerate the model's variants via * `handle.getVariantNames()`. */ variant?: string | null; /** * Length unit the model geometry is authored in (default `'meters'`). * Non-meter models are rescaled on load — without touching the model's own * transform — to the viewer's 1-unit-=-1-meter convention that the * real-scale floor, contact shadows and framing rely on. */ units?: ModelUnits; /** * Drop the loaded model onto the floor at y=0 on load (default `true`). Set * `false` for a model that carries its own ground and must keep its authored * Y — otherwise softbox snaps the model's lowest point (e.g. the bottom of an * embedded ground slab) to the floor, shifting everything above it upward. */ floorAlignment?: boolean; backgroundColor?: string | number; /** * Optional darker edge colour for a RADIAL backdrop vignette. When set, * `backgroundColor` is painted as the centre (behind the subject) and this as * the corners/bottom, floating the model in a soft cove instead of a flat * fill. Omit for a flat background. Runtime-tunable (applies on a live preset * switch without a rebuild), same as `backgroundColor`. */ backgroundColorEdge?: string | number; staticScene?: boolean; /** GLTF animation playback (autoplay, speed). */ animations?: AnimationOptions; camera?: CameraOptions; controls?: ControlsOptions; environment?: EnvironmentOptions; helpers?: HelperOptions; lighting?: LightingOptions; pathTracing?: PathTracingOptions; renderer?: RendererOptions; rendering?: RenderingOptions; /** Called when a model finishes loading (each load, including replacements). */ onLoad?: () => void; /** * Download progress for URL-loaded models as a 0–1 fraction. Only called * when the server reports a total size (Content-Length). */ onProgress?: (progress: number) => void; /** * Called on viewer construction/initialization failures (e.g. WebGL * unavailable) and on model load errors. The built-in overlay shows an * error state either way; use this to render your own affordance or report. */ onError?: (error: Error) => void; /** * @deprecated Never functional since the 3.x architecture rewrite — the * render loop is fully managed (turntable/animations/path tracing drive it). * Ignored; will be removed in 5.0. */ animationLoop?: ((time: number) => void) | null; /** * Replace the canvas with an `` snapshot when a path-traced * accumulation completes; the first click restores the live viewer by * reloading the model (default `false`). A legacy from one-shot path * tracing — the interactive tracer keeps the converged frame on the live * canvas and re-accumulates on camera moves, so most consumers should * leave this off. */ replaceWithScreenshotOnComplete?: boolean; /** * When to boot the WebGL engine and fetch the model (default `'eager'`). * `'lazy'` defers everything until the viewer first approaches the * viewport (like ``) — on pages with many viewers * only the visible ones pay for a GL context and a model download. Once * booted a viewer stays booted; where IntersectionObserver is unavailable * the option gracefully degrades to eager. */ loading?: 'eager' | 'lazy'; /** * Built-in loading overlay shown while a model loads. `true`/omitted shows the * default spinner; `false` hides it (render your own via the loading events); * an object customizes it. UI-only — changing it never rebuilds the viewer. */ loadingIndicator?: boolean | LoadingIndicatorOptions; /** * Compression decoders for the glTF/GLB loader (DRACO, KTX2/Basis, Meshopt). * All enabled by default so compressed assets load with no setup; pass this to * disable a decoder or self-host the DRACO/KTX2 WebAssembly files offline. */ loaders?: LoaderOptions; /** * Built-in UI chrome over the canvas (e.g. `ui: { presets: true }` for the * live preset picker). All opt-in; UI-only — never rebuilds the viewer. */ ui?: UIOptions; /** * Poster image (URL) shown over the canvas until the model's first painted * frame. Composes with `loading: 'lazy'`: the poster is the instant, * WebGL-free first paint while the real viewer boots and the GLB * downloads. Generate one with `handle.captureStill()`. Stays up as the * backdrop if the load errs (the error overlay renders above it). * UI-only — changing it never rebuilds the viewer. */ poster?: string; /** * AR handoff button: opens the model in the platform's native AR viewer — * AR Quick Look on iOS (needs `iosSrc`, a USDZ counterpart), Scene Viewer * on Android (reuses the model's own URL). `true` enables with defaults. * The button renders only on devices that can actually hand off, so it is * safe to set unconditionally. UI-only — never rebuilds the viewer. */ ar?: boolean | AROptions; /** * Click-picking / hotspot-occlusion raycast tuning (e.g. `selection: { bvh: * false }` to skip the load-time BVH build on memory-constrained targets). */ selection?: SelectionOptions; } export declare interface SimpleViewerProps { /** * A URL to a glb/gltf file, or a Three.js object. The viewer takes * OWNERSHIP of objects you pass: their geometries, materials and textures * are disposed when the object is replaced or the viewer unmounts. Pass a * `.clone()` if you need to keep using the original elsewhere. */ object: THREE.Object3D | null | string; options?: SimpleViewerOptions; /** * Shorthand for `options.preset` — a one-word look * (`studio` / `product` / `neutral` / `dark` / `outdoor`). * `options.preset` takes precedence if both are set. */ preset?: ViewerPreset; /** * Shorthand for `options.pathTracing.enabled = true` — photoreal progressive * path tracing (a construction-time render mode). Composes with a partial * `options.pathTracing` (tuning fields are kept); an explicit * `options.pathTracing.enabled` wins. Pair with `handle.captureStill()` for * a photoreal still once the accumulation completes. */ pathTraced?: boolean; /** * Shorthand for `options.controls.autoRotate = true` — a showcase turntable * that slowly orbits the camera around the model. Toggling it never rebuilds * the viewer (applied live), and rotation pauses automatically while the * user is dragging. Speed is tuned via `options.controls.autoRotateSpeed` * (2 ≈ one orbit per 30s). An explicit `options.controls.autoRotate` wins. */ turntable?: boolean; /** * Shorthand for `options.animations.autoplay = true` — plays ALL of the * model's animation clips, looped, as soon as it loads. Toggling is live * (pause/resume without a rebuild). Pick a single clip or tune the speed * via `options.animations`; an explicit `options.animations.autoplay` wins. */ animations?: boolean; /** * Overlay children rendered inside the viewer container (over the canvas), * e.g. `` annotations. */ children?: React_2.ReactNode; } /** * How the built-in procedural studio environment is graded when it is built. * `crisp` (the default) darkens the surround and boosts the soft-box panels so * glossy materials show distinct highlights; `soft` uses the studio room * as-built for an even, low-contrast wraparound light. Structural — the * environment is baked once at construction, so changing it rebuilds the * viewer. Scenes (`SimpleViewerOptions.scene`) drive this. */ export declare type StudioLook = 'crisp' | 'soft'; export declare class ThreeViewerError extends Error { readonly code: ErrorCode; readonly context?: ErrorContext | undefined; readonly timestamp: Date; constructor(message: string, code: ErrorCode, context?: ErrorContext | undefined); static fromError(error: unknown, code: ErrorCode, context?: ErrorContext): ThreeViewerError; } export declare class TypedEventEmitter { private listeners; on(event: K, listener: (data: T[K]) => void): () => void; emit(event: K, data: T[K]): void; once(event: K, listener: (data: T[K]) => void): () => void; removeAllListeners(event?: keyof T): void; listenerCount(event: keyof T): number; /** * Alias for removing a listener (compatible with Node.js EventEmitter) */ off(event: K, listener: (data: T[K]) => void): void; /** * Alias for on (compatible with Node.js EventEmitter) */ removeListener(event: K, listener: (data: T[K]) => void): void; } /** * Built-in UI chrome rendered over the canvas. Everything here is opt-in and * UI-only — toggling it never rebuilds the viewer or reloads the model. */ export declare interface UIOptions { /** * Show the built-in preset picker: a row of chips over the canvas that * switches the visual preset live. Off by default. Turning the picker off * also clears any preset picked through it — your own `preset` takes over. */ presets?: boolean; /** * Called when the user picks a preset via the built-in picker, e.g. to * persist the choice. A later change to your own `preset` prop/option * overrides the picked one; echoing a reported pick back into `preset` * (even asynchronously) is safe and never reverts a newer pick. */ onPresetChange?: (preset: ViewerPreset) => void; } /** A plain, engine-agnostic 3D point. */ declare interface Vec3Like { x: number; y: number; z: number; } /** * Visual presets: cohesive deltas layered over the defaults (deep-merged) so a * model looks intentional on first paint. Each preset only sets **runtime** look * fields — background color (plus an optional radial-vignette edge colour), * tone-mapping exposure and environment intensity — so switching presets is * applied live (no viewer rebuild, no model reload) and everything else (camera * auto-framing, lighting rig, controls, grid) is inherited from the defaults. * Explicit user options always win. */ export declare const VIEWER_PRESETS: Record>; export declare const VIEWER_SCENES: Record>; /** * The public, Three.js-typed view of the viewer event contract — the shape * consumers see on the viewer handle's `events` emitter. Shares its single * source of truth with the core map via the generic {@link GenericViewerEventMap}. */ export declare type ViewerEventMap = ViewerEventMap_2; /** * The viewer's event contract, generic over the layer-specific representations * of a 3D object, camera, controls, and viewer handle. The engine-agnostic core * instantiates it with its interfaces (`IObject3D`/`ICamera`/…); the public * surface instantiates it with the concrete Three.js types. Keeping a single * generic definition is what stops the two instantiations from drifting apart. */ declare interface ViewerEventMap_2 { 'initialized': { viewer: THandle; }; 'disposed': { viewer: THandle; }; 'model:loading': { url: string; }; /** Download progress for URL loads; emitted only when the server reports a total size. */ 'model:progress': { url: string; loaded: number; total: number; }; 'model:loaded': { model: TObject; loadTime: number; }; 'model:error': { error: ThreeViewerError; url?: string; }; 'render:start': { frame: number; }; 'render:complete': { frame: number; renderTime: number; samples?: number; }; 'pathtracing:complete': { samples: number; totalTime: number; }; 'screenshot:captured': { dataUrl: string; }; 'controls:change': { type?: string; camera?: TCamera; controls?: TControls; }; /** A click (not a drag) hit the loaded model; `point` is the world-space hit. */ 'object:selected': { object: TObject; point: Vec3Like; }; 'error': { error: ThreeViewerError; }; } /** * A one-word visual preset that sets the background, tone-mapping exposure and * environment intensity as a cohesive "look", so a model looks intentional on * first paint with zero manual tuning. Set it on `SimpleViewerOptions.preset` * (or the `preset` prop). Presets apply live, so switching one never rebuilds * the viewer or reloads the model. Any explicit option you pass overrides it. * * - `studio` — clean, neutral light-grey backdrop; the balanced default look. * - `product` — bright, high-key white backdrop for e-commerce hero shots. * - `neutral` — flat, even, low-drama lighting for accurate inspection. * - `dark` — dramatic dark backdrop for portfolios and glossy materials. * - `outdoor` — brighter, daylight-leaning sky tint. * * Path-traced output is a construction-time render mode (`pathTracing.enabled`), * not a live-switchable preset. */ export declare type ViewerPreset = 'studio' | 'product' | 'neutral' | 'dark' | 'outdoor'; /** * A one-word scene that selects the physical SET the model stands in — the * floor, the backdrop geometry and how the built-in studio environment is * built. Set it on `SimpleViewerOptions.scene`. The scene is the structural * counterpart of the tonal `preset` axis: presets grade the picture live, * scenes swap the set (switching one rebuilds the viewer). Any explicit * option you pass overrides the scene's values. * * - `studio_dome` — the default set: invisible shadow-catcher floor, baked * soft contact shadow, crisp contrast-pushed studio environment (distinct * highlights on glossy materials) and the path-traced infinity dome. * - `studio_soft` — the same set lit softly: the studio environment is used * as-built, without the contrast push, plus a rebalanced rig (the key steps * back, the rim edge nearly goes, the fill opens the shadows) for an even, * low-drama read that flatters matte materials. * - `outdoor_concrete` — open air: a real daylight HDRI lights the model and * paints the sky, standing on a large matte concrete ground disc. The HDRI * is fetched from a CDN by default (the one network request this scene * makes); pass your own `environment.url` to override or self-host it. */ export declare type ViewerScene = 'studio_dome' | 'studio_soft' | 'outdoor_concrete'; export { }