@tscircuit/schematic-viewer 0.0.1
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/.prettierrc +1 -0
- package/.storybook/main.js +15 -0
- package/.storybook/preview.js +9 -0
- package/README.md +26 -0
- package/ava.config.js +7 -0
- package/dist/Schematic.js +8606 -0
- package/dist/Schematic.js.map +1 -0
- package/dist/lib/hooks/index.js +2170 -0
- package/dist/lib/hooks/index.js.map +1 -0
- package/dist/lib/hooks/use-maybe-promise.js +2170 -0
- package/dist/lib/hooks/use-maybe-promise.js.map +1 -0
- package/dist/lib/render-context/index.js +45 -0
- package/dist/lib/render-context/index.js.map +1 -0
- package/dist/lib/types/core.js +18 -0
- package/dist/lib/types/core.js.map +1 -0
- package/dist/lib/types/index.js +18 -0
- package/dist/lib/types/index.js.map +1 -0
- package/dist/lib/types/route-solver.js +18 -0
- package/dist/lib/types/route-solver.js.map +1 -0
- package/dist/lib/types/source-component.js +18 -0
- package/dist/lib/types/source-component.js.map +1 -0
- package/dist/lib/types/util.js +18 -0
- package/dist/lib/types/util.js.map +1 -0
- package/dist/lib/utils/direction-to-vec.js +96 -0
- package/dist/lib/utils/direction-to-vec.js.map +1 -0
- package/dist/lib/utils/get-svg-path-bounds.js +51 -0
- package/dist/lib/utils/get-svg-path-bounds.js.map +1 -0
- package/dist/lib/utils/point-math.js +57 -0
- package/dist/lib/utils/point-math.js.map +1 -0
- package/dist/pages/_app.js +2714 -0
- package/dist/pages/_app.js.map +1 -0
- package/dist/pages/index.js +8612 -0
- package/dist/pages/index.js.map +1 -0
- package/dist/pages/led-circuit-react.js +2185 -0
- package/dist/pages/led-circuit-react.js.map +1 -0
- package/dist/pages/led-circuit.js +8656 -0
- package/dist/pages/led-circuit.js.map +1 -0
- package/dist/schematic-components/MovableGrid/MovableGrid.stories.js +47 -0
- package/dist/schematic-components/MovableGrid/MovableGrid.stories.js.map +1 -0
- package/dist/schematic-components/MovableGrid/index.js +34 -0
- package/dist/schematic-components/MovableGrid/index.js.map +1 -0
- package/dist/schematic-components/ProjectComponent.js +8584 -0
- package/dist/schematic-components/ProjectComponent.js.map +1 -0
- package/dist/schematic-components/RenderError.js +40 -0
- package/dist/schematic-components/RenderError.js.map +1 -0
- package/dist/schematic-components/SVGPathComponent.js +90 -0
- package/dist/schematic-components/SVGPathComponent.js.map +1 -0
- package/dist/schematic-components/SchematicBug.js +468 -0
- package/dist/schematic-components/SchematicBug.js.map +1 -0
- package/dist/schematic-components/SchematicComponent.js +8451 -0
- package/dist/schematic-components/SchematicComponent.js.map +1 -0
- package/dist/schematic-components/SchematicGroup.js +32 -0
- package/dist/schematic-components/SchematicGroup.js.map +1 -0
- package/dist/schematic-components/SchematicPort.js +8348 -0
- package/dist/schematic-components/SchematicPort.js.map +1 -0
- package/dist/schematic-components/SchematicText.js +71 -0
- package/dist/schematic-components/SchematicText.js.map +1 -0
- package/dist/schematic-components/SchematicTrace.js +137 -0
- package/dist/schematic-components/SchematicTrace.js.map +1 -0
- package/dist/schematic-components/SimpleCapacitor.js +103 -0
- package/dist/schematic-components/SimpleCapacitor.js.map +1 -0
- package/dist/schematic-components/SimpleDiode.js +101 -0
- package/dist/schematic-components/SimpleDiode.js.map +1 -0
- package/dist/schematic-components/SimpleGround.js +102 -0
- package/dist/schematic-components/SimpleGround.js.map +1 -0
- package/dist/schematic-components/SimpleInductor.js +102 -0
- package/dist/schematic-components/SimpleInductor.js.map +1 -0
- package/dist/schematic-components/SimplePowerSource.js +104 -0
- package/dist/schematic-components/SimplePowerSource.js.map +1 -0
- package/dist/schematic-components/SimpleResistor.js +102 -0
- package/dist/schematic-components/SimpleResistor.js.map +1 -0
- package/dist/schematic-components/index.js +8618 -0
- package/dist/schematic-components/index.js.map +1 -0
- package/next-env.d.ts +5 -0
- package/package.json +52 -0
- package/parsel.d.ts +81 -0
- package/src/Schematic.tsx +40 -0
- package/src/lib/hooks/index.ts +1 -0
- package/src/lib/hooks/use-maybe-promise.ts +14 -0
- package/src/lib/render-context/index.ts +15 -0
- package/src/lib/types/core.ts +179 -0
- package/src/lib/types/index.ts +4 -0
- package/src/lib/types/route-solver.ts +10 -0
- package/src/lib/types/source-component.ts +63 -0
- package/src/lib/types/util.ts +52 -0
- package/src/lib/utils/direction-to-vec.ts +50 -0
- package/src/lib/utils/get-svg-path-bounds.ts +22 -0
- package/src/lib/utils/point-math.ts +26 -0
- package/src/pages/_app.tsx +23 -0
- package/src/pages/index.tsx +10 -0
- package/src/pages/led-circuit-react.tsx +51 -0
- package/src/pages/led-circuit.tsx +91 -0
- package/src/schematic-components/MovableGrid/MovableGrid.stories.tsx +23 -0
- package/src/schematic-components/MovableGrid/index.tsx +4 -0
- package/src/schematic-components/ProjectComponent.tsx +62 -0
- package/src/schematic-components/RenderError.tsx +23 -0
- package/src/schematic-components/SVGPathComponent.tsx +64 -0
- package/src/schematic-components/SchematicBug.tsx +52 -0
- package/src/schematic-components/SchematicComponent.tsx +42 -0
- package/src/schematic-components/SchematicGroup.tsx +3 -0
- package/src/schematic-components/SchematicPort.tsx +39 -0
- package/src/schematic-components/SchematicText.tsx +41 -0
- package/src/schematic-components/SchematicTrace.tsx +48 -0
- package/src/schematic-components/SimpleCapacitor.tsx +29 -0
- package/src/schematic-components/SimpleDiode.tsx +38 -0
- package/src/schematic-components/SimpleGround.tsx +28 -0
- package/src/schematic-components/SimpleInductor.tsx +29 -0
- package/src/schematic-components/SimplePowerSource.tsx +30 -0
- package/src/schematic-components/SimpleResistor.tsx +28 -0
- package/src/schematic-components/index.tsx +17 -0
- package/tsconfig.json +31 -0
- package/tsconfig.tsbuildinfo +1 -0
package/next-env.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tscircuit/schematic-viewer",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "next dev",
|
|
8
|
+
"typecheck": "tsc --noEmit",
|
|
9
|
+
"build": "tsup ./src --dts --sourcemap",
|
|
10
|
+
"yalc": "npm run build && yalc push"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@babel/core": "^7.18.9",
|
|
14
|
+
"@storybook/addon-actions": "^6.5.9",
|
|
15
|
+
"@storybook/addon-essentials": "^6.5.9",
|
|
16
|
+
"@storybook/addon-interactions": "^6.5.9",
|
|
17
|
+
"@storybook/addon-links": "^6.5.9",
|
|
18
|
+
"@storybook/builder-webpack5": "^6.5.9",
|
|
19
|
+
"@storybook/manager-webpack5": "^6.5.9",
|
|
20
|
+
"@storybook/react": "^6.5.9",
|
|
21
|
+
"@storybook/testing-library": "^0.0.13",
|
|
22
|
+
"@types/node": "^18.6.0",
|
|
23
|
+
"@types/react": "^18.0.15",
|
|
24
|
+
"ava": "^4.3.1",
|
|
25
|
+
"babel-loader": "^8.2.5",
|
|
26
|
+
"esbuild": "^0.15.10",
|
|
27
|
+
"esbuild-register": "^3.3.3",
|
|
28
|
+
"next": "^12.2.3",
|
|
29
|
+
"react": "^18.2.0",
|
|
30
|
+
"react-dom": "^18.2.0",
|
|
31
|
+
"tsup": "^6.2.3",
|
|
32
|
+
"type-fest": "^2.17.0",
|
|
33
|
+
"typescript": "^4.8.4"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@chakra-ui/react": "^2.2.4",
|
|
37
|
+
"@emotion/react": "^11",
|
|
38
|
+
"@emotion/styled": "^11",
|
|
39
|
+
"@tscircuit/react-fiber": "^0.0.5",
|
|
40
|
+
"framer-motion": "^6",
|
|
41
|
+
"parse-svg-path": "^0.1.2",
|
|
42
|
+
"parsel-js": "^1.0.2",
|
|
43
|
+
"react-no-ssr": "^1.1.0",
|
|
44
|
+
"react-use-measure": "^2.1.1",
|
|
45
|
+
"rectilinear-router": "^1.0.1",
|
|
46
|
+
"svg-path-bounds": "^1.0.2",
|
|
47
|
+
"svg-path-generator": "^1.1.0",
|
|
48
|
+
"transformation-matrix": "^2.12.0",
|
|
49
|
+
"tscircuit": "^0.0.3",
|
|
50
|
+
"zustand": "^4.0.0"
|
|
51
|
+
}
|
|
52
|
+
}
|
package/parsel.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
declare module "parsel-js" {
|
|
2
|
+
export interface Tokens {
|
|
3
|
+
type:
|
|
4
|
+
| "class"
|
|
5
|
+
| "attribute"
|
|
6
|
+
| "id"
|
|
7
|
+
| "type"
|
|
8
|
+
| "pseudo-element"
|
|
9
|
+
| "pseudo-class"
|
|
10
|
+
| "comma"
|
|
11
|
+
| "combinator"
|
|
12
|
+
content: string
|
|
13
|
+
name: string
|
|
14
|
+
namespace?: string
|
|
15
|
+
value?: string
|
|
16
|
+
pos: [number, number]
|
|
17
|
+
operator?: string
|
|
18
|
+
argument?: string
|
|
19
|
+
subtree?: AST
|
|
20
|
+
caseSensitive?: "i"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface Complex {
|
|
24
|
+
type: "complex"
|
|
25
|
+
combinator: string
|
|
26
|
+
right: AST
|
|
27
|
+
left: AST
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface Compound {
|
|
31
|
+
type: "compound"
|
|
32
|
+
list: Tokens[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface List {
|
|
36
|
+
type: "list"
|
|
37
|
+
list: AST[]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ParserOptions {
|
|
41
|
+
recursive?: boolean
|
|
42
|
+
list?: boolean
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface SpecificityOptions {
|
|
46
|
+
format?: string
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type AST = Complex | Compound | List | Tokens
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get AST:
|
|
53
|
+
*/
|
|
54
|
+
export function parse(selector: string, options?: ParserOptions): AST
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get list of tokens as a flat array:
|
|
58
|
+
*/
|
|
59
|
+
export function tokenize(selector: string): Tokens[]
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Traverse all tokens of a (sub)tree:
|
|
63
|
+
*/
|
|
64
|
+
export function walk(node: AST, cb: (node: AST, parentNode: AST) => {}): void
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Calculate specificity (returns an array of 3 numbers):
|
|
68
|
+
*/
|
|
69
|
+
export function specificity(
|
|
70
|
+
selector: string | AST,
|
|
71
|
+
options?: SpecificityOptions
|
|
72
|
+
): number[]
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* To convert the specificity array to a number
|
|
76
|
+
*/
|
|
77
|
+
export function specificityToNumber(
|
|
78
|
+
specificity: number[],
|
|
79
|
+
base?: number
|
|
80
|
+
): number
|
|
81
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useEffect, useState } from "react"
|
|
2
|
+
import { ProjectComponent } from "schematic-components"
|
|
3
|
+
import {
|
|
4
|
+
createProjectBuilder,
|
|
5
|
+
createProjectFromElements,
|
|
6
|
+
} from "@tscircuit/builder"
|
|
7
|
+
import { createRoot } from "@tscircuit/react-fiber"
|
|
8
|
+
|
|
9
|
+
export const Schematic = ({
|
|
10
|
+
children,
|
|
11
|
+
elements: initialElements = [],
|
|
12
|
+
}: {
|
|
13
|
+
children?: any
|
|
14
|
+
elements?: any
|
|
15
|
+
}) => {
|
|
16
|
+
const [elements, setElements] = useState<any>(initialElements)
|
|
17
|
+
const [project, setProject] = useState<any>(null)
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (initialElements.length > 0) {
|
|
21
|
+
setProject(createProjectFromElements(initialElements))
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
const projectBuilder = createProjectBuilder()
|
|
25
|
+
createRoot()
|
|
26
|
+
.render(children, projectBuilder as any)
|
|
27
|
+
.then(async (elements) => {
|
|
28
|
+
setElements(elements)
|
|
29
|
+
setProject(createProjectFromElements(elements))
|
|
30
|
+
})
|
|
31
|
+
.catch((e) => {
|
|
32
|
+
console.error("ERROR RENDERING CIRCUIT")
|
|
33
|
+
throw e
|
|
34
|
+
})
|
|
35
|
+
}, [children])
|
|
36
|
+
|
|
37
|
+
if (elements.length === 0) return null
|
|
38
|
+
|
|
39
|
+
return <ProjectComponent project={project} />
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./use-maybe-promise"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect, useState } from "react"
|
|
2
|
+
|
|
3
|
+
export const useMaybePromise = <T>(promise: Promise<T> | T): T | null => {
|
|
4
|
+
const [state, setState] = useState<T | null>(null)
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
if (promise instanceof Promise) {
|
|
7
|
+
promise.then(setState)
|
|
8
|
+
} else {
|
|
9
|
+
setState(promise)
|
|
10
|
+
}
|
|
11
|
+
}, [promise])
|
|
12
|
+
return state
|
|
13
|
+
}
|
|
14
|
+
export default useMaybePromise
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import createStore from "zustand"
|
|
2
|
+
import { Matrix, compose, scale } from "transformation-matrix"
|
|
3
|
+
|
|
4
|
+
interface RenderContextState {
|
|
5
|
+
camera_transform: Matrix
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const useRenderContext = createStore<RenderContextState>()(
|
|
9
|
+
(set, get) => ({
|
|
10
|
+
camera_transform: compose(scale(100, 100, 0, 0)),
|
|
11
|
+
})
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
export const useCameraTransform = () =>
|
|
15
|
+
useRenderContext((s) => s.camera_transform)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { SourceComponent } from "./source-component"
|
|
2
|
+
|
|
3
|
+
export interface SchematicConfig {
|
|
4
|
+
type: "schematic_config"
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface Point {
|
|
8
|
+
x: number
|
|
9
|
+
y: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface Size {
|
|
13
|
+
width: number
|
|
14
|
+
height: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface SourceConfig {
|
|
18
|
+
type: "source_config"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SchematicGroup {
|
|
22
|
+
type: "schematic_group"
|
|
23
|
+
schematic_group_id: string
|
|
24
|
+
source_group_id: string
|
|
25
|
+
center: Point
|
|
26
|
+
size: Size
|
|
27
|
+
children_schematic_component_ids: string[]
|
|
28
|
+
children_schematic_trace_ids: string[]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SchematicComponent {
|
|
32
|
+
type: "schematic_component"
|
|
33
|
+
rotation: number
|
|
34
|
+
size: Size
|
|
35
|
+
center: Point
|
|
36
|
+
source_component_id: string
|
|
37
|
+
schematic_component_id: string
|
|
38
|
+
|
|
39
|
+
// TODO only for schematic-bug
|
|
40
|
+
port_arrangement?: {
|
|
41
|
+
left_size: number
|
|
42
|
+
right_size: number
|
|
43
|
+
top_size?: number
|
|
44
|
+
bottom_size?: number
|
|
45
|
+
}
|
|
46
|
+
port_labels?: {
|
|
47
|
+
[port_number: string]: string
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SchematicTrace {
|
|
52
|
+
type: "schematic_trace"
|
|
53
|
+
schematic_trace_id: string
|
|
54
|
+
source_trace_id: string
|
|
55
|
+
edges: Array<{
|
|
56
|
+
from: { x: number; y: number }
|
|
57
|
+
to: { x: number; y: number }
|
|
58
|
+
from_schematic_port_id?: string
|
|
59
|
+
to_schematic_port_id?: string
|
|
60
|
+
}>
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface SchematicText {
|
|
64
|
+
type: "schematic_text"
|
|
65
|
+
schematic_component_id: string
|
|
66
|
+
schematic_text_id: string
|
|
67
|
+
text: string
|
|
68
|
+
position: Point
|
|
69
|
+
anchor: "center" | "left" | "right" | "top" | "bottom"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface SchematicPort {
|
|
73
|
+
type: "schematic_port"
|
|
74
|
+
schematic_port_id: string
|
|
75
|
+
source_port_id: string
|
|
76
|
+
center: Point
|
|
77
|
+
facing_direction?: "up" | "down" | "left" | "right"
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface PCBTrace {
|
|
81
|
+
type: "pcb_trace"
|
|
82
|
+
source_trace_id: string
|
|
83
|
+
pcb_trace_id: string
|
|
84
|
+
route: Array<{
|
|
85
|
+
x: number
|
|
86
|
+
y: number
|
|
87
|
+
strokeWidth: number
|
|
88
|
+
cap: "butt" | "round" | "square"
|
|
89
|
+
start_pcb_port_id?: string
|
|
90
|
+
end_pcb_port_id?: string
|
|
91
|
+
}>
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface PCBComponent {
|
|
95
|
+
type: "pcb_component"
|
|
96
|
+
pcb_component_id: string
|
|
97
|
+
source_component_id: string
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface PCBPort {
|
|
101
|
+
type: "pcb_port"
|
|
102
|
+
pcb_port_id: string
|
|
103
|
+
source_port_id: string
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface PCBGroup {
|
|
107
|
+
type: "pcb_group"
|
|
108
|
+
source_group_id: string
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface PCBConfig {
|
|
112
|
+
type: "pcb_config"
|
|
113
|
+
dimension_unit: "mm"
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface SourceTrace {
|
|
117
|
+
type: "source_trace"
|
|
118
|
+
source_trace_id: string
|
|
119
|
+
connected_source_port_ids: string[]
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface SourceGroup {
|
|
123
|
+
type: "source_group"
|
|
124
|
+
source_group_id: string
|
|
125
|
+
name: string
|
|
126
|
+
children_source_component_ids: string[]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface SourcePort {
|
|
130
|
+
type: "source_port"
|
|
131
|
+
name: string
|
|
132
|
+
source_port_id: string
|
|
133
|
+
source_component_id: string
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface Project {
|
|
137
|
+
type: "project"
|
|
138
|
+
schematic_config: SchematicConfig
|
|
139
|
+
schematic_components: SchematicComponent[]
|
|
140
|
+
schematic_groups: SchematicGroup[]
|
|
141
|
+
schematic_traces: SchematicTrace[]
|
|
142
|
+
schematic_texts: SchematicText[]
|
|
143
|
+
schematic_ports: SchematicPort[]
|
|
144
|
+
pcb_config: PCBConfig
|
|
145
|
+
pcb_groups: PCBGroup[]
|
|
146
|
+
pcb_components: PCBComponent[]
|
|
147
|
+
pcb_traces: PCBTrace[]
|
|
148
|
+
pcb_ports: PCBPort[]
|
|
149
|
+
source_config: SourceConfig
|
|
150
|
+
source_traces: SourceTrace[]
|
|
151
|
+
source_groups: SourceGroup[]
|
|
152
|
+
source_components: SourceComponent[]
|
|
153
|
+
source_ports: SourcePort[]
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export type AnyElement =
|
|
157
|
+
| Project
|
|
158
|
+
| SourceConfig
|
|
159
|
+
| SourceComponent
|
|
160
|
+
| SourceGroup
|
|
161
|
+
| SourceTrace
|
|
162
|
+
| SourcePort
|
|
163
|
+
| PCBTrace
|
|
164
|
+
| PCBComponent
|
|
165
|
+
| PCBGroup
|
|
166
|
+
| PCBConfig
|
|
167
|
+
| PCBPort
|
|
168
|
+
| SchematicGroup
|
|
169
|
+
| SchematicComponent
|
|
170
|
+
| SchematicTrace
|
|
171
|
+
| SchematicConfig
|
|
172
|
+
| SchematicPort
|
|
173
|
+
| SchematicText
|
|
174
|
+
|
|
175
|
+
export type ElementType = AnyElement["type"]
|
|
176
|
+
export type ElementOfType<T extends ElementType> = Extract<
|
|
177
|
+
AnyElement,
|
|
178
|
+
{ type: T }
|
|
179
|
+
>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type RouteSolver = (params: {
|
|
2
|
+
terminals: Array<{
|
|
3
|
+
x: number
|
|
4
|
+
y: number
|
|
5
|
+
facing_direction?: "up" | "down" | "left" | "right"
|
|
6
|
+
}>
|
|
7
|
+
obstacles: Array<{ cx: number; cy: number; w: number; h: number }>
|
|
8
|
+
}) => Promise<
|
|
9
|
+
Array<{ from: { x: number; y: number }; to: { x: number; y: number } }>
|
|
10
|
+
>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { NumberWithUnit } from "./util"
|
|
2
|
+
|
|
3
|
+
export interface SourceComponentBase {
|
|
4
|
+
type: "source_component"
|
|
5
|
+
/** The functional type of this component, e.g. resistor, capacitor etc. */
|
|
6
|
+
ftype?: string
|
|
7
|
+
source_component_id: string
|
|
8
|
+
name: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface SimpleResistor extends SourceComponentBase {
|
|
12
|
+
ftype: "simple_resistor"
|
|
13
|
+
// Resistance measured in ohms
|
|
14
|
+
resistance: NumberWithUnit<"ohm">
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface SimpleCapacitor extends SourceComponentBase {
|
|
18
|
+
ftype: "simple_capacitor"
|
|
19
|
+
// Capacitance measured in farads
|
|
20
|
+
capacitance: NumberWithUnit<"farad">
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface SimpleInductor extends SourceComponentBase {
|
|
24
|
+
ftype: "simple_inductor"
|
|
25
|
+
// Inductance measured in henries
|
|
26
|
+
inductance: NumberWithUnit<"henry">
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface SimpleDiode extends SourceComponentBase {
|
|
30
|
+
ftype: "simple_diode"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type LightEmittingDiode = SimpleDiode & {
|
|
34
|
+
ftype: "led"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface SimpleBug extends SourceComponentBase {
|
|
38
|
+
ftype: "simple_bug"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SimplePowerSource extends SourceComponentBase {
|
|
42
|
+
ftype: "simple_power_source"
|
|
43
|
+
voltage: NumberWithUnit<"volt">
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface SimpleGround extends SourceComponentBase {
|
|
47
|
+
ftype: "simple_ground"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type AnySourceComponent =
|
|
51
|
+
| SimpleResistor
|
|
52
|
+
| SimpleCapacitor
|
|
53
|
+
| SimpleBug
|
|
54
|
+
| SimpleInductor
|
|
55
|
+
| SimplePowerSource
|
|
56
|
+
| SimpleGround
|
|
57
|
+
| SimpleDiode
|
|
58
|
+
| LightEmittingDiode
|
|
59
|
+
|
|
60
|
+
export type SourceComponentFType = AnySourceComponent["ftype"]
|
|
61
|
+
export type SourceComponent<
|
|
62
|
+
T extends SourceComponentFType = SourceComponentFType
|
|
63
|
+
> = Extract<AnySourceComponent, { ftype: T }>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Currently, removing uncommon SI Prefixes for type simplicity.
|
|
2
|
+
export type SIPrefix =
|
|
3
|
+
// | "y"
|
|
4
|
+
// | "yocto"
|
|
5
|
+
// | "z"
|
|
6
|
+
// | "zepto"
|
|
7
|
+
// | "atto"
|
|
8
|
+
// | "a"
|
|
9
|
+
| "femto"
|
|
10
|
+
| "f"
|
|
11
|
+
| "u"
|
|
12
|
+
| "micro"
|
|
13
|
+
// | "d"
|
|
14
|
+
// | "deci"
|
|
15
|
+
| "c"
|
|
16
|
+
| "centi"
|
|
17
|
+
| "m"
|
|
18
|
+
| "milli"
|
|
19
|
+
| "k"
|
|
20
|
+
| "kilo"
|
|
21
|
+
| "M"
|
|
22
|
+
| "mega"
|
|
23
|
+
// | "G"
|
|
24
|
+
// | "T"
|
|
25
|
+
// | "P"
|
|
26
|
+
// | "E"
|
|
27
|
+
// | "Z"
|
|
28
|
+
// | "Y"
|
|
29
|
+
|
|
30
|
+
export type UnitAbbreviations = {
|
|
31
|
+
farad: "F"
|
|
32
|
+
ohm: "Ω"
|
|
33
|
+
henry: "H"
|
|
34
|
+
meter: "m"
|
|
35
|
+
volt: "V"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type Unit = "ohm" | "farad" | "henry" | "meter" | "volt"
|
|
39
|
+
|
|
40
|
+
export type UnitOrAbbreviation = UnitAbbreviations[Unit] | Unit
|
|
41
|
+
|
|
42
|
+
export type NumberWithAnyUnit =
|
|
43
|
+
| `${number}${UnitOrAbbreviation}`
|
|
44
|
+
| `${number} ${UnitOrAbbreviation}`
|
|
45
|
+
| `${number}${SIPrefix}${UnitOrAbbreviation}`
|
|
46
|
+
| `${number} ${SIPrefix}${UnitOrAbbreviation}`
|
|
47
|
+
|
|
48
|
+
export type NumberWithUnit<T extends Unit> =
|
|
49
|
+
| `${number}${T | UnitAbbreviations[T]}`
|
|
50
|
+
| `${number} ${T | UnitAbbreviations[T]}`
|
|
51
|
+
| `${number}${SIPrefix}${T | UnitAbbreviations[T]}`
|
|
52
|
+
| `${number} ${SIPrefix}${T | UnitAbbreviations[T]}`
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const directionToVec = (direction: "up" | "down" | "left" | "right") => {
|
|
2
|
+
if (direction === "up") return { x: 0, y: -1 }
|
|
3
|
+
else if (direction === "down") return { x: 0, y: 1 }
|
|
4
|
+
else if (direction === "left") return { x: -1, y: 0 }
|
|
5
|
+
else if (direction === "right") return { x: 1, y: 0 }
|
|
6
|
+
else throw new Error("Invalid direction")
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const vecToDirection = ({ x, y }: { x: number; y: number }) => {
|
|
10
|
+
if (x > y) y = 0
|
|
11
|
+
if (y > x) x = 0
|
|
12
|
+
if (x > 0 && y === 0) return "right"
|
|
13
|
+
else if (x < 0 && y === 0) return "left"
|
|
14
|
+
else if (x === 0 && y > 0) return "down"
|
|
15
|
+
else if (x === 0 && y < 0) return "up"
|
|
16
|
+
else throw new Error(`Invalid vector for direction conversion (${x}, ${y})`)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const rotateClockwise = (
|
|
20
|
+
direction: "up" | "down" | "left" | "right"
|
|
21
|
+
) => {
|
|
22
|
+
if (direction === "up") return "right"
|
|
23
|
+
else if (direction === "right") return "down"
|
|
24
|
+
else if (direction === "down") return "left"
|
|
25
|
+
else if (direction === "left") return "up"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const rotateCounterClockwise = (
|
|
29
|
+
direction: "up" | "down" | "left" | "right"
|
|
30
|
+
) => {
|
|
31
|
+
if (direction === "up") return "left"
|
|
32
|
+
else if (direction === "left") return "down"
|
|
33
|
+
else if (direction === "down") return "right"
|
|
34
|
+
else if (direction === "right") return "up"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const rotateDirection = (
|
|
38
|
+
direction: "up" | "down" | "left" | "right",
|
|
39
|
+
num90DegreeClockwiseTurns: number
|
|
40
|
+
) => {
|
|
41
|
+
while (num90DegreeClockwiseTurns > 0) {
|
|
42
|
+
direction = rotateClockwise(direction)
|
|
43
|
+
num90DegreeClockwiseTurns--
|
|
44
|
+
}
|
|
45
|
+
while (num90DegreeClockwiseTurns < 0) {
|
|
46
|
+
direction = rotateCounterClockwise(direction)
|
|
47
|
+
num90DegreeClockwiseTurns++
|
|
48
|
+
}
|
|
49
|
+
return direction
|
|
50
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import svgPathBounds from "svg-path-bounds"
|
|
2
|
+
|
|
3
|
+
export function getSVGPathBounds(ds: string[] | string) {
|
|
4
|
+
if (typeof ds === "string") ds = [ds]
|
|
5
|
+
let minX = Infinity,
|
|
6
|
+
maxX = -Infinity,
|
|
7
|
+
minY = Infinity,
|
|
8
|
+
maxY = -Infinity
|
|
9
|
+
|
|
10
|
+
for (const d of ds) {
|
|
11
|
+
const [left, top, right, bottom] = svgPathBounds(d)
|
|
12
|
+
|
|
13
|
+
minX = Math.min(left, minX)
|
|
14
|
+
maxX = Math.max(right, maxX)
|
|
15
|
+
minY = Math.min(top, minY)
|
|
16
|
+
maxY = Math.max(bottom, maxY)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return { minX, maxX, minY, maxY, width: maxX - minX, height: maxY - minY }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default getSVGPathBounds
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type Point = { x: number; y: number }
|
|
2
|
+
|
|
3
|
+
export function sub(p1: Point, p2: Point) {
|
|
4
|
+
return { x: p1.x - p2.x, y: p1.y - p2.y }
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function mult(p1: Point, p2: Point) {
|
|
8
|
+
return { x: p1.x * p2.x, y: p1.y * p2.y }
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function mag(p1: Point, p2: Point) {
|
|
12
|
+
const dx = p1.x - p2.x
|
|
13
|
+
const dy = p1.y - p2.y
|
|
14
|
+
return Math.sqrt(dx ** 2 + dy ** 2)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function componentSum(p1: Point) {
|
|
18
|
+
return p1.x + p1.y
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function norm(p1: Point) {
|
|
22
|
+
return {
|
|
23
|
+
x: Math.sign(p1.x),
|
|
24
|
+
y: Math.sign(p1.y),
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Head from "next/head"
|
|
2
|
+
|
|
3
|
+
export const App = ({ Component }) => {
|
|
4
|
+
return (
|
|
5
|
+
<>
|
|
6
|
+
<Head>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
|
+
<link
|
|
9
|
+
rel="preconnect"
|
|
10
|
+
href="https://fonts.gstatic.com"
|
|
11
|
+
crossOrigin="anonymous"
|
|
12
|
+
/>
|
|
13
|
+
<link
|
|
14
|
+
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&display=swap"
|
|
15
|
+
rel="stylesheet"
|
|
16
|
+
/>
|
|
17
|
+
</Head>
|
|
18
|
+
<Component />
|
|
19
|
+
</>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default App
|