@cadview/react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +65 -0
- package/dist/index.cjs +159 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +39 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +156 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Wisnu Wicaksono
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# @cadview/react
|
|
2
|
+
|
|
3
|
+
React wrapper for `@cadview/core` — a CAD/DXF file viewer.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @cadview/core @cadview/react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { CadViewer } from '@cadview/react';
|
|
15
|
+
|
|
16
|
+
function App() {
|
|
17
|
+
const [file, setFile] = useState<File | null>(null);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div style={{ width: '100%', height: '100vh' }}>
|
|
21
|
+
<input
|
|
22
|
+
type="file"
|
|
23
|
+
accept=".dxf"
|
|
24
|
+
onChange={(e) => setFile(e.target.files?.[0] ?? null)}
|
|
25
|
+
/>
|
|
26
|
+
<CadViewer
|
|
27
|
+
file={file}
|
|
28
|
+
theme="dark"
|
|
29
|
+
tool="pan"
|
|
30
|
+
onSelect={(e) => console.log('Selected:', e.entity.type)}
|
|
31
|
+
onMeasure={(e) => console.log('Distance:', e.distance)}
|
|
32
|
+
/>
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Props
|
|
39
|
+
|
|
40
|
+
| Prop | Type | Default | Description |
|
|
41
|
+
|------|------|---------|-------------|
|
|
42
|
+
| `file` | `File \| null` | — | DXF file to load |
|
|
43
|
+
| `theme` | `'dark' \| 'light'` | `'dark'` | Color theme |
|
|
44
|
+
| `tool` | `'pan' \| 'select' \| 'measure'` | `'pan'` | Active tool |
|
|
45
|
+
| `options` | `CadViewerOptions` | — | Additional viewer options |
|
|
46
|
+
| `onSelect` | `(e: SelectEvent) => void` | — | Selection callback |
|
|
47
|
+
| `onMeasure` | `(e: MeasureEvent) => void` | — | Measurement callback |
|
|
48
|
+
| `onViewChange` | `(vt: ViewTransform) => void` | — | View change callback |
|
|
49
|
+
| `onLayersLoaded` | `(layers: DxfLayer[]) => void` | — | Layers loaded callback |
|
|
50
|
+
|
|
51
|
+
## Hook
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { useCadViewer } from '@cadview/react';
|
|
55
|
+
|
|
56
|
+
function App() {
|
|
57
|
+
const { ref, viewer } = useCadViewer({ theme: 'dark' });
|
|
58
|
+
|
|
59
|
+
return <canvas ref={ref} style={{ width: '100%', height: '100%' }} />;
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## License
|
|
64
|
+
|
|
65
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var core = require('@cadview/core');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
// src/CadViewer.tsx
|
|
8
|
+
var CadViewer = react.forwardRef(
|
|
9
|
+
function CadViewer2(props, ref) {
|
|
10
|
+
const {
|
|
11
|
+
file,
|
|
12
|
+
theme = "dark",
|
|
13
|
+
tool = "pan",
|
|
14
|
+
className,
|
|
15
|
+
style,
|
|
16
|
+
options,
|
|
17
|
+
onSelect,
|
|
18
|
+
onMeasure,
|
|
19
|
+
onViewChange,
|
|
20
|
+
onLayersLoaded
|
|
21
|
+
} = props;
|
|
22
|
+
const canvasRef = react.useRef(null);
|
|
23
|
+
const viewerRef = react.useRef(null);
|
|
24
|
+
react.useEffect(() => {
|
|
25
|
+
if (!canvasRef.current) return;
|
|
26
|
+
const viewer = new core.CadViewer(canvasRef.current, {
|
|
27
|
+
theme,
|
|
28
|
+
initialTool: tool,
|
|
29
|
+
...options
|
|
30
|
+
});
|
|
31
|
+
viewerRef.current = viewer;
|
|
32
|
+
return () => {
|
|
33
|
+
viewer.destroy();
|
|
34
|
+
viewerRef.current = null;
|
|
35
|
+
};
|
|
36
|
+
}, []);
|
|
37
|
+
react.useEffect(() => {
|
|
38
|
+
viewerRef.current?.setTheme(theme);
|
|
39
|
+
}, [theme]);
|
|
40
|
+
react.useEffect(() => {
|
|
41
|
+
viewerRef.current?.setTool(tool);
|
|
42
|
+
}, [tool]);
|
|
43
|
+
react.useEffect(() => {
|
|
44
|
+
const viewer = viewerRef.current;
|
|
45
|
+
if (!viewer || !file) return;
|
|
46
|
+
if (file instanceof File) {
|
|
47
|
+
viewer.loadFile(file).then(
|
|
48
|
+
() => onLayersLoaded?.(viewer.getLayers()),
|
|
49
|
+
(err) => console.error("CadViewer: failed to load file", err)
|
|
50
|
+
);
|
|
51
|
+
} else if (file instanceof ArrayBuffer) {
|
|
52
|
+
viewer.loadArrayBuffer(file);
|
|
53
|
+
onLayersLoaded?.(viewer.getLayers());
|
|
54
|
+
} else if (typeof file === "string") {
|
|
55
|
+
viewer.loadString(file);
|
|
56
|
+
onLayersLoaded?.(viewer.getLayers());
|
|
57
|
+
}
|
|
58
|
+
}, [file]);
|
|
59
|
+
react.useEffect(() => {
|
|
60
|
+
const viewer = viewerRef.current;
|
|
61
|
+
if (!viewer) return;
|
|
62
|
+
const handlers = [];
|
|
63
|
+
if (onSelect) {
|
|
64
|
+
viewer.on("select", onSelect);
|
|
65
|
+
handlers.push(() => viewer.off("select", onSelect));
|
|
66
|
+
}
|
|
67
|
+
if (onMeasure) {
|
|
68
|
+
viewer.on("measure", onMeasure);
|
|
69
|
+
handlers.push(() => viewer.off("measure", onMeasure));
|
|
70
|
+
}
|
|
71
|
+
if (onViewChange) {
|
|
72
|
+
viewer.on("viewchange", onViewChange);
|
|
73
|
+
handlers.push(() => viewer.off("viewchange", onViewChange));
|
|
74
|
+
}
|
|
75
|
+
return () => {
|
|
76
|
+
handlers.forEach((h) => {
|
|
77
|
+
h();
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
}, [onSelect, onMeasure, onViewChange]);
|
|
81
|
+
react.useImperativeHandle(ref, () => ({
|
|
82
|
+
getViewer: () => viewerRef.current,
|
|
83
|
+
fitToView: () => viewerRef.current?.fitToView(),
|
|
84
|
+
getLayers: () => viewerRef.current?.getLayers() ?? [],
|
|
85
|
+
setLayerVisible: (name, visible) => viewerRef.current?.setLayerVisible(name, visible)
|
|
86
|
+
}));
|
|
87
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
88
|
+
"div",
|
|
89
|
+
{
|
|
90
|
+
className,
|
|
91
|
+
style: { position: "relative", overflow: "hidden", ...style },
|
|
92
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
93
|
+
"canvas",
|
|
94
|
+
{
|
|
95
|
+
ref: canvasRef,
|
|
96
|
+
style: { display: "block", width: "100%", height: "100%" }
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
function useCadViewer(canvasRef, options) {
|
|
104
|
+
const viewerRef = react.useRef(null);
|
|
105
|
+
const [viewer, setViewer] = react.useState(null);
|
|
106
|
+
const [layers, setLayers] = react.useState([]);
|
|
107
|
+
const [isLoaded, setIsLoaded] = react.useState(false);
|
|
108
|
+
const [error, setError] = react.useState(null);
|
|
109
|
+
react.useEffect(() => {
|
|
110
|
+
if (!canvasRef.current) return;
|
|
111
|
+
const v = new core.CadViewer(canvasRef.current, options);
|
|
112
|
+
viewerRef.current = v;
|
|
113
|
+
setViewer(v);
|
|
114
|
+
return () => {
|
|
115
|
+
v.destroy();
|
|
116
|
+
viewerRef.current = null;
|
|
117
|
+
setViewer(null);
|
|
118
|
+
};
|
|
119
|
+
}, []);
|
|
120
|
+
const loadFile = react.useCallback(async (file) => {
|
|
121
|
+
if (!viewerRef.current) return;
|
|
122
|
+
setError(null);
|
|
123
|
+
try {
|
|
124
|
+
await viewerRef.current.loadFile(file);
|
|
125
|
+
setLayers(viewerRef.current.getLayers());
|
|
126
|
+
setIsLoaded(true);
|
|
127
|
+
} catch (err) {
|
|
128
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
129
|
+
}
|
|
130
|
+
}, []);
|
|
131
|
+
const loadString = react.useCallback((dxf) => {
|
|
132
|
+
if (!viewerRef.current) return;
|
|
133
|
+
setError(null);
|
|
134
|
+
try {
|
|
135
|
+
viewerRef.current.loadString(dxf);
|
|
136
|
+
setLayers(viewerRef.current.getLayers());
|
|
137
|
+
setIsLoaded(true);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
140
|
+
}
|
|
141
|
+
}, []);
|
|
142
|
+
return {
|
|
143
|
+
viewer,
|
|
144
|
+
layers,
|
|
145
|
+
isLoaded,
|
|
146
|
+
error,
|
|
147
|
+
loadFile,
|
|
148
|
+
loadString,
|
|
149
|
+
fitToView: () => viewerRef.current?.fitToView(),
|
|
150
|
+
setLayerVisible: (name, visible) => viewerRef.current?.setLayerVisible(name, visible),
|
|
151
|
+
setTheme: (theme) => viewerRef.current?.setTheme(theme),
|
|
152
|
+
setTool: (tool) => viewerRef.current?.setTool(tool)
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
exports.CadViewer = CadViewer;
|
|
157
|
+
exports.useCadViewer = useCadViewer;
|
|
158
|
+
//# sourceMappingURL=index.cjs.map
|
|
159
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/CadViewer.tsx","../src/useCadViewer.ts"],"names":["forwardRef","CadViewer","useRef","useEffect","CoreCadViewer","useImperativeHandle","jsx","useState","useCallback"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n type CSSProperties,\n} from 'react';\nimport {\n CadViewer as CoreCadViewer,\n type CadViewerOptions,\n type DxfLayer,\n type SelectEvent,\n type MeasureEvent,\n type ViewTransform,\n type Tool,\n type Theme,\n} from '@cadview/core';\n\nexport interface CadViewerProps {\n file?: File | ArrayBuffer | string | null;\n theme?: Theme;\n tool?: Tool;\n className?: string;\n style?: CSSProperties;\n options?: Omit<CadViewerOptions, 'theme' | 'initialTool'>;\n onSelect?: (event: SelectEvent) => void;\n onMeasure?: (event: MeasureEvent) => void;\n onViewChange?: (transform: ViewTransform) => void;\n onLayersLoaded?: (layers: DxfLayer[]) => void;\n}\n\nexport interface CadViewerRef {\n getViewer(): CoreCadViewer | null;\n fitToView(): void;\n getLayers(): DxfLayer[];\n setLayerVisible(name: string, visible: boolean): void;\n}\n\nexport const CadViewer = forwardRef<CadViewerRef, CadViewerProps>(\n function CadViewer(props, ref) {\n const {\n file,\n theme = 'dark',\n tool = 'pan',\n className,\n style,\n options,\n onSelect,\n onMeasure,\n onViewChange,\n onLayersLoaded,\n } = props;\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const viewerRef = useRef<CoreCadViewer | null>(null);\n\n useEffect(() => {\n if (!canvasRef.current) return;\n\n const viewer = new CoreCadViewer(canvasRef.current, {\n theme,\n initialTool: tool,\n ...options,\n });\n viewerRef.current = viewer;\n\n return () => {\n viewer.destroy();\n viewerRef.current = null;\n };\n }, []);\n\n useEffect(() => {\n viewerRef.current?.setTheme(theme);\n }, [theme]);\n\n useEffect(() => {\n viewerRef.current?.setTool(tool);\n }, [tool]);\n\n useEffect(() => {\n const viewer = viewerRef.current;\n if (!viewer || !file) return;\n\n if (file instanceof File) {\n viewer.loadFile(file).then(\n () => onLayersLoaded?.(viewer.getLayers()),\n (err) => console.error('CadViewer: failed to load file', err),\n );\n } else if (file instanceof ArrayBuffer) {\n viewer.loadArrayBuffer(file);\n onLayersLoaded?.(viewer.getLayers());\n } else if (typeof file === 'string') {\n viewer.loadString(file);\n onLayersLoaded?.(viewer.getLayers());\n }\n }, [file]);\n\n useEffect(() => {\n const viewer = viewerRef.current;\n if (!viewer) return;\n\n const handlers: Array<() => void> = [];\n\n if (onSelect) {\n viewer.on('select', onSelect);\n handlers.push(() => viewer.off('select', onSelect));\n }\n if (onMeasure) {\n viewer.on('measure', onMeasure);\n handlers.push(() => viewer.off('measure', onMeasure));\n }\n if (onViewChange) {\n viewer.on('viewchange', onViewChange);\n handlers.push(() => viewer.off('viewchange', onViewChange));\n }\n\n return () => { handlers.forEach((h) => { h(); }); };\n }, [onSelect, onMeasure, onViewChange]);\n\n useImperativeHandle(ref, () => ({\n getViewer: () => viewerRef.current,\n fitToView: () => viewerRef.current?.fitToView(),\n getLayers: () => viewerRef.current?.getLayers() ?? [],\n setLayerVisible: (name: string, visible: boolean) =>\n viewerRef.current?.setLayerVisible(name, visible),\n }));\n\n return (\n <div\n className={className}\n style={{ position: 'relative', overflow: 'hidden', ...style }}\n >\n <canvas\n ref={canvasRef}\n style={{ display: 'block', width: '100%', height: '100%' }}\n />\n </div>\n );\n },\n);\n","import { useEffect, useRef, useState, useCallback } from 'react';\nimport {\n CadViewer,\n type CadViewerOptions,\n type DxfLayer,\n} from '@cadview/core';\n\nexport function useCadViewer(\n canvasRef: React.RefObject<HTMLCanvasElement | null>,\n options?: CadViewerOptions,\n) {\n const viewerRef = useRef<CadViewer | null>(null);\n const [viewer, setViewer] = useState<CadViewer | null>(null);\n const [layers, setLayers] = useState<DxfLayer[]>([]);\n const [isLoaded, setIsLoaded] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (!canvasRef.current) return;\n const v = new CadViewer(canvasRef.current, options);\n viewerRef.current = v;\n setViewer(v);\n return () => {\n v.destroy();\n viewerRef.current = null;\n setViewer(null);\n };\n }, []);\n\n const loadFile = useCallback(async (file: File) => {\n if (!viewerRef.current) return;\n setError(null);\n try {\n await viewerRef.current.loadFile(file);\n setLayers(viewerRef.current.getLayers());\n setIsLoaded(true);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, []);\n\n const loadString = useCallback((dxf: string) => {\n if (!viewerRef.current) return;\n setError(null);\n try {\n viewerRef.current.loadString(dxf);\n setLayers(viewerRef.current.getLayers());\n setIsLoaded(true);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, []);\n\n return {\n viewer,\n layers,\n isLoaded,\n error,\n loadFile,\n loadString,\n fitToView: () => viewerRef.current?.fitToView(),\n setLayerVisible: (name: string, visible: boolean) =>\n viewerRef.current?.setLayerVisible(name, visible),\n setTheme: (theme: 'dark' | 'light') =>\n viewerRef.current?.setTheme(theme),\n setTool: (tool: 'pan' | 'select' | 'measure') =>\n viewerRef.current?.setTool(tool),\n };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { CSSProperties } from 'react';
|
|
3
|
+
import { Theme, Tool, CadViewerOptions, SelectEvent, MeasureEvent, ViewTransform, DxfLayer, CadViewer as CadViewer$1 } from '@cadview/core';
|
|
4
|
+
export { DxfDocument, DxfEntity, DxfLayer, MeasureEvent, SelectEvent, Theme, Tool, ViewTransform } from '@cadview/core';
|
|
5
|
+
|
|
6
|
+
interface CadViewerProps {
|
|
7
|
+
file?: File | ArrayBuffer | string | null;
|
|
8
|
+
theme?: Theme;
|
|
9
|
+
tool?: Tool;
|
|
10
|
+
className?: string;
|
|
11
|
+
style?: CSSProperties;
|
|
12
|
+
options?: Omit<CadViewerOptions, 'theme' | 'initialTool'>;
|
|
13
|
+
onSelect?: (event: SelectEvent) => void;
|
|
14
|
+
onMeasure?: (event: MeasureEvent) => void;
|
|
15
|
+
onViewChange?: (transform: ViewTransform) => void;
|
|
16
|
+
onLayersLoaded?: (layers: DxfLayer[]) => void;
|
|
17
|
+
}
|
|
18
|
+
interface CadViewerRef {
|
|
19
|
+
getViewer(): CadViewer$1 | null;
|
|
20
|
+
fitToView(): void;
|
|
21
|
+
getLayers(): DxfLayer[];
|
|
22
|
+
setLayerVisible(name: string, visible: boolean): void;
|
|
23
|
+
}
|
|
24
|
+
declare const CadViewer: react.ForwardRefExoticComponent<CadViewerProps & react.RefAttributes<CadViewerRef>>;
|
|
25
|
+
|
|
26
|
+
declare function useCadViewer(canvasRef: React.RefObject<HTMLCanvasElement | null>, options?: CadViewerOptions): {
|
|
27
|
+
viewer: CadViewer$1 | null;
|
|
28
|
+
layers: DxfLayer[];
|
|
29
|
+
isLoaded: boolean;
|
|
30
|
+
error: Error | null;
|
|
31
|
+
loadFile: (file: File) => Promise<void>;
|
|
32
|
+
loadString: (dxf: string) => void;
|
|
33
|
+
fitToView: () => void | undefined;
|
|
34
|
+
setLayerVisible: (name: string, visible: boolean) => void | undefined;
|
|
35
|
+
setTheme: (theme: "dark" | "light") => void | undefined;
|
|
36
|
+
setTool: (tool: "pan" | "select" | "measure") => void | undefined;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export { CadViewer, type CadViewerProps, type CadViewerRef, useCadViewer };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { CSSProperties } from 'react';
|
|
3
|
+
import { Theme, Tool, CadViewerOptions, SelectEvent, MeasureEvent, ViewTransform, DxfLayer, CadViewer as CadViewer$1 } from '@cadview/core';
|
|
4
|
+
export { DxfDocument, DxfEntity, DxfLayer, MeasureEvent, SelectEvent, Theme, Tool, ViewTransform } from '@cadview/core';
|
|
5
|
+
|
|
6
|
+
interface CadViewerProps {
|
|
7
|
+
file?: File | ArrayBuffer | string | null;
|
|
8
|
+
theme?: Theme;
|
|
9
|
+
tool?: Tool;
|
|
10
|
+
className?: string;
|
|
11
|
+
style?: CSSProperties;
|
|
12
|
+
options?: Omit<CadViewerOptions, 'theme' | 'initialTool'>;
|
|
13
|
+
onSelect?: (event: SelectEvent) => void;
|
|
14
|
+
onMeasure?: (event: MeasureEvent) => void;
|
|
15
|
+
onViewChange?: (transform: ViewTransform) => void;
|
|
16
|
+
onLayersLoaded?: (layers: DxfLayer[]) => void;
|
|
17
|
+
}
|
|
18
|
+
interface CadViewerRef {
|
|
19
|
+
getViewer(): CadViewer$1 | null;
|
|
20
|
+
fitToView(): void;
|
|
21
|
+
getLayers(): DxfLayer[];
|
|
22
|
+
setLayerVisible(name: string, visible: boolean): void;
|
|
23
|
+
}
|
|
24
|
+
declare const CadViewer: react.ForwardRefExoticComponent<CadViewerProps & react.RefAttributes<CadViewerRef>>;
|
|
25
|
+
|
|
26
|
+
declare function useCadViewer(canvasRef: React.RefObject<HTMLCanvasElement | null>, options?: CadViewerOptions): {
|
|
27
|
+
viewer: CadViewer$1 | null;
|
|
28
|
+
layers: DxfLayer[];
|
|
29
|
+
isLoaded: boolean;
|
|
30
|
+
error: Error | null;
|
|
31
|
+
loadFile: (file: File) => Promise<void>;
|
|
32
|
+
loadString: (dxf: string) => void;
|
|
33
|
+
fitToView: () => void | undefined;
|
|
34
|
+
setLayerVisible: (name: string, visible: boolean) => void | undefined;
|
|
35
|
+
setTheme: (theme: "dark" | "light") => void | undefined;
|
|
36
|
+
setTool: (tool: "pan" | "select" | "measure") => void | undefined;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export { CadViewer, type CadViewerProps, type CadViewerRef, useCadViewer };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { forwardRef, useRef, useEffect, useImperativeHandle, useState, useCallback } from 'react';
|
|
2
|
+
import { CadViewer as CadViewer$1 } from '@cadview/core';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/CadViewer.tsx
|
|
6
|
+
var CadViewer = forwardRef(
|
|
7
|
+
function CadViewer2(props, ref) {
|
|
8
|
+
const {
|
|
9
|
+
file,
|
|
10
|
+
theme = "dark",
|
|
11
|
+
tool = "pan",
|
|
12
|
+
className,
|
|
13
|
+
style,
|
|
14
|
+
options,
|
|
15
|
+
onSelect,
|
|
16
|
+
onMeasure,
|
|
17
|
+
onViewChange,
|
|
18
|
+
onLayersLoaded
|
|
19
|
+
} = props;
|
|
20
|
+
const canvasRef = useRef(null);
|
|
21
|
+
const viewerRef = useRef(null);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!canvasRef.current) return;
|
|
24
|
+
const viewer = new CadViewer$1(canvasRef.current, {
|
|
25
|
+
theme,
|
|
26
|
+
initialTool: tool,
|
|
27
|
+
...options
|
|
28
|
+
});
|
|
29
|
+
viewerRef.current = viewer;
|
|
30
|
+
return () => {
|
|
31
|
+
viewer.destroy();
|
|
32
|
+
viewerRef.current = null;
|
|
33
|
+
};
|
|
34
|
+
}, []);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
viewerRef.current?.setTheme(theme);
|
|
37
|
+
}, [theme]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
viewerRef.current?.setTool(tool);
|
|
40
|
+
}, [tool]);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const viewer = viewerRef.current;
|
|
43
|
+
if (!viewer || !file) return;
|
|
44
|
+
if (file instanceof File) {
|
|
45
|
+
viewer.loadFile(file).then(
|
|
46
|
+
() => onLayersLoaded?.(viewer.getLayers()),
|
|
47
|
+
(err) => console.error("CadViewer: failed to load file", err)
|
|
48
|
+
);
|
|
49
|
+
} else if (file instanceof ArrayBuffer) {
|
|
50
|
+
viewer.loadArrayBuffer(file);
|
|
51
|
+
onLayersLoaded?.(viewer.getLayers());
|
|
52
|
+
} else if (typeof file === "string") {
|
|
53
|
+
viewer.loadString(file);
|
|
54
|
+
onLayersLoaded?.(viewer.getLayers());
|
|
55
|
+
}
|
|
56
|
+
}, [file]);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
const viewer = viewerRef.current;
|
|
59
|
+
if (!viewer) return;
|
|
60
|
+
const handlers = [];
|
|
61
|
+
if (onSelect) {
|
|
62
|
+
viewer.on("select", onSelect);
|
|
63
|
+
handlers.push(() => viewer.off("select", onSelect));
|
|
64
|
+
}
|
|
65
|
+
if (onMeasure) {
|
|
66
|
+
viewer.on("measure", onMeasure);
|
|
67
|
+
handlers.push(() => viewer.off("measure", onMeasure));
|
|
68
|
+
}
|
|
69
|
+
if (onViewChange) {
|
|
70
|
+
viewer.on("viewchange", onViewChange);
|
|
71
|
+
handlers.push(() => viewer.off("viewchange", onViewChange));
|
|
72
|
+
}
|
|
73
|
+
return () => {
|
|
74
|
+
handlers.forEach((h) => {
|
|
75
|
+
h();
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
}, [onSelect, onMeasure, onViewChange]);
|
|
79
|
+
useImperativeHandle(ref, () => ({
|
|
80
|
+
getViewer: () => viewerRef.current,
|
|
81
|
+
fitToView: () => viewerRef.current?.fitToView(),
|
|
82
|
+
getLayers: () => viewerRef.current?.getLayers() ?? [],
|
|
83
|
+
setLayerVisible: (name, visible) => viewerRef.current?.setLayerVisible(name, visible)
|
|
84
|
+
}));
|
|
85
|
+
return /* @__PURE__ */ jsx(
|
|
86
|
+
"div",
|
|
87
|
+
{
|
|
88
|
+
className,
|
|
89
|
+
style: { position: "relative", overflow: "hidden", ...style },
|
|
90
|
+
children: /* @__PURE__ */ jsx(
|
|
91
|
+
"canvas",
|
|
92
|
+
{
|
|
93
|
+
ref: canvasRef,
|
|
94
|
+
style: { display: "block", width: "100%", height: "100%" }
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
function useCadViewer(canvasRef, options) {
|
|
102
|
+
const viewerRef = useRef(null);
|
|
103
|
+
const [viewer, setViewer] = useState(null);
|
|
104
|
+
const [layers, setLayers] = useState([]);
|
|
105
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
106
|
+
const [error, setError] = useState(null);
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (!canvasRef.current) return;
|
|
109
|
+
const v = new CadViewer$1(canvasRef.current, options);
|
|
110
|
+
viewerRef.current = v;
|
|
111
|
+
setViewer(v);
|
|
112
|
+
return () => {
|
|
113
|
+
v.destroy();
|
|
114
|
+
viewerRef.current = null;
|
|
115
|
+
setViewer(null);
|
|
116
|
+
};
|
|
117
|
+
}, []);
|
|
118
|
+
const loadFile = useCallback(async (file) => {
|
|
119
|
+
if (!viewerRef.current) return;
|
|
120
|
+
setError(null);
|
|
121
|
+
try {
|
|
122
|
+
await viewerRef.current.loadFile(file);
|
|
123
|
+
setLayers(viewerRef.current.getLayers());
|
|
124
|
+
setIsLoaded(true);
|
|
125
|
+
} catch (err) {
|
|
126
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
127
|
+
}
|
|
128
|
+
}, []);
|
|
129
|
+
const loadString = useCallback((dxf) => {
|
|
130
|
+
if (!viewerRef.current) return;
|
|
131
|
+
setError(null);
|
|
132
|
+
try {
|
|
133
|
+
viewerRef.current.loadString(dxf);
|
|
134
|
+
setLayers(viewerRef.current.getLayers());
|
|
135
|
+
setIsLoaded(true);
|
|
136
|
+
} catch (err) {
|
|
137
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
138
|
+
}
|
|
139
|
+
}, []);
|
|
140
|
+
return {
|
|
141
|
+
viewer,
|
|
142
|
+
layers,
|
|
143
|
+
isLoaded,
|
|
144
|
+
error,
|
|
145
|
+
loadFile,
|
|
146
|
+
loadString,
|
|
147
|
+
fitToView: () => viewerRef.current?.fitToView(),
|
|
148
|
+
setLayerVisible: (name, visible) => viewerRef.current?.setLayerVisible(name, visible),
|
|
149
|
+
setTheme: (theme) => viewerRef.current?.setTheme(theme),
|
|
150
|
+
setTool: (tool) => viewerRef.current?.setTool(tool)
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export { CadViewer, useCadViewer };
|
|
155
|
+
//# sourceMappingURL=index.js.map
|
|
156
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/CadViewer.tsx","../src/useCadViewer.ts"],"names":["CadViewer","CoreCadViewer","useRef","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n type CSSProperties,\n} from 'react';\nimport {\n CadViewer as CoreCadViewer,\n type CadViewerOptions,\n type DxfLayer,\n type SelectEvent,\n type MeasureEvent,\n type ViewTransform,\n type Tool,\n type Theme,\n} from '@cadview/core';\n\nexport interface CadViewerProps {\n file?: File | ArrayBuffer | string | null;\n theme?: Theme;\n tool?: Tool;\n className?: string;\n style?: CSSProperties;\n options?: Omit<CadViewerOptions, 'theme' | 'initialTool'>;\n onSelect?: (event: SelectEvent) => void;\n onMeasure?: (event: MeasureEvent) => void;\n onViewChange?: (transform: ViewTransform) => void;\n onLayersLoaded?: (layers: DxfLayer[]) => void;\n}\n\nexport interface CadViewerRef {\n getViewer(): CoreCadViewer | null;\n fitToView(): void;\n getLayers(): DxfLayer[];\n setLayerVisible(name: string, visible: boolean): void;\n}\n\nexport const CadViewer = forwardRef<CadViewerRef, CadViewerProps>(\n function CadViewer(props, ref) {\n const {\n file,\n theme = 'dark',\n tool = 'pan',\n className,\n style,\n options,\n onSelect,\n onMeasure,\n onViewChange,\n onLayersLoaded,\n } = props;\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const viewerRef = useRef<CoreCadViewer | null>(null);\n\n useEffect(() => {\n if (!canvasRef.current) return;\n\n const viewer = new CoreCadViewer(canvasRef.current, {\n theme,\n initialTool: tool,\n ...options,\n });\n viewerRef.current = viewer;\n\n return () => {\n viewer.destroy();\n viewerRef.current = null;\n };\n }, []);\n\n useEffect(() => {\n viewerRef.current?.setTheme(theme);\n }, [theme]);\n\n useEffect(() => {\n viewerRef.current?.setTool(tool);\n }, [tool]);\n\n useEffect(() => {\n const viewer = viewerRef.current;\n if (!viewer || !file) return;\n\n if (file instanceof File) {\n viewer.loadFile(file).then(\n () => onLayersLoaded?.(viewer.getLayers()),\n (err) => console.error('CadViewer: failed to load file', err),\n );\n } else if (file instanceof ArrayBuffer) {\n viewer.loadArrayBuffer(file);\n onLayersLoaded?.(viewer.getLayers());\n } else if (typeof file === 'string') {\n viewer.loadString(file);\n onLayersLoaded?.(viewer.getLayers());\n }\n }, [file]);\n\n useEffect(() => {\n const viewer = viewerRef.current;\n if (!viewer) return;\n\n const handlers: Array<() => void> = [];\n\n if (onSelect) {\n viewer.on('select', onSelect);\n handlers.push(() => viewer.off('select', onSelect));\n }\n if (onMeasure) {\n viewer.on('measure', onMeasure);\n handlers.push(() => viewer.off('measure', onMeasure));\n }\n if (onViewChange) {\n viewer.on('viewchange', onViewChange);\n handlers.push(() => viewer.off('viewchange', onViewChange));\n }\n\n return () => { handlers.forEach((h) => { h(); }); };\n }, [onSelect, onMeasure, onViewChange]);\n\n useImperativeHandle(ref, () => ({\n getViewer: () => viewerRef.current,\n fitToView: () => viewerRef.current?.fitToView(),\n getLayers: () => viewerRef.current?.getLayers() ?? [],\n setLayerVisible: (name: string, visible: boolean) =>\n viewerRef.current?.setLayerVisible(name, visible),\n }));\n\n return (\n <div\n className={className}\n style={{ position: 'relative', overflow: 'hidden', ...style }}\n >\n <canvas\n ref={canvasRef}\n style={{ display: 'block', width: '100%', height: '100%' }}\n />\n </div>\n );\n },\n);\n","import { useEffect, useRef, useState, useCallback } from 'react';\nimport {\n CadViewer,\n type CadViewerOptions,\n type DxfLayer,\n} from '@cadview/core';\n\nexport function useCadViewer(\n canvasRef: React.RefObject<HTMLCanvasElement | null>,\n options?: CadViewerOptions,\n) {\n const viewerRef = useRef<CadViewer | null>(null);\n const [viewer, setViewer] = useState<CadViewer | null>(null);\n const [layers, setLayers] = useState<DxfLayer[]>([]);\n const [isLoaded, setIsLoaded] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (!canvasRef.current) return;\n const v = new CadViewer(canvasRef.current, options);\n viewerRef.current = v;\n setViewer(v);\n return () => {\n v.destroy();\n viewerRef.current = null;\n setViewer(null);\n };\n }, []);\n\n const loadFile = useCallback(async (file: File) => {\n if (!viewerRef.current) return;\n setError(null);\n try {\n await viewerRef.current.loadFile(file);\n setLayers(viewerRef.current.getLayers());\n setIsLoaded(true);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, []);\n\n const loadString = useCallback((dxf: string) => {\n if (!viewerRef.current) return;\n setError(null);\n try {\n viewerRef.current.loadString(dxf);\n setLayers(viewerRef.current.getLayers());\n setIsLoaded(true);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, []);\n\n return {\n viewer,\n layers,\n isLoaded,\n error,\n loadFile,\n loadString,\n fitToView: () => viewerRef.current?.fitToView(),\n setLayerVisible: (name: string, visible: boolean) =>\n viewerRef.current?.setLayerVisible(name, visible),\n setTheme: (theme: 'dark' | 'light') =>\n viewerRef.current?.setTheme(theme),\n setTool: (tool: 'pan' | 'select' | 'measure') =>\n viewerRef.current?.setTool(tool),\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cadview/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "React wrapper for @cadview/core — CAD/DXF file viewer component",
|
|
7
|
+
"author": "Wisnu Wicaksono",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"cad",
|
|
10
|
+
"dxf",
|
|
11
|
+
"viewer",
|
|
12
|
+
"react",
|
|
13
|
+
"component",
|
|
14
|
+
"canvas"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/wiscaksono/cadview.git",
|
|
19
|
+
"directory": "packages/react"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/wiscaksono/cadview/tree/main/packages/react#readme",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/wiscaksono/cadview/issues"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
},
|
|
28
|
+
"main": "./dist/index.cjs",
|
|
29
|
+
"module": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"import": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"require": {
|
|
38
|
+
"types": "./dist/index.d.cts",
|
|
39
|
+
"default": "./dist/index.cjs"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"LICENSE",
|
|
46
|
+
"README.md"
|
|
47
|
+
],
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
50
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
51
|
+
"@cadview/core": "0.1.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/react": "^19.0.0",
|
|
55
|
+
"@types/react-dom": "^19.0.0",
|
|
56
|
+
"react": "^19.0.0",
|
|
57
|
+
"react-dom": "^19.0.0",
|
|
58
|
+
"tsup": "^8.0.0",
|
|
59
|
+
"typescript": "^5.7.0",
|
|
60
|
+
"@cadview/core": "0.1.0"
|
|
61
|
+
},
|
|
62
|
+
"sideEffects": false,
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsup",
|
|
65
|
+
"dev": "tsup --watch",
|
|
66
|
+
"typecheck": "tsc --noEmit"
|
|
67
|
+
}
|
|
68
|
+
}
|