React Integration

// @cadview/react โ€” React 18/19 component and hook

Installation

pnpm add @cadview/core @cadview/react

CadViewer Component

The simplest way to embed a CAD viewer:

import { CadViewer } from '@cadview/react';

function App() {
	const [file, setFile] = useState<File | null>(null);

	return (
		<CadViewer
			file={file}
			theme="dark"
			tool="pan"
			style={{ width: '100%', height: '600px' }}
			onSelect={(e) => console.log(e.entity)}
			onMeasure={(e) => console.log(e.distance)}
		/>
	);
}

Props

PropTypeDefault
fileFile \| ArrayBuffer \| string \| nullโ€”
themeTheme'dark'
toolTool'pan'
debugboolean \| DebugOptionsfalse
workerbooleanfalse
classNamestringโ€”
styleCSSPropertiesโ€”
optionsCadViewerOptions{}
formatConvertersFormatConverter[][]
onSelect(event: SelectEvent) => voidโ€”
onMeasure(event: MeasureEvent) => voidโ€”
onViewChange(transform: ViewTransform) => voidโ€”
onLayersLoaded(layers: DxfLayer[]) => voidโ€”

Ref API

Use a ref to access imperative methods:

import { useRef } from 'react';
import { CadViewer, type CadViewerRef } from '@cadview/react';

function App() {
	const viewerRef = useRef<CadViewerRef>(null);

	return (
		<>
			<CadViewer ref={viewerRef} file={file} />
			<button onClick={() => viewerRef.current?.fitToView()}>Fit to View</button>
		</>
	);
}

CadViewerRef Methods

MethodReturnsDescription
getViewer()CadViewer \| nullAccess the core viewer instance
fitToView()voidFit camera to drawing extents
getLayers()DxfLayer[]Get all layers
setLayerVisible(name, visible)voidToggle layer visibility

useCadViewer Hook

For more control, use the hook directly with your own canvas:

import { useRef } from 'react';
import { useCadViewer } from '@cadview/react';

function CustomViewer() {
	const canvasRef = useRef<HTMLCanvasElement>(null);
	const {
		viewer,
		layers,
		isLoaded,
		error,
		loadFile,
		fitToView,
		setTheme,
		setTool,
		setLayerVisible
	} = useCadViewer(canvasRef, { theme: 'dark' });

	return (
		<div>
			<canvas ref={canvasRef} style={{ width: '100%', height: '500px' }} />
			{error && <p>Error: {error.message}</p>}
			{isLoaded && (
				<div>
					<button onClick={fitToView}>Fit</button>
					<p>{layers.length} layers loaded</p>
				</div>
			)}
		</div>
	);
}

Hook Return Values

PropertyTypeDescription
viewerCadViewer \| nullCore viewer instance
layersDxfLayer[]Current layers (reactive)
isLoadedbooleanWhether a document is loaded
errorError \| nullLast loading error
loadFile(file: File) => Promise<void>Load a File object
loadBuffer(buffer: ArrayBuffer) => Promise<void>Load an ArrayBuffer
loadString(dxf: string) => voidLoad a DXF string
fitToView() => voidFit camera to drawing
setLayerVisible(name: string, visible: boolean) => voidToggle layer
setTheme(theme: Theme) => voidChange theme
setTool(tool: Tool) => voidChange active tool

Full Example

A complete example with file input, tool switching, and layer management:

import { useState, useRef } from 'react';
import { CadViewer, type CadViewerRef, type DxfLayer } from '@cadview/react';
import { dwgConverter } from '@cadview/dwg';

export default function CadApp() {
	const ref = useRef<CadViewerRef>(null);
	const [file, setFile] = useState<File | null>(null);
	const [tool, setTool] = useState<'pan' | 'select' | 'measure'>('pan');
	const [layers, setLayers] = useState<DxfLayer[]>([]);

	return (
		<div>
			<header>
				<input
					type="file"
					accept=".dxf,.dwg"
					onChange={(e) => setFile(e.target.files?.[0] ?? null)}
				/>
				<select value={tool} onChange={(e) => setTool(e.target.value as any)}>
					<option value="pan">Pan</option>
					<option value="select">Select</option>
					<option value="measure">Measure</option>
				</select>
				<button onClick={() => ref.current?.fitToView()}>Fit</button>
			</header>

			<CadViewer
				ref={ref}
				file={file}
				tool={tool}
				theme="dark"
				formatConverters={[dwgConverter]}
				onLayersLoaded={setLayers}
				onSelect={(e) => console.log('Selected:', e.entity.type)}
				onMeasure={(e) => console.log('Distance:', e.distance)}
				style={{ width: '100%', height: '80vh' }}
			/>

			<aside>
				<h3>Layers</h3>
				{layers.map((layer) => (
					<label key={layer.name}>
						<input
							type="checkbox"
							checked={!layer.isOff}
							onChange={(e) => ref.current?.setLayerVisible(layer.name, e.target.checked)}
						/>
						{layer.name}
					</label>
				))}
			</aside>
		</div>
	);
}