{"_id":"@aleontaridis/pcb-3d-viewer","_rev":"2-cbc396467c241810dde78debb8652dbd","name":"@aleontaridis/pcb-3d-viewer","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@aleontaridis/pcb-3d-viewer","version":"1.0.0","author":"","license":"ISC","_id":"@aleontaridis/pcb-3d-viewer@1.0.0","maintainers":[{"name":"aleontaridis","email":"alexleontaridis230708@gmail.com"}],"dist":{"shasum":"edc46452450f4393894f83ac42103825bda5793e","tarball":"https://registry.npmjs.org/@aleontaridis/pcb-3d-viewer/-/pcb-3d-viewer-1.0.0.tgz","fileCount":7,"integrity":"sha512-Dl9lJyG9hojia6qtnLN/FUThkxb+XXiunJS0ZfdxniRCO82fDViMrCD5adwwucBWraECJMwrNTij4cnnIC/YSQ==","signatures":[{"sig":"MEYCIQC7sQ1rZ5wFG8xy+VOzGeZSmOgGlgHhu2iNlpLozUvySwIhAIm/wS2OMwYB5Oa40xUbivkAd1UJVlwgO7ITuSIjfY49","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1945851},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"e1a9ad7947c1390e9dc616fffd90caacd8991e50","scripts":{"build":"tsup","start":"bun run storybook","format":"biome format . --write","dev:old":"bunx --bun vite","preview":"vite preview","storybook":"storybook dev -p 6006","prepublish":"npm run build","format:check":"biome format .","vercel-build":"bun run build-storybook","build-storybook":"storybook build","test:node-bundle":"node ./scripts/load-bundle-in-node.js"},"_npmUser":{"name":"aleontaridis","email":"alexleontaridis230708@gmail.com"},"_npmVersion":"10.8.2","description":"React 3D PCB viewer for Circuit JSON","directories":{"lib":"lib","test":"tests"},"_nodeVersion":"20.19.4","dependencies":{"three":"^0.165.0","circuit-json":"^0.0.421","three-stdlib":"^2.36.0","react-hot-toast":"^2.6.0","circuit-to-canvas":"^0.0.102","troika-three-text":"^0.52.4","@jscad/regl-renderer":"^2.6.12","@jscad/stl-serializer":"^2.1.20","@radix-ui/react-dropdown-menu":"^2.1.16"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.6","vite":"^7.1.5","debug":"^4.4.0","jsdom":"^26.0.0","semver":"^7.7.0","spicey":"^0.0.14","bun-types":"1.2.1","storybook":"^9.1.20","tscircuit":"^0.0.1704","strip-ansi":"^7.1.0","typescript":"^5.7.3","@types/jsdom":"^21.1.7","@types/react":"19","@types/three":"^0.165.0","bun-match-svg":"^0.0.9","jscad-planner":"^0.0.13","@biomejs/biome":"^2.1.4","@jscad/modeling":"^2.12.5","@tscircuit/eval":"^0.0.836","@tscircuit/props":"^0.0.532","@types/react-dom":"19","@storybook/blocks":"9.0.0-alpha.17","calculate-packing":"^0.0.73","jscad-electronics":"^0.0.123","react-use-gesture":"^9.1.3","@tscircuit/alphabet":"^0.0.25","@tscircuit/krt-wasm":"^0.1.0","vite-tsconfig-paths":"^4.3.2","@vitejs/plugin-react":"^4.3.4","@storybook/react-vite":"^9.1.5","@tscircuit/math-utils":"^0.0.36","circuit-json-to-spice":"^0.0.34","@tscircuit/solver-utils":"^0.0.4","@chromatic-com/storybook":"^1.9.0","@tscircuit/copper-pour-solver":"^0.0.29"},"peerDependencies":{"zod":"3","react":"19.1.0","react-dom":"19.1.0","@tscircuit/core":"*","@tscircuit/circuit-json-util":"*"},"_npmOperationalInternal":{"tmp":"tmp/pcb-3d-viewer_1.0.0_1778580073069_0.30160044891103444","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@aleontaridis/pcb-3d-viewer","version":"1.1.0","description":"React 3D PCB viewer for Circuit JSON","main":"./dist/index.js","module":"./dist/index.js","type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"dependencies":{"@radix-ui/react-dropdown-menu":"^2.1.16","@jscad/regl-renderer":"^2.6.12","@jscad/stl-serializer":"^2.1.20","circuit-json":"^0.0.421","circuit-to-canvas":"^0.0.102","react-hot-toast":"^2.6.0","occt-import-js":"0.0.23","three":"^0.165.0","three-stdlib":"^2.36.0","troika-three-text":"^0.52.4"},"peerDependencies":{"@tscircuit/circuit-json-util":"*","@tscircuit/core":"*","react":"19.1.0","react-dom":"19.1.0","zod":"3"},"devDependencies":{"@biomejs/biome":"^2.1.4","@chromatic-com/storybook":"^1.9.0","@jscad/modeling":"^2.12.5","@storybook/blocks":"9.0.0-alpha.17","@storybook/react-vite":"^9.1.5","@tscircuit/alphabet":"^0.0.25","@tscircuit/copper-pour-solver":"^0.0.29","@tscircuit/eval":"^0.0.836","@tscircuit/krt-wasm":"^0.1.0","@tscircuit/math-utils":"^0.0.36","@tscircuit/props":"^0.0.532","@tscircuit/solver-utils":"^0.0.4","@types/jsdom":"^21.1.7","@types/react":"19","@types/react-dom":"19","@types/three":"^0.165.0","@vitejs/plugin-react":"^4.3.4","bun-match-svg":"^0.0.9","bun-types":"1.2.1","calculate-packing":"^0.0.73","circuit-json-to-spice":"^0.0.34","debug":"^4.4.0","jscad-electronics":"^0.0.123","jscad-planner":"^0.0.13","jsdom":"^26.0.0","react-use-gesture":"^9.1.3","semver":"^7.7.0","spicey":"^0.0.14","storybook":"^9.1.20","strip-ansi":"^7.1.0","tscircuit":"^0.0.1704","tsup":"^8.3.6","typescript":"^5.7.3","vite":"^7.1.5","vite-tsconfig-paths":"^4.3.2"},"directories":{"lib":"lib","test":"tests"},"author":"","license":"ISC","types":"./dist/index.d.ts","scripts":{"start":"bun run storybook","dev:old":"bunx --bun vite","build":"tsup","prepublish":"npm run build","preview":"vite preview","storybook":"storybook dev -p 6006","build-storybook":"storybook build","vercel-build":"bun run build-storybook","format":"biome format . --write","format:check":"biome format .","test:node-bundle":"node ./scripts/load-bundle-in-node.js"},"_id":"@aleontaridis/pcb-3d-viewer@1.1.0","_integrity":"sha512-Eto4qrA9KYF/YUh+oVYicdJ+ntwctt2FIPtQ4tY7Qds6w1PN2OwZAOh8TacaVnH84OSKENIUwaE7YD3qM0DvYg==","_resolved":"/private/var/folders/3l/mp53phls7t94_lbfhr0_rv780000gn/T/f33b37a25cdf61d6b656f1433175f837/aleontaridis-pcb-3d-viewer-1.1.0.tgz","_from":"file:aleontaridis-pcb-3d-viewer-1.1.0.tgz","_nodeVersion":"20.19.4","_npmVersion":"10.8.2","dist":{"integrity":"sha512-Eto4qrA9KYF/YUh+oVYicdJ+ntwctt2FIPtQ4tY7Qds6w1PN2OwZAOh8TacaVnH84OSKENIUwaE7YD3qM0DvYg==","shasum":"d8265d4c5ceb0d90b253a023517527d517138b08","tarball":"https://registry.npmjs.org/@aleontaridis/pcb-3d-viewer/-/pcb-3d-viewer-1.1.0.tgz","fileCount":8,"unpackedSize":9550680,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDAv8vfuIsocnXpTpJQO9WsSdgFVZ3lalovXCnpkTaeAQIgUm3F4Ku5s1qLy6O7E8GEg73ezcyhKPVSRQF49AZkBlE="}]},"_npmUser":{"name":"aleontaridis","email":"alexleontaridis230708@gmail.com"},"maintainers":[{"name":"aleontaridis","email":"alexleontaridis230708@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pcb-3d-viewer_1.1.0_1778583841333_0.8525375518842779"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-12T10:01:12.910Z","modified":"2026-05-12T11:04:01.817Z","1.0.0":"2026-05-12T10:01:13.294Z","1.1.0":"2026-05-12T11:04:01.693Z"},"license":"ISC","description":"React 3D PCB viewer for Circuit JSON","maintainers":[{"name":"aleontaridis","email":"alexleontaridis230708@gmail.com"}],"readme":"# @aleontaridis/pcb-3d-viewer\n\n**Built on top of** [`@tscircuit/3d-viewer`](https://www.npmjs.com/package/@tscircuit/3d-viewer) ([GitHub](https://github.com/tscircuit/3d-viewer)): same Circuit JSON / tscircuit integration model, with rendering and viewer UI changes described below.\n\nAn updated 3D printed circuit board viewer for [Circuit JSON](https://github.com/tscircuit/circuit-json) and [tscircuit](https://github.com/tscircuit/tscircuit).\n\n## Visual comparison\n\nSame demo board (USB-C, tactile switch, **R1**, **LED**): **before** = upstream viewer, **after** = this fork.\n\n| Before (original library) | After (this library) |\n| --- | --- |\n| ![Before: original 3d viewer](https://raw.githubusercontent.com/Alex-Leontaridis/3d-viewer/main/readme-assets/before-original-viewer.png) | ![After: this library](https://raw.githubusercontent.com/Alex-Leontaridis/3d-viewer/main/readme-assets/after-this-library.png) |\n\n## What changed in this fork\n\n**Rendering and materials.** The look of the viewer was rebuilt in passes: **lighting** and the **background grid** were updated, the **WebGL canvas** and **renderer** settings were tuned for clearer exposure and contrast, and the **board plus parts** (footprints, imported models, and board textures) were adjusted so everything reads more like real objects than flat shapes. Parts now pick up scene lighting in a more uniform way, and surface colors drive more believable **metal vs plastic** shading so resistors, connectors, and the board do not all look the same. **Board shading** was split so **painted textures** and **solid mesh** stay aligned instead of fighting each other.\n\n**Copper, board laminate, and solder mask.** **Copper** color is defined in one place and reused wherever copper appears in both **flat overlays** and **3D**, so the 2D layers and the 3D metal tint match. The **fiberglass edge** of the board uses explicit laminate coloring so the side of the PCB reads as stacked material, not one flat green slab. **Solder mask**, **height**, and **shininess** maps were expanded so mask, bumps, and copper interact: as you **orbit the camera**, you get more depth and specular variation on the green surface.\n\n**Engine simplification.** The old **Manifold-based** mesh path (used for some hole and via geometry) was **removed completely**. The viewer that ships now is built on **JSCAD** and **Three.js** only; the main viewer shell was rewired, dependencies and dev stories were cleaned up, and a large block of unused geometry code was deleted.\n\n**Silkscreen and labels.** Silkscreen and related overlays got a reliability pass: an outdated bounds helper was removed, and the pipelines that draw **silkscreen**, **mask**, **assembly notes**, and **fab notes** were rewired so **reference designators and text** land at **stable size and position**. The silkscreen Storybook example is the best quick visual check for label quality.\n\n**Camera and menus.** **Orbit**, **view presets**, and the **corner orientation control** were reworked so camera motion and preset jumps feel smoother and more predictable. During the parallel-branch period, the experimental UI and the main tree were kept in step so menus and the gizmo did not drift apart. A later pass simplified how the outer viewer wires into the **context menu** while keeping **camera presets**, **auto-rotate**, **export**, and **layer / appearance** toggles.\n\n**For app authors.** What you import and render—the main **viewer component**, **circuit JSON**, and **board markup**—stays the same idea as upstream even though the internals changed. Install and examples below.\n\n## Features\n\n- 3D visualization of PCB layouts\n- Interactive camera controls (pan, zoom, rotate)\n- Support for various PCB components (resistors, capacitors, Chips, etc.)\n- Customizable board and component rendering\n\n## Installation\n\n```bash\nnpm install @aleontaridis/pcb-3d-viewer\n```\n\n## Usage\n\n### Basic Example\n\n```jsx\nimport React from \"react\"\nimport { CadViewer } from \"@aleontaridis/pcb-3d-viewer\"\n\nconst MyPCBViewer = () => {\n  return (\n    <CadViewer>\n      <board width=\"20mm\" height=\"20mm\">\n        <resistor\n          name=\"R1\"\n          footprint=\"0805\"\n          resistance=\"10k\"\n          pcbX={5}\n          pcbY={5}\n        />\n        <capacitor\n          name=\"C1\"\n          footprint=\"0603\"\n          capacitance=\"1uF\"\n          pcbX={-4}\n          pcbY={0}\n        />\n      </board>\n    </CadViewer>\n  )\n}\n\nexport default MyPCBViewer\n```\n\n### Using with circuitJson Data\n\n```jsx\nimport React from \"react\"\nimport { CadViewer } from \"@aleontaridis/pcb-3d-viewer\"\nimport mycircuitJsonData from \"./mycircuitJsonpData.json\"\n\nconst MyPCBViewer = () => {\n  return <CadViewer circuitJson={mycircuitJsonData} />\n}\n\nexport default MyPCBViewer\n```\n\n### Converting to SVG (Node.js)\n\nWhen using the SVG converter in Node.js environments, you'll need to provide JSDOM:\n\n```typescript\nimport { JSDOM } from \"jsdom\"\nimport {\n  convertCircuitJsonTo3dSvg,\n  applyJsdomShim,\n} from \"@aleontaridis/pcb-3d-viewer\"\n\n// Setup JSDOM environment\nconst dom = new JSDOM()\napplyJsdomShim(dom)\n\n// Convert circuit to SVG\nconst options = {\n  width: 800,\n  height: 600,\n  backgroundColor: \"#ffffff\",\n  padding: 20,\n  zoom: 50,\n  camera: {\n    position: { x: 0, y: 0, z: 100 },\n    lookAt: { x: 0, y: 0, z: 0 },\n  },\n}\n\nconst svgString = await convertCircuitJsonTo3dSvg(circuitJson, options)\n```\n\nThe `convertCircuitJsonTo3dSvg` function accepts the following options:\n- `width`: Width of the output SVG (default: 800)\n- `height`: Height of the output SVG (default: 600)\n- `backgroundColor`: Background color in hex format (default: \"#ffffff\")\n- `padding`: Padding around the board (default: 20)\n- `zoom`: Zoom level (default: 1.5)\n- `camera`: Camera position and lookAt configuration\n  - `position`: {x, y, z} coordinates for camera position\n  - `lookAt`: {x, y, z} coordinates for camera target\n\n## API Reference\n\n### `<CadViewer>`\n\nMain component for rendering the 3D PCB viewer.\n\nProps:\n\n- `circuit-json`: (optional) An array of AnyCircuitElement objects representing the PCB layout.\n- `children`: (optional) React children elements describing the PCB layout (alternative to using `circuit-json`).\n- `resolveStaticAsset`: (optional) Function that receives each component model URL (`obj`, `wrl`, `stl`, `gltf`, `glb`, `step`) and returns the resolved URL to load.\n\n### `<board>`\n\nDefines the PCB board dimensions.\n\nProps:\n\n- `width`: Width of the board (e.g., \"20mm\").\n- `height`: Height of the board (e.g., \"20mm\").\n\n### Component Elements\n\nVarious component elements can be used as children of the `<board>` element:\n\n- `<resistor>`\n- `<capacitor>`\n- `<chip>`\n- `<bug>` (for ICs)\n\nEach component has specific props for defining its characteristics and position on the board.\n\n## Advanced Usage\n\n### Custom Component Models\n\nYou can define custom 3D models for components using the `cadModel` prop:\n\n```jsx\n<chip\n  name=\"U1\"\n  footprint=\"soic8\"\n  cadModel={{\n    objUrl: \"/path/to/custom-model.obj\",\n    mtlUrl: \"/path/to/custom-material.mtl\",\n  }}\n/>\n```\n\n### JSCAD Models\n\nFor more complex or programmatically defined models, you can use JSCAD:\n\n```jsx\n<bug\n  footprint=\"soic8\"\n  name=\"U1\"\n  cadModel={{\n    jscad: {\n      type: \"cube\",\n      size: 5,\n    },\n  }}\n/>\n```\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n","readmeFilename":"README.md"}