@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.
Files changed (112) hide show
  1. package/.prettierrc +1 -0
  2. package/.storybook/main.js +15 -0
  3. package/.storybook/preview.js +9 -0
  4. package/README.md +26 -0
  5. package/ava.config.js +7 -0
  6. package/dist/Schematic.js +8606 -0
  7. package/dist/Schematic.js.map +1 -0
  8. package/dist/lib/hooks/index.js +2170 -0
  9. package/dist/lib/hooks/index.js.map +1 -0
  10. package/dist/lib/hooks/use-maybe-promise.js +2170 -0
  11. package/dist/lib/hooks/use-maybe-promise.js.map +1 -0
  12. package/dist/lib/render-context/index.js +45 -0
  13. package/dist/lib/render-context/index.js.map +1 -0
  14. package/dist/lib/types/core.js +18 -0
  15. package/dist/lib/types/core.js.map +1 -0
  16. package/dist/lib/types/index.js +18 -0
  17. package/dist/lib/types/index.js.map +1 -0
  18. package/dist/lib/types/route-solver.js +18 -0
  19. package/dist/lib/types/route-solver.js.map +1 -0
  20. package/dist/lib/types/source-component.js +18 -0
  21. package/dist/lib/types/source-component.js.map +1 -0
  22. package/dist/lib/types/util.js +18 -0
  23. package/dist/lib/types/util.js.map +1 -0
  24. package/dist/lib/utils/direction-to-vec.js +96 -0
  25. package/dist/lib/utils/direction-to-vec.js.map +1 -0
  26. package/dist/lib/utils/get-svg-path-bounds.js +51 -0
  27. package/dist/lib/utils/get-svg-path-bounds.js.map +1 -0
  28. package/dist/lib/utils/point-math.js +57 -0
  29. package/dist/lib/utils/point-math.js.map +1 -0
  30. package/dist/pages/_app.js +2714 -0
  31. package/dist/pages/_app.js.map +1 -0
  32. package/dist/pages/index.js +8612 -0
  33. package/dist/pages/index.js.map +1 -0
  34. package/dist/pages/led-circuit-react.js +2185 -0
  35. package/dist/pages/led-circuit-react.js.map +1 -0
  36. package/dist/pages/led-circuit.js +8656 -0
  37. package/dist/pages/led-circuit.js.map +1 -0
  38. package/dist/schematic-components/MovableGrid/MovableGrid.stories.js +47 -0
  39. package/dist/schematic-components/MovableGrid/MovableGrid.stories.js.map +1 -0
  40. package/dist/schematic-components/MovableGrid/index.js +34 -0
  41. package/dist/schematic-components/MovableGrid/index.js.map +1 -0
  42. package/dist/schematic-components/ProjectComponent.js +8584 -0
  43. package/dist/schematic-components/ProjectComponent.js.map +1 -0
  44. package/dist/schematic-components/RenderError.js +40 -0
  45. package/dist/schematic-components/RenderError.js.map +1 -0
  46. package/dist/schematic-components/SVGPathComponent.js +90 -0
  47. package/dist/schematic-components/SVGPathComponent.js.map +1 -0
  48. package/dist/schematic-components/SchematicBug.js +468 -0
  49. package/dist/schematic-components/SchematicBug.js.map +1 -0
  50. package/dist/schematic-components/SchematicComponent.js +8451 -0
  51. package/dist/schematic-components/SchematicComponent.js.map +1 -0
  52. package/dist/schematic-components/SchematicGroup.js +32 -0
  53. package/dist/schematic-components/SchematicGroup.js.map +1 -0
  54. package/dist/schematic-components/SchematicPort.js +8348 -0
  55. package/dist/schematic-components/SchematicPort.js.map +1 -0
  56. package/dist/schematic-components/SchematicText.js +71 -0
  57. package/dist/schematic-components/SchematicText.js.map +1 -0
  58. package/dist/schematic-components/SchematicTrace.js +137 -0
  59. package/dist/schematic-components/SchematicTrace.js.map +1 -0
  60. package/dist/schematic-components/SimpleCapacitor.js +103 -0
  61. package/dist/schematic-components/SimpleCapacitor.js.map +1 -0
  62. package/dist/schematic-components/SimpleDiode.js +101 -0
  63. package/dist/schematic-components/SimpleDiode.js.map +1 -0
  64. package/dist/schematic-components/SimpleGround.js +102 -0
  65. package/dist/schematic-components/SimpleGround.js.map +1 -0
  66. package/dist/schematic-components/SimpleInductor.js +102 -0
  67. package/dist/schematic-components/SimpleInductor.js.map +1 -0
  68. package/dist/schematic-components/SimplePowerSource.js +104 -0
  69. package/dist/schematic-components/SimplePowerSource.js.map +1 -0
  70. package/dist/schematic-components/SimpleResistor.js +102 -0
  71. package/dist/schematic-components/SimpleResistor.js.map +1 -0
  72. package/dist/schematic-components/index.js +8618 -0
  73. package/dist/schematic-components/index.js.map +1 -0
  74. package/next-env.d.ts +5 -0
  75. package/package.json +52 -0
  76. package/parsel.d.ts +81 -0
  77. package/src/Schematic.tsx +40 -0
  78. package/src/lib/hooks/index.ts +1 -0
  79. package/src/lib/hooks/use-maybe-promise.ts +14 -0
  80. package/src/lib/render-context/index.ts +15 -0
  81. package/src/lib/types/core.ts +179 -0
  82. package/src/lib/types/index.ts +4 -0
  83. package/src/lib/types/route-solver.ts +10 -0
  84. package/src/lib/types/source-component.ts +63 -0
  85. package/src/lib/types/util.ts +52 -0
  86. package/src/lib/utils/direction-to-vec.ts +50 -0
  87. package/src/lib/utils/get-svg-path-bounds.ts +22 -0
  88. package/src/lib/utils/point-math.ts +26 -0
  89. package/src/pages/_app.tsx +23 -0
  90. package/src/pages/index.tsx +10 -0
  91. package/src/pages/led-circuit-react.tsx +51 -0
  92. package/src/pages/led-circuit.tsx +91 -0
  93. package/src/schematic-components/MovableGrid/MovableGrid.stories.tsx +23 -0
  94. package/src/schematic-components/MovableGrid/index.tsx +4 -0
  95. package/src/schematic-components/ProjectComponent.tsx +62 -0
  96. package/src/schematic-components/RenderError.tsx +23 -0
  97. package/src/schematic-components/SVGPathComponent.tsx +64 -0
  98. package/src/schematic-components/SchematicBug.tsx +52 -0
  99. package/src/schematic-components/SchematicComponent.tsx +42 -0
  100. package/src/schematic-components/SchematicGroup.tsx +3 -0
  101. package/src/schematic-components/SchematicPort.tsx +39 -0
  102. package/src/schematic-components/SchematicText.tsx +41 -0
  103. package/src/schematic-components/SchematicTrace.tsx +48 -0
  104. package/src/schematic-components/SimpleCapacitor.tsx +29 -0
  105. package/src/schematic-components/SimpleDiode.tsx +38 -0
  106. package/src/schematic-components/SimpleGround.tsx +28 -0
  107. package/src/schematic-components/SimpleInductor.tsx +29 -0
  108. package/src/schematic-components/SimplePowerSource.tsx +30 -0
  109. package/src/schematic-components/SimpleResistor.tsx +28 -0
  110. package/src/schematic-components/index.tsx +17 -0
  111. package/tsconfig.json +31 -0
  112. package/tsconfig.tsbuildinfo +1 -0
package/next-env.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+
4
+ // NOTE: This file should not be edited
5
+ // see https://nextjs.org/docs/basic-features/typescript for more information.
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,4 @@
1
+ export * from "./core"
2
+ export * from "./source-component"
3
+ export * from "./util"
4
+ export * from "./route-solver"
@@ -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
@@ -0,0 +1,10 @@
1
+ import "@tscircuit/react-fiber/dist/types/intrinsic-jsx.d"
2
+ import { Schematic } from "Schematic"
3
+
4
+ export default () => {
5
+ return (
6
+ <Schematic>
7
+ <resistor name="R1" resistance="10 ohm" />
8
+ </Schematic>
9
+ )
10
+ }