React component wrappers for @ts3d-hoops/web-viewer-components. This package provides React-friendly components that wrap the underlying web components, giving you proper TypeScript support, React event handling, and seamless integration with your React-b
React component wrappers for @ts3d-hoops/web-viewer-components. This package provides React-friendly components that wrap the underlying web components, giving you proper TypeScript support, React event handling, and seamless integration with your React-based HOOPS Web Viewer applications.
- React 18+ compatible
- Full TypeScript support with proper event typing
- Complete viewer UI components (trees, toolbars, panels)
- Built on @lit/react for optimal performance
- Service architecture integration
``bash`
npm install @ts3d-hoops/web-viewer-components-react react
Note: React 18+ is required as a peer dependency.
`tsx
import React from 'react';
import {
WebViewerComponent,
HoopsModelTree,
HoopsHomeButton,
HoopsCameraButton,
HoopsDrawmodeButton,
} from '@ts3d-hoops/web-viewer-components-react';
function ViewerApp() {
const handleModelLoaded = (e: CustomEvent) => {
console.log('Model loaded:', e.detail);
};
const handleModelTreeClick = (e: CustomEvent) => {
console.log('Model tree node clicked:', e.detail);
};
return (
enginePath="/engine"
style={{ width: '100%', height: '600px' }}
onHwvSceneReady={handleModelLoaded}
>
{/ Toolbar /}
{/ Sidebar /}
style={{ width: '300px' }}
onModelTreeNodeClick={handleModelTreeClick}
/>
);
}
`
- WebViewerComponent — Main HOOPS Web Viewer with full event support
- HoopsWebviewerContextManager — Context management for component communication
- HoopsServiceRegistry — Service registry for viewer operations
- HoopsHomeButton — Home/fit view button
- HoopsCameraButton — Camera controls and projections
- HoopsDrawmodeButton — Rendering mode toggle (shaded, wireframe, etc.)
- HoopsCameraOperatorButton — Camera operation controls
- HoopsExplodeButton — Model explode controls
- HoopsSnapshotButton — Screenshot capture
- HoopsRedlinesButton — Markup and redlining tools
- HoopsToolsButton — Additional viewer tools
- HoopsModelTreeButton — Model tree panel toggle
- HoopsLayersButton — Layer management toggle
- HoopsViewsButton — View management toggle
- HoopsTypesButton — Object type filtering toggle
- HoopsPropertiesButton — Properties panel toggle
- HoopsSettingsButton — Settings panel toggle
- HoopsCadConfigurationButton — CAD configuration controls
- HoopsModelTree — Hierarchical model structure tree
- HoopsLayerTree — CAD layer management tree
- HoopsViewTree — Saved views and configurations tree
- HoopsTypesTree — Object type filtering tree
- HoopsToolsPanel — Tool collection panel
- HoopsSettingsPanel — Viewer settings and preferences
- HoopsCadConfigurationList — CAD configuration selection
- HoopsContextMenu — Right-click context menu
- HoopsInfoButton — Information display button
- HoopsIFCRelationship — IFC relationship components
`tsx
import React, { useState } from 'react';
import {
WebViewerComponent,
HoopsModelTree,
HoopsLayerTree,
HoopsSettingsPanel,
HoopsHomeButton,
HoopsCameraButton,
HoopsDrawmodeButton,
HoopsSnapshotButton,
} from '@ts3d-hoops/web-viewer-components-react';
function CompleteViewer() {
const [selectedNodes, setSelectedNodes] = useState
return (
enginePath="/engine"
style={{ width: '100vw', height: '100vh' }}
onHwvSceneReady={() => console.log('Scene ready')}
onHwvSelectionArray={(e) => setSelectedNodes(e.detail)}
>
{/ Toolbar /}
{/ Left sidebar with trees /}
{/ Right panel /}
);
}
`
`tsx
import React from 'react';
import { WebViewerComponent, HoopsModelTree } from '@ts3d-hoops/web-viewer-components-react';
function EventExample() {
// Viewer events
const handleSceneReady = () => {
console.log('Viewer is ready!');
};
const handleSelectionChange = (e: CustomEvent) => {
console.log('Selection changed:', e.detail);
};
const handleModelLoadBegin = () => {
console.log('Model loading started...');
};
// Tree events
const handleModelTreeClick = (e: CustomEvent) => {
const { nodeId, nodeName } = e.detail;
console.log(Clicked node: ${nodeName} (${nodeId}));
};
const handleVisibilityChange = (e: CustomEvent) => {
const { nodeId, visible } = e.detail;
console.log(Node ${nodeId} visibility: ${visible});
};
return (
onHwvSceneReady={handleSceneReady}
onHwvSelectionArray={handleSelectionChange}
onHwvModelLoadBegin={handleModelLoadBegin}
style={{ width: '100%', height: '500px' }}
>
onModelTreeNodeClick={handleModelTreeClick}
onModelTreeNodeVisibilityChange={handleVisibilityChange}
style={{ width: '300px' }}
/>
);
}
`
`tsx
import React, { useEffect, useState } from 'react';
import { WebViewerComponent } from '@ts3d-hoops/web-viewer-components-react';
import {
CameraService,
SelectionService,
serviceRegistry,
} from '@ts3d-hoops/web-viewer-components/services';
function ServiceIntegration() {
const [cameraService, setCameraService] = useState
const [selectionService, setSelectionService] = useState
useEffect(() => {
// Get services after viewer is ready
const camera = serviceRegistry.get(CameraService);
const selection = serviceRegistry.get(SelectionService);
setCameraService(camera);
setSelectionService(selection);
}, []);
const fitView = async () => {
if (cameraService) {
await cameraService.fitView();
}
};
const clearSelection = async () => {
if (selectionService) {
await selectionService.clear();
}
};
return (
style={{ width: '100%', height: '500px' }}
/>
$3
`tsx
import React, { useEffect, useState } from 'react';
import { WebViewerComponent } from '@ts3d-hoops/web-viewer-components-react';// Custom hook for viewer state
function useViewerState() {
const [isReady, setIsReady] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [selection, setSelection] = useState([]);
const handleSceneReady = () => setIsReady(true);
const handleLoadBegin = () => setIsLoading(true);
const handleLoadEnd = () => setIsLoading(false);
const handleSelection = (e: CustomEvent) => setSelection(e.detail);
return {
isReady,
isLoading,
selection,
events: {
onHwvSceneReady: handleSceneReady,
onHwvModelLoadBegin: handleLoadBegin,
onHwvFirstModelLoaded: handleLoadEnd,
onHwvSelectionArray: handleSelection,
},
};
}
function ViewerWithHook() {
const { isReady, isLoading, selection, events } = useViewerState();
return (
Status: {isLoading ? 'Loading...' : isReady ? 'Ready' : 'Initializing'}
{selection.length > 0 && | Selected: {selection.length} items}
endpointUri="/models/sample.scs"
style={{ width: '100%', height: '500px' }}
{...events}
/>
);
}
`Event reference
The WebViewerComponent supports all HOOPS Web Viewer events as React props:
$3
-
onHwvReady — Viewer initialization complete
- onHwvSceneReady — Scene and model ready for interaction
- onHwvFirstModelLoaded — First model loaded successfully$3
-
onHwvModelLoadBegin — Model loading started
- onHwvModelStructureReady — Model structure parsed
- onHwvModelSwitched — Model switched in multi-model scenarios$3
-
onHwvSelectionArray — Selection changed
- onHwvBeginInteraction — User interaction started
- onHwvEndInteraction — User interaction ended
- onHwvCamera — Camera changed
- onHwvContextMenu — Right-click context menu$3
-
onHwvViewCreated — View created
- onHwvViewLoaded — View loaded
- onHwvViewOrientation — View orientation changed$3
-
onHwvMeasurementCreated — Measurement created
- onHwvMeasurementDeleted — Measurement deleted
- onHwvRedlineCreated — Redline markup created$3
-
onHwvModelLoadFailure — Model failed to load
- onHwvTimeout — Operation timeout
- onHwvWebGlContextLost — WebGL context lostTypeScript support
All components are fully typed for TypeScript with proper event interfaces:
`tsx
import React from 'react';
import type { CustomEvent } from 'react';
import { WebViewerComponent, HoopsModelTree } from '@ts3d-hoops/web-viewer-components-react';interface ViewerProps {
modelUrl: string;
onReady?: () => void;
}
function TypedViewer({ modelUrl, onReady }: ViewerProps) {
const handleModelTreeClick = (e: CustomEvent) => {
// e.detail is properly typed
const { nodeId, nodeName } = e.detail;
console.log(
Clicked: ${nodeName});
}; return (
endpointUri={modelUrl}
onHwvSceneReady={onReady}
style={{ width: '100%', height: '500px' }}
>
);
}
`Comparison with vanilla web components
| Feature | @ts3d-hoops/web-viewer-components | @ts3d-hoops/web-viewer-components-react |
| ----------------- | --------------------------------- | --------------------------------------- |
| React integration | Manual JSX declarations needed | Native React components |
| TypeScript | Generic web component types | Full React component types |
| Event handling | DOM events only | React SyntheticEvents + Custom Events |
| Props | Attributes only | React props + attributes |
| Tree shaking | ✅ | ✅ |
| Bundle size | Smaller | Slightly larger (+@lit/react) |
Performance
- Built on @lit/react for optimal React integration
- Components are lazy-loaded and tree-shakable
- No unnecessary re-renders thanks to Lit's efficient change detection
- Minimal overhead over vanilla web components
Browser support
- React 18+
- Modern browsers with web component support
- WebGL-capable devices
- ES2020+ environments
- Works with all major bundlers (Vite, Webpack, Create React App)
Related packages
-
@ts3d-hoops/web-viewer-components — The underlying web component library
- @ts3d-hoops/web-viewer — Core HOOPS Web Viewer library
- @ts3d-hoops/ui-kit-react — React wrappers for base UI components
- @ts3d-hoops/streamcache — Low-level streaming clientMigration from @ts3d-hoops/web-viewer-components
If you're using @ts3d-hoops/web-viewer-components web components directly in React:
Before:
`tsx
// Manual JSX declarations needed
declare global {
namespace JSX {
interface IntrinsicElements {
'hoops-web-viewer': any;
'hoops-model-tree': any;
}
}
}
;
`After:
`tsx
import { WebViewerComponent, HoopsModelTree } from '@ts3d-hoops/web-viewer-components-react';
;
``Commercial license. For evaluation or production licensing, contact Tech Soft 3D.