Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import path from "node:path"
import type { StorybookConfig } from "@storybook/react-vite"
import path from "path"

const addProxyLogging = (proxy: any) => {
proxy.on("error", (err, req, res) => {
proxy.on("error", (err, _req, _res) => {
console.error("proxy error", err)
})
proxy.on("proxyReq", (proxyReq, req, res) => {
proxy.on("proxyReq", (_proxyReq, req, _res) => {
console.log("Sending Request to the Target:", req.method, req.url)
})
proxy.on("proxyRes", (proxyRes, req, res) => {
proxy.on("proxyRes", (proxyRes, req, _res) => {
console.log(
"Received Response from the Target:",
proxyRes.statusCode,
Expand Down
4 changes: 1 addition & 3 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from "react"
import type { Preview } from "@storybook/react"
import type { StoryFn } from "@storybook/react"
import type { Preview, StoryFn } from "@storybook/react"

const withContainer = (Story: StoryFn) => (
<div style={{ width: "100vw", height: "100vh" }}>
Expand Down
15 changes: 8 additions & 7 deletions biome.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
{
"$schema": "https://biomejs.dev/schemas/2.1.4/schema.json",
"$schema": "https://biomejs.dev/schemas/2.4.10/schema.json",
"formatter": {
"enabled": true,
"indentStyle": "space"
},
"files": {
"includes": [
"!**/cosmos-export/**",
"!dist/**",
"!**/package.json",
"!**/node_modules/**",
"**",
"!**/stores/assets/**",
"!**/cosmos-export",
"!**/dist",
"!**/package.json",
"!**/node_modules",
"!**/vendor",
"!**/stores/assets",
"!**/*.json"
]
},
Expand Down Expand Up @@ -44,7 +45,7 @@
"noNonNullAssertion": "off",
"useNumberNamespace": "off",
"useFilenamingConvention": {
"level": "error",
"level": "warn",
"options": {
"strictCase": true,
"requireAscii": true,
Expand Down
2 changes: 1 addition & 1 deletion src/AnyCadComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { GltfModel } from "./three-components/GltfModel"
import { JscadModel } from "./three-components/JscadModel"
import { MixedStlModel } from "./three-components/MixedStlModel"
import { StepModel } from "./three-components/StepModel"
import { ThreeErrorBoundary } from "./three-components/ThreeErrorBoundary"
import {
getCadLoaderTransformConfig,
getCadLoaderTransformMatrix,
Expand All @@ -25,7 +26,6 @@ import {
} from "./utils/get-cad-model-type"
import { resolveModelUrl } from "./utils/resolve-model-url"
import { tuple } from "./utils/tuple"
import { ThreeErrorBoundary } from "./three-components/ThreeErrorBoundary"

const ModelLoadErrorReporter = ({
error,
Expand Down
34 changes: 3 additions & 31 deletions src/BoardGeomBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import type {
PcbHole,
PcbPanel,
PcbPlatedHole,
PcbTrace,
PcbVia,
} from "circuit-json"
import type { GeomContext } from "./GeomContext"
Expand Down Expand Up @@ -68,11 +67,9 @@ const buildStateOrder: BuilderState[] = [
]

export class BoardGeomBuilder {
private circuitJson: AnyCircuitElement[]
private board: PcbBoard
private plated_holes: PcbPlatedHole[]
private holes: PcbHole[]
private traces: PcbTrace[]
private pcb_vias: PcbVia[]
private pcb_cutouts: PcbCutout[]

Expand All @@ -88,35 +85,10 @@ export class BoardGeomBuilder {
private onCompleteCallback?: (geoms: Geom3[]) => void
private finalGeoms: Geom3[] = []

private getHoleToCut(x: number, y: number): { diameter: number } | null {
const epsilon = M / 10
for (const via of this.pcb_vias) {
if (
Math.abs(via.x - x) < epsilon &&
Math.abs(via.y - y) < epsilon &&
via.hole_diameter
) {
return { diameter: via.hole_diameter }
}
}
for (const ph of this.plated_holes) {
if (ph.shape !== "circle") continue
if (
Math.abs(ph.x - x) < epsilon &&
Math.abs(ph.y - y) < epsilon &&
ph.hole_diameter
) {
return { diameter: ph.hole_diameter }
}
}
return null
}

constructor(
circuitJson: AnyCircuitElement[],
onComplete: (geoms: Geom3[]) => void,
) {
this.circuitJson = circuitJson
this.onCompleteCallback = onComplete

// Extract elements - check for panel first, then board
Expand Down Expand Up @@ -150,8 +122,8 @@ export class BoardGeomBuilder {

this.plated_holes = su(circuitJson).pcb_plated_hole.list()
this.holes = su(circuitJson).pcb_hole.list()
this.traces = su(circuitJson).pcb_trace.list()
this.pcb_vias = su(circuitJson).pcb_via.list()
const pcb_vias = su(circuitJson).pcb_via.list()
this.pcb_vias = pcb_vias
this.pcb_cutouts = su(circuitJson).pcb_cutout.list()

this.ctx = { pcbThickness: this.board.thickness ?? 1.2 }
Expand Down Expand Up @@ -589,7 +561,7 @@ export class BoardGeomBuilder {
if (!this.boardGeom) return

const holeDepth = this.ctx.pcbThickness * 1.5 // still cut through board fully
const copperInset = 0.02 // tiny offset for plated hole copper cut
const _copperInset = 0.02 // tiny offset for plated hole copper cut

if (hole.hole_shape === "circle") {
const cyGeom = cylinder({
Expand Down
30 changes: 15 additions & 15 deletions src/CadViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
import type React from "react"
import { useState, useCallback, useRef, useEffect } from "react"
import { useCallback, useEffect, useRef, useState } from "react"
import * as THREE from "three"

// Constants for camera initialization - defined once, reused across renders
const DEFAULT_TARGET = new THREE.Vector3(0, 0, 0)
const INITIAL_CAMERA_POSITION = [5, -5, 5] as const

import { CadViewerJscad } from "./CadViewerJscad"
import CadViewerManifold from "./CadViewerManifold"
import { useContextMenu } from "./hooks/useContextMenu"
import { useCameraPreset } from "./hooks/useCameraPreset"
import { useGlobalDownloadGltf } from "./hooks/useGlobalDownloadGltf"
import { ContextMenu } from "./components/ContextMenu"
import { KeyboardShortcutsDialog } from "./components/KeyboardShortcutsDialog"
import {
useRegisteredHotkey,
registerHotkeyViewer,
} from "./hooks/useRegisteredHotkey"
CameraControllerProvider,
useCameraController,
} from "./contexts/CameraControllerContext"
import {
LayerVisibilityProvider,
useLayerVisibility,
} from "./contexts/LayerVisibilityContext"
import {
CameraControllerProvider,
useCameraController,
} from "./contexts/CameraControllerContext"
import { ToastProvider, useToast } from "./contexts/ToastContext"
import { ContextMenu } from "./components/ContextMenu"
import { KeyboardShortcutsDialog } from "./components/KeyboardShortcutsDialog"
import type { CameraController, CameraPreset } from "./hooks/cameraAnimation"
import { useCameraPreset } from "./hooks/useCameraPreset"
import { useContextMenu } from "./hooks/useContextMenu"
import { useGlobalDownloadGltf } from "./hooks/useGlobalDownloadGltf"
import {
registerHotkeyViewer,
useRegisteredHotkey,
} from "./hooks/useRegisteredHotkey"

const CadViewerInner = (props: any) => {
const [engine, setEngine] = useState<"jscad" | "manifold">("manifold")
Expand All @@ -34,7 +34,7 @@ const CadViewerInner = (props: any) => {
useState(false)
const [autoRotate, setAutoRotate] = useState(() => {
const stored = window.localStorage.getItem("cadViewerAutoRotate")
return stored === "false" ? false : true
return stored !== "false"
})
const [autoRotateUserToggled, setAutoRotateUserToggled] = useState(() => {
const stored = window.localStorage.getItem("cadViewerAutoRotateUserToggled")
Expand Down
15 changes: 8 additions & 7 deletions src/CadViewerContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import type * as React from "react"
import { forwardRef, useEffect, useMemo, useState } from "react"
import * as THREE from "three"
import { zIndexMap } from "../lib/utils/z-index-map"
import packageJson from "../package.json"
import { useCameraController } from "./contexts/CameraControllerContext"
import type { CameraController } from "./hooks/cameraAnimation"
import { CameraAnimatorWithContext } from "./hooks/cameraAnimation"
import { useCameraSession } from "./hooks/useCameraSession"
import { Canvas } from "./react-three/Canvas"
import { OrbitControls } from "./react-three/OrbitControls"
import { Grid } from "./react-three/Grid"
import { useFrame, useThree } from "./react-three/ThreeContext"
import { Lights } from "./react-three/Lights"
import { CameraAnimatorWithContext } from "./hooks/cameraAnimation"
import { useCameraController } from "./contexts/CameraControllerContext"
import { useCameraSession } from "./hooks/useCameraSession"
import type { CameraController } from "./hooks/cameraAnimation"
import { OrbitControls } from "./react-three/OrbitControls"
import { useFrame, useThree } from "./react-three/ThreeContext"
import { OrientationCubeCanvas } from "./three-components/OrientationCubeCanvas"
import { zIndexMap } from "../lib/utils/z-index-map"

export type {
CameraController,
CameraPreset,
Expand Down
12 changes: 6 additions & 6 deletions src/CadViewerJscad.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import { useStlsFromGeom } from "./hooks/use-stls-from-geom"
import { useBoardGeomBuilder } from "./hooks/useBoardGeomBuilder"
import { usePcbThickness } from "./hooks/usePcbThickness"
import { Error3d } from "./three-components/Error3d"
import { VisibleSTLModel } from "./three-components/VisibleSTLModel"
import { ThreeErrorBoundary } from "./three-components/ThreeErrorBoundary"
import { JscadBoardTextures } from "./three-components/JscadBoardTextures"
import { ThreeErrorBoundary } from "./three-components/ThreeErrorBoundary"
import { VisibleSTLModel } from "./three-components/VisibleSTLModel"
import { addFauxBoardIfNeeded } from "./utils/preprocess-circuit-json"

interface Props {
Expand Down Expand Up @@ -88,7 +88,7 @@ export const CadViewerJscad = forwardRef<
try {
const board = su(internalCircuitJson as any).pcb_board.list()[0]
return !!board && board.pcb_board_id === "faux-board"
} catch (e) {
} catch (_e) {
return false
}
}, [internalCircuitJson])
Expand All @@ -109,7 +109,7 @@ export const CadViewerJscad = forwardRef<
if (!internalCircuitJson) return undefined
try {
const board = su(internalCircuitJson as any).pcb_board.list()[0]
if (!board || !board.center) return undefined
if (!board?.center) return undefined
return { x: board.center.x, y: board.center.y }
} catch (e) {
console.error(e)
Expand All @@ -120,7 +120,7 @@ export const CadViewerJscad = forwardRef<
const pcbThickness = usePcbThickness(internalCircuitJson)

// Use the state `boardGeom` which starts simplified and gets updated
const { stls: boardStls, loading } = useStlsFromGeom(boardGeom)
const { stls: boardStls } = useStlsFromGeom(boardGeom)

const cad_components = su(internalCircuitJson).cad_component.list()

Expand All @@ -137,7 +137,7 @@ export const CadViewerJscad = forwardRef<
>
{boardStls.map(({ stlData, color, layerType }, index) => (
<VisibleSTLModel
key={`board-${index}`}
key={layerType || index}
stlData={stlData}
color={color}
opacity={index === 0 ? (isFauxBoard ? 0.8 : 0.95) : 1}
Expand Down
6 changes: 5 additions & 1 deletion src/CadViewerManifold.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,11 @@ try {
isFauxBoard,
} = useManifoldBoardBuilder(manifoldJSModule, circuitJson, visibility)

const geometryMeshes = useMemo(() => createGeometryMeshes(geoms), [geoms])
const geometryMeshes = useMemo(
() => createGeometryMeshes(geoms, textures),
[geoms, textures],
)

const textureMeshes = useMemo(
() => createTextureMeshes(textures, boardData, pcbThickness, isFauxBoard),
[textures, boardData, pcbThickness, isFauxBoard],
Expand Down
5 changes: 3 additions & 2 deletions src/ContainerWithTooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect } from "react"
import type React from "react"
import { useEffect } from "react"
import type * as THREE from "three"
import { useHover } from "./react-three/HoverContext"
import * as THREE from "three"

const ContainerWithTooltip = ({
children,
Expand Down
6 changes: 3 additions & 3 deletions src/components/AppearanceMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
import type React from "react"
import { useState } from "react"
import { zIndexMap } from "../../lib/utils/z-index-map"
import { useLayerVisibility } from "../contexts/LayerVisibilityContext"
import type React from "react"
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
import { CheckIcon, ChevronRightIcon } from "./Icons"
import { zIndexMap } from "../../lib/utils/z-index-map"

const itemStyles: React.CSSProperties = {
padding: "6px 8px",
Expand Down
10 changes: 5 additions & 5 deletions src/components/ContextMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
import type React from "react"
import { useState } from "react"
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
import { AppearanceMenu } from "./AppearanceMenu"
import type { CameraPreset } from "../hooks/cameraAnimation"
import { useCameraController } from "../contexts/CameraControllerContext"
import { zIndexMap } from "../../lib/utils/z-index-map"
import packageJson from "../../package.json"
import { useCameraController } from "../contexts/CameraControllerContext"
import type { CameraPreset } from "../hooks/cameraAnimation"
import { AppearanceMenu } from "./AppearanceMenu"
import { CheckIcon, ChevronRightIcon, DotIcon } from "./Icons"
import { zIndexMap } from "../../lib/utils/z-index-map"

interface ContextMenuProps {
menuRef: React.RefObject<HTMLDivElement | null>
Expand Down
3 changes: 3 additions & 0 deletions src/components/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const CheckIcon = () => (
strokeLinecap="round"
strokeLinejoin="round"
>
<title>Check</title>
<path d="M20 6 9 17l-5-5" />
</svg>
)
Expand All @@ -33,6 +34,7 @@ export const ChevronRightIcon = ({ isOpen }: { isOpen: boolean }) => (
opacity: 0.6,
}}
>
<title>Chevron Right</title>
<path d="m9 18 6-6-6-6" />
</svg>
)
Expand All @@ -50,6 +52,7 @@ export const DotIcon = () => (
strokeLinejoin="round"
className="lucide lucide-dot-icon lucide-dot"
>
<title>Dot</title>
<circle cx="12.1" cy="12.1" r="4.5" fill="white" />
</svg>
)
1 change: 0 additions & 1 deletion src/contexts/CameraControllerContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ export const CameraControllerProvider: React.FC<
target: targetVector,
up: [0, 0, 1],
}
case "Custom":
default:
return null
}
Expand Down
8 changes: 4 additions & 4 deletions src/contexts/LayerVisibilityContext.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, {
import type React from "react"
import {
createContext,
useContext,
useState,
useEffect,
useCallback,
useContext,
useMemo,
useState,
} from "react"

export interface LayerVisibilityState {
Expand Down
4 changes: 2 additions & 2 deletions src/contexts/ToastContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react"
import { Toaster, toast as hotToast } from "react-hot-toast"
import type React from "react"
import { toast as hotToast, Toaster } from "react-hot-toast"

export const useToast = () => {
return {
Expand Down
Loading
Loading