@grayhaven/nerve-react 0.5.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.
@@ -0,0 +1,13 @@
1
+ // src/jsx-runtime.ts
2
+ var jsx = (type, props) => type(props);
3
+ var jsxs = jsx;
4
+ var jsxDEV = (type, props) => type(props);
5
+ var Fragment = (props) => props.children;
6
+
7
+ export {
8
+ jsx,
9
+ jsxs,
10
+ jsxDEV,
11
+ Fragment
12
+ };
13
+ //# sourceMappingURL=chunk-IBL3BQIP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/jsx-runtime.ts"],"sourcesContent":["/**\n * Custom JSX runtime (automatic mode): no React, no fiber, no VDOM —\n * `jsx(Component, props)` simply CALLS the component. JSX becomes pure\n * function application over the typed DSL, so authoring style changes\n * and nothing else does.\n */\nexport type JsxComponent<P, R> = (props: P) => R\n\nexport const jsx = <P, R>(type: JsxComponent<P, R>, props: P): R => type(props)\nexport const jsxs = jsx\nexport const jsxDEV = <P, R>(type: JsxComponent<P, R>, props: P): R => type(props)\n\nexport const Fragment = (props: { children?: unknown }): unknown => props.children\n\n// Minimal JSX namespace: components only (no intrinsic lowercase elements —\n// <Harness> not <harness>, keeping every element a typed function).\ndeclare global {\n namespace JSX {\n // Element is intentionally loose (each component returns its own def\n // type); ElementType constrains elements to component FUNCTIONS.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n type Element = any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n type ElementType = (props: any) => unknown\n interface ElementChildrenAttribute {\n children: unknown\n }\n interface IntrinsicElements {\n [k: string]: never\n }\n }\n}\n"],"mappings":";AAQO,IAAM,MAAM,CAAO,MAA0B,UAAgB,KAAK,KAAK;AACvE,IAAM,OAAO;AACb,IAAM,SAAS,CAAO,MAA0B,UAAgB,KAAK,KAAK;AAE1E,IAAM,WAAW,CAAC,UAA2C,MAAM;","names":[]}
@@ -0,0 +1,40 @@
1
+ import * as _grayhaven_nerve from '@grayhaven/nerve';
2
+ import { BranchProps, CableProps, connector, wire, branch, label, splice, cable, ConnectorPart, PinAssignments, PinPartAssignment, HarnessDesign, LabelProps, SpliceProps, WireProps } from '@grayhaven/nerve';
3
+ export { Fragment, jsx, jsxs } from './jsx-runtime.js';
4
+
5
+ type Def = ReturnType<typeof connector | typeof wire | typeof branch | typeof label | typeof splice | typeof cable>;
6
+ type Children = Def | ReadonlyArray<Children> | undefined | null | false;
7
+ declare function Connector(props: {
8
+ ref: string;
9
+ part: ConnectorPart;
10
+ pins: PinAssignments;
11
+ terminals?: PinPartAssignment;
12
+ seals?: PinPartAssignment;
13
+ }): _grayhaven_nerve.ConnectorInstance;
14
+ declare function Wire(props: {
15
+ id: string;
16
+ from: string;
17
+ to: string;
18
+ } & WireProps): _grayhaven_nerve.WireDef;
19
+ declare function Splice(props: {
20
+ id: string;
21
+ } & SpliceProps): _grayhaven_nerve.SpliceDef;
22
+ declare function Cable(props: {
23
+ id: string;
24
+ } & CableProps): _grayhaven_nerve.CableDef;
25
+ declare function Branch(props: {
26
+ id: string;
27
+ } & Omit<BranchProps, "path"> & {
28
+ path: ReadonlyArray<string>;
29
+ }): _grayhaven_nerve.BranchDef;
30
+ declare function Label(props: {
31
+ id: string;
32
+ } & LabelProps): _grayhaven_nerve.LabelDef;
33
+ declare function Harness(props: {
34
+ id: string;
35
+ revision: string;
36
+ units: "mm" | "in";
37
+ children?: Children;
38
+ }): HarnessDesign;
39
+
40
+ export { Branch, Cable, type Children, Connector, Harness, Label, Splice, Wire };
package/dist/index.js ADDED
@@ -0,0 +1,77 @@
1
+ import {
2
+ Fragment,
3
+ jsx,
4
+ jsxs
5
+ } from "./chunk-IBL3BQIP.js";
6
+
7
+ // src/components.ts
8
+ import {
9
+ branch as branchFn,
10
+ cable as cableFn,
11
+ connector as connectorFn,
12
+ harness as harnessFn,
13
+ label as labelFn,
14
+ splice as spliceFn,
15
+ wire as wireFn
16
+ } from "@grayhaven/nerve";
17
+ var flatten = (children) => {
18
+ if (children === void 0 || children === null || children === false) return [];
19
+ if (Array.isArray(children)) return children.flatMap(flatten);
20
+ return [children];
21
+ };
22
+ var endpoint = (s) => {
23
+ const dot = s.lastIndexOf(".");
24
+ if (dot === -1) return { kind: "splice-ref", splice: s };
25
+ return { kind: "pin-ref", connector: s.slice(0, dot), pin: s.slice(dot + 1) };
26
+ };
27
+ function Connector(props) {
28
+ const { ref, part, ...rest } = props;
29
+ return connectorFn(ref, part, rest);
30
+ }
31
+ function Wire(props) {
32
+ const { id, from, to, ...rest } = props;
33
+ return wireFn(id, endpoint(from), endpoint(to), rest);
34
+ }
35
+ function Splice(props) {
36
+ const { id, ...rest } = props;
37
+ return spliceFn(id, rest);
38
+ }
39
+ function Cable(props) {
40
+ const { id, ...rest } = props;
41
+ return cableFn(id, rest);
42
+ }
43
+ function Branch(props) {
44
+ const { id, ...rest } = props;
45
+ return branchFn(id, rest);
46
+ }
47
+ function Label(props) {
48
+ const { id, ...rest } = props;
49
+ return labelFn(id, rest);
50
+ }
51
+ function Harness(props) {
52
+ const kids = flatten(props.children);
53
+ const byKind = (kind) => kids.filter((k) => k.kind === kind);
54
+ return harnessFn(props.id, {
55
+ revision: props.revision,
56
+ units: props.units,
57
+ connectors: byKind("connector"),
58
+ wires: byKind("wire"),
59
+ splices: byKind("splice"),
60
+ cables: byKind("cable"),
61
+ branches: byKind("branch"),
62
+ labels: byKind("label")
63
+ });
64
+ }
65
+ export {
66
+ Branch,
67
+ Cable,
68
+ Connector,
69
+ Fragment,
70
+ Harness,
71
+ Label,
72
+ Splice,
73
+ Wire,
74
+ jsx,
75
+ jsxs
76
+ };
77
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components.ts"],"sourcesContent":["/**\n * JSX components for harness authoring (tscircuit-inspired, experimental).\n * No React: these are plain functions invoked by the custom JSX runtime in\n * jsx-runtime.ts. The output is the SAME typed design objects the function\n * DSL produces — <Harness> compiles to byte-identical HIR (proven in\n * tests), so JSX is purely an authoring-style choice.\n *\n * /** @jsxImportSource @grayhaven/nerve-react *​/\n * export default (\n * <Harness id=\"h\" revision=\"A\" units=\"mm\">\n * <Connector ref=\"J1\" part={part(\"microfit-2x8\")} pins={{ 1: \"VBAT\" }} />\n * <Wire id=\"W1\" from=\"J1.1\" to=\"M1.1\" gauge=\"20AWG\" color=\"red\" length={420} />\n * </Harness>\n * )\n *\n * Endpoints are strings: \"J1.3\" (connector.pin) or a splice id (\"S1\").\n */\nimport {\n branch as branchFn,\n cable as cableFn,\n connector as connectorFn,\n harness as harnessFn,\n label as labelFn,\n splice as spliceFn,\n wire as wireFn,\n type BranchProps,\n type CableProps,\n type ConnectorPart,\n type HarnessDesign,\n type LabelProps,\n type PinAssignments,\n type PinPartAssignment,\n type SpliceProps,\n type WireProps\n} from \"@grayhaven/nerve\"\n\ntype Def = ReturnType<\n | typeof connectorFn\n | typeof wireFn\n | typeof branchFn\n | typeof labelFn\n | typeof spliceFn\n | typeof cableFn\n>\n\nexport type Children = Def | ReadonlyArray<Children> | undefined | null | false\n\nexport const flatten = (children: Children): Array<Def> => {\n if (children === undefined || children === null || children === false) return []\n if (Array.isArray(children)) return (children as ReadonlyArray<Children>).flatMap(flatten)\n return [children as Def]\n}\n\n/** \"J1.3\" -> pin ref; anything without a dot is a splice id. */\nconst endpoint = (s: string) => {\n const dot = s.lastIndexOf(\".\")\n if (dot === -1) return { kind: \"splice-ref\" as const, splice: s }\n return { kind: \"pin-ref\" as const, connector: s.slice(0, dot), pin: s.slice(dot + 1) }\n}\n\nexport function Connector(props: {\n ref: string\n part: ConnectorPart\n pins: PinAssignments\n terminals?: PinPartAssignment\n seals?: PinPartAssignment\n}) {\n const { ref, part, ...rest } = props\n return connectorFn(ref, part, rest)\n}\n\nexport function Wire(props: { id: string; from: string; to: string } & WireProps) {\n const { id, from, to, ...rest } = props\n return wireFn(id, endpoint(from), endpoint(to), rest)\n}\n\nexport function Splice(props: { id: string } & SpliceProps) {\n const { id, ...rest } = props\n return spliceFn(id, rest)\n}\n\nexport function Cable(props: { id: string } & CableProps) {\n const { id, ...rest } = props\n return cableFn(id, rest)\n}\n\nexport function Branch(props: { id: string } & Omit<BranchProps, \"path\"> & { path: ReadonlyArray<string> }) {\n const { id, ...rest } = props\n return branchFn(id, rest)\n}\n\nexport function Label(props: { id: string } & LabelProps) {\n const { id, ...rest } = props\n return labelFn(id, rest)\n}\n\nexport function Harness(props: {\n id: string\n revision: string\n units: \"mm\" | \"in\"\n children?: Children\n}): HarnessDesign {\n const kids = flatten(props.children)\n const byKind = (kind: Def[\"kind\"]) => kids.filter((k) => k.kind === kind)\n return harnessFn(props.id, {\n revision: props.revision,\n units: props.units,\n connectors: byKind(\"connector\") as never,\n wires: byKind(\"wire\") as never,\n splices: byKind(\"splice\") as never,\n cables: byKind(\"cable\") as never,\n branches: byKind(\"branch\") as never,\n labels: byKind(\"label\") as never\n })\n}\n"],"mappings":";;;;;;;AAiBA;AAAA,EACE,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,OAUH;AAaA,IAAM,UAAU,CAAC,aAAmC;AACzD,MAAI,aAAa,UAAa,aAAa,QAAQ,aAAa,MAAO,QAAO,CAAC;AAC/E,MAAI,MAAM,QAAQ,QAAQ,EAAG,QAAQ,SAAqC,QAAQ,OAAO;AACzF,SAAO,CAAC,QAAe;AACzB;AAGA,IAAM,WAAW,CAAC,MAAc;AAC9B,QAAM,MAAM,EAAE,YAAY,GAAG;AAC7B,MAAI,QAAQ,GAAI,QAAO,EAAE,MAAM,cAAuB,QAAQ,EAAE;AAChE,SAAO,EAAE,MAAM,WAAoB,WAAW,EAAE,MAAM,GAAG,GAAG,GAAG,KAAK,EAAE,MAAM,MAAM,CAAC,EAAE;AACvF;AAEO,SAAS,UAAU,OAMvB;AACD,QAAM,EAAE,KAAK,MAAM,GAAG,KAAK,IAAI;AAC/B,SAAO,YAAY,KAAK,MAAM,IAAI;AACpC;AAEO,SAAS,KAAK,OAA6D;AAChF,QAAM,EAAE,IAAI,MAAM,IAAI,GAAG,KAAK,IAAI;AAClC,SAAO,OAAO,IAAI,SAAS,IAAI,GAAG,SAAS,EAAE,GAAG,IAAI;AACtD;AAEO,SAAS,OAAO,OAAqC;AAC1D,QAAM,EAAE,IAAI,GAAG,KAAK,IAAI;AACxB,SAAO,SAAS,IAAI,IAAI;AAC1B;AAEO,SAAS,MAAM,OAAoC;AACxD,QAAM,EAAE,IAAI,GAAG,KAAK,IAAI;AACxB,SAAO,QAAQ,IAAI,IAAI;AACzB;AAEO,SAAS,OAAO,OAAqF;AAC1G,QAAM,EAAE,IAAI,GAAG,KAAK,IAAI;AACxB,SAAO,SAAS,IAAI,IAAI;AAC1B;AAEO,SAAS,MAAM,OAAoC;AACxD,QAAM,EAAE,IAAI,GAAG,KAAK,IAAI;AACxB,SAAO,QAAQ,IAAI,IAAI;AACzB;AAEO,SAAS,QAAQ,OAKN;AAChB,QAAM,OAAO,QAAQ,MAAM,QAAQ;AACnC,QAAM,SAAS,CAAC,SAAsB,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AACxE,SAAO,UAAU,MAAM,IAAI;AAAA,IACzB,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM;AAAA,IACb,YAAY,OAAO,WAAW;AAAA,IAC9B,OAAO,OAAO,MAAM;AAAA,IACpB,SAAS,OAAO,QAAQ;AAAA,IACxB,QAAQ,OAAO,OAAO;AAAA,IACtB,UAAU,OAAO,QAAQ;AAAA,IACzB,QAAQ,OAAO,OAAO;AAAA,EACxB,CAAC;AACH;","names":[]}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Custom JSX runtime (automatic mode): no React, no fiber, no VDOM —
3
+ * `jsx(Component, props)` simply CALLS the component. JSX becomes pure
4
+ * function application over the typed DSL, so authoring style changes
5
+ * and nothing else does.
6
+ */
7
+ type JsxComponent<P, R> = (props: P) => R;
8
+ declare const jsx: <P, R>(type: JsxComponent<P, R>, props: P) => R;
9
+ declare const jsxs: <P, R>(type: JsxComponent<P, R>, props: P) => R;
10
+ declare const jsxDEV: <P, R>(type: JsxComponent<P, R>, props: P) => R;
11
+ declare const Fragment: (props: {
12
+ children?: unknown;
13
+ }) => unknown;
14
+ declare global {
15
+ namespace JSX {
16
+ type Element = any;
17
+ type ElementType = (props: any) => unknown;
18
+ interface ElementChildrenAttribute {
19
+ children: unknown;
20
+ }
21
+ interface IntrinsicElements {
22
+ [k: string]: never;
23
+ }
24
+ }
25
+ }
26
+
27
+ export { Fragment, type JsxComponent, jsx, jsxDEV, jsxs };
@@ -0,0 +1,13 @@
1
+ import {
2
+ Fragment,
3
+ jsx,
4
+ jsxDEV,
5
+ jsxs
6
+ } from "./chunk-IBL3BQIP.js";
7
+ export {
8
+ Fragment,
9
+ jsx,
10
+ jsxDEV,
11
+ jsxs
12
+ };
13
+ //# sourceMappingURL=jsx-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@grayhaven/nerve-react",
3
+ "version": "0.5.0",
4
+ "description": "JSX authoring for Grayhaven Nerve harnesses (experimental). No React runtime — a 2KB custom JSX factory over the same typed DSL.",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": "./src/index.ts",
8
+ "./jsx-runtime": "./src/jsx-runtime.ts",
9
+ "./jsx-dev-runtime": "./src/jsx-runtime.ts"
10
+ },
11
+ "publishConfig": {
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ },
17
+ "./jsx-runtime": {
18
+ "types": "./dist/jsx-runtime.d.ts",
19
+ "default": "./dist/jsx-runtime.js"
20
+ },
21
+ "./jsx-dev-runtime": {
22
+ "types": "./dist/jsx-runtime.d.ts",
23
+ "default": "./dist/jsx-runtime.js"
24
+ }
25
+ }
26
+ },
27
+ "scripts": {
28
+ "build": "tsup src/index.ts src/jsx-runtime.ts --format esm --dts --sourcemap --clean",
29
+ "typecheck": "tsc -p . --noEmit"
30
+ },
31
+ "dependencies": {
32
+ "@grayhaven/nerve": "0.4.0"
33
+ },
34
+ "devDependencies": {
35
+ "tsup": "^8.5.0",
36
+ "typescript": "^5.8.3",
37
+ "@grayhaven/nerve-connectors": "0.4.0"
38
+ },
39
+ "license": "Apache-2.0"
40
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * JSX components for harness authoring (tscircuit-inspired, experimental).
3
+ * No React: these are plain functions invoked by the custom JSX runtime in
4
+ * jsx-runtime.ts. The output is the SAME typed design objects the function
5
+ * DSL produces — <Harness> compiles to byte-identical HIR (proven in
6
+ * tests), so JSX is purely an authoring-style choice.
7
+ *
8
+ * /** @jsxImportSource @grayhaven/nerve-react *​/
9
+ * export default (
10
+ * <Harness id="h" revision="A" units="mm">
11
+ * <Connector ref="J1" part={part("microfit-2x8")} pins={{ 1: "VBAT" }} />
12
+ * <Wire id="W1" from="J1.1" to="M1.1" gauge="20AWG" color="red" length={420} />
13
+ * </Harness>
14
+ * )
15
+ *
16
+ * Endpoints are strings: "J1.3" (connector.pin) or a splice id ("S1").
17
+ */
18
+ import {
19
+ branch as branchFn,
20
+ cable as cableFn,
21
+ connector as connectorFn,
22
+ harness as harnessFn,
23
+ label as labelFn,
24
+ splice as spliceFn,
25
+ wire as wireFn,
26
+ type BranchProps,
27
+ type CableProps,
28
+ type ConnectorPart,
29
+ type HarnessDesign,
30
+ type LabelProps,
31
+ type PinAssignments,
32
+ type PinPartAssignment,
33
+ type SpliceProps,
34
+ type WireProps
35
+ } from "@grayhaven/nerve"
36
+
37
+ type Def = ReturnType<
38
+ | typeof connectorFn
39
+ | typeof wireFn
40
+ | typeof branchFn
41
+ | typeof labelFn
42
+ | typeof spliceFn
43
+ | typeof cableFn
44
+ >
45
+
46
+ export type Children = Def | ReadonlyArray<Children> | undefined | null | false
47
+
48
+ export const flatten = (children: Children): Array<Def> => {
49
+ if (children === undefined || children === null || children === false) return []
50
+ if (Array.isArray(children)) return (children as ReadonlyArray<Children>).flatMap(flatten)
51
+ return [children as Def]
52
+ }
53
+
54
+ /** "J1.3" -> pin ref; anything without a dot is a splice id. */
55
+ const endpoint = (s: string) => {
56
+ const dot = s.lastIndexOf(".")
57
+ if (dot === -1) return { kind: "splice-ref" as const, splice: s }
58
+ return { kind: "pin-ref" as const, connector: s.slice(0, dot), pin: s.slice(dot + 1) }
59
+ }
60
+
61
+ export function Connector(props: {
62
+ ref: string
63
+ part: ConnectorPart
64
+ pins: PinAssignments
65
+ terminals?: PinPartAssignment
66
+ seals?: PinPartAssignment
67
+ }) {
68
+ const { ref, part, ...rest } = props
69
+ return connectorFn(ref, part, rest)
70
+ }
71
+
72
+ export function Wire(props: { id: string; from: string; to: string } & WireProps) {
73
+ const { id, from, to, ...rest } = props
74
+ return wireFn(id, endpoint(from), endpoint(to), rest)
75
+ }
76
+
77
+ export function Splice(props: { id: string } & SpliceProps) {
78
+ const { id, ...rest } = props
79
+ return spliceFn(id, rest)
80
+ }
81
+
82
+ export function Cable(props: { id: string } & CableProps) {
83
+ const { id, ...rest } = props
84
+ return cableFn(id, rest)
85
+ }
86
+
87
+ export function Branch(props: { id: string } & Omit<BranchProps, "path"> & { path: ReadonlyArray<string> }) {
88
+ const { id, ...rest } = props
89
+ return branchFn(id, rest)
90
+ }
91
+
92
+ export function Label(props: { id: string } & LabelProps) {
93
+ const { id, ...rest } = props
94
+ return labelFn(id, rest)
95
+ }
96
+
97
+ export function Harness(props: {
98
+ id: string
99
+ revision: string
100
+ units: "mm" | "in"
101
+ children?: Children
102
+ }): HarnessDesign {
103
+ const kids = flatten(props.children)
104
+ const byKind = (kind: Def["kind"]) => kids.filter((k) => k.kind === kind)
105
+ return harnessFn(props.id, {
106
+ revision: props.revision,
107
+ units: props.units,
108
+ connectors: byKind("connector") as never,
109
+ wires: byKind("wire") as never,
110
+ splices: byKind("splice") as never,
111
+ cables: byKind("cable") as never,
112
+ branches: byKind("branch") as never,
113
+ labels: byKind("label") as never
114
+ })
115
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { Branch, Cable, Connector, Harness, Label, Splice, Wire } from "./components.js"
2
+ export type { Children } from "./components.js"
3
+ export { Fragment, jsx, jsxs } from "./jsx-runtime.js"
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Custom JSX runtime (automatic mode): no React, no fiber, no VDOM —
3
+ * `jsx(Component, props)` simply CALLS the component. JSX becomes pure
4
+ * function application over the typed DSL, so authoring style changes
5
+ * and nothing else does.
6
+ */
7
+ export type JsxComponent<P, R> = (props: P) => R
8
+
9
+ export const jsx = <P, R>(type: JsxComponent<P, R>, props: P): R => type(props)
10
+ export const jsxs = jsx
11
+ export const jsxDEV = <P, R>(type: JsxComponent<P, R>, props: P): R => type(props)
12
+
13
+ export const Fragment = (props: { children?: unknown }): unknown => props.children
14
+
15
+ // Minimal JSX namespace: components only (no intrinsic lowercase elements —
16
+ // <Harness> not <harness>, keeping every element a typed function).
17
+ declare global {
18
+ namespace JSX {
19
+ // Element is intentionally loose (each component returns its own def
20
+ // type); ElementType constrains elements to component FUNCTIONS.
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ type Element = any
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ type ElementType = (props: any) => unknown
25
+ interface ElementChildrenAttribute {
26
+ children: unknown
27
+ }
28
+ interface IntrinsicElements {
29
+ [k: string]: never
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,59 @@
1
+ /** @jsxImportSource @grayhaven/nerve-react */
2
+ /**
3
+ * The JSX layer is authoring sugar ONLY: the same harness written as JSX
4
+ * and as function calls must compile to byte-identical HIR.
5
+ */
6
+ import { describe, expect, it } from "vitest"
7
+ import { compileDesign } from "@grayhaven/nerve"
8
+ import { Branch, Connector, Harness, Label, Wire } from "@grayhaven/nerve-react"
9
+ import functionStyle from "../../../examples/motor-controller/src/main.harness.js"
10
+ import { MolexMicroFit } from "@grayhaven/nerve-connectors"
11
+
12
+ const PINS = {
13
+ 1: "VBAT_24V", 2: "GND", 3: "CAN_H", 4: "CAN_L",
14
+ 5: "ENC_A", 6: "ENC_B", 7: "MOTOR_TEMP", 8: "SHIELD_DRAIN"
15
+ } as const
16
+
17
+ const jsxStyle = (
18
+ <Harness id="motor-controller-harness" revision="A" units="mm">
19
+ <Connector ref="J1" part={MolexMicroFit["43025-0800"]} pins={PINS} />
20
+ <Connector ref="M1" part={MolexMicroFit["43020-0800"]} pins={PINS} />
21
+ <Wire id="W1" from="J1.1" to="M1.1" gauge="20AWG" color="red" length={420} signal="VBAT_24V" />
22
+ <Wire id="W2" from="J1.2" to="M1.2" gauge="20AWG" color="black" length={420} signal="GND" />
23
+ <Wire id="W3" from="J1.3" to="M1.3" gauge="24AWG" color="white" twistGroup="CAN_PAIR" signal="CAN_H" />
24
+ <Wire id="W4" from="J1.4" to="M1.4" gauge="24AWG" color="blue" twistGroup="CAN_PAIR" signal="CAN_L" />
25
+ <Branch id="main" path={["J1", "M1"]} sleeve="braided-pet" nominalLength={420} />
26
+ <Label id="L1" text="MOTOR CTRL A" attachTo="main" offsetFrom="J1" distance={50} />
27
+ </Harness>
28
+ )
29
+
30
+ describe("@grayhaven/nerve-react (experimental JSX authoring)", () => {
31
+ it("compiles JSX to byte-identical HIR vs the function DSL", () => {
32
+ const a = JSON.stringify(compileDesign(jsxStyle).hir, null, 2)
33
+ const b = JSON.stringify(compileDesign(functionStyle).hir, null, 2)
34
+ expect(a).toBe(b)
35
+ })
36
+
37
+ it("string endpoints parse pins and splices", () => {
38
+ const w = <Wire id="W9" from="J1.12" to="S1" gauge="24AWG" />
39
+ expect(w).toMatchObject({
40
+ from: { kind: "pin-ref", connector: "J1", pin: "12" },
41
+ to: { kind: "splice-ref", splice: "S1" }
42
+ })
43
+ })
44
+
45
+ it("nested arrays and conditionals flatten like JSX children should", () => {
46
+ const drops = ["A", "B"].map((s, i) => (
47
+ <Wire id={`W${i}`} from={`J1.${i + 1}`} to={`M1.${i + 1}`} signal={s} gauge="24AWG" />
48
+ ))
49
+ const h = (
50
+ <Harness id="t" revision="A" units="mm">
51
+ <Connector ref="J1" part={MolexMicroFit["43025-0800"]} pins={{ 1: "A", 2: "B" }} />
52
+ <Connector ref="M1" part={MolexMicroFit["43020-0800"]} pins={{ 1: "A", 2: "B" }} />
53
+ {drops}
54
+ {false}
55
+ </Harness>
56
+ )
57
+ expect(compileDesign(h).hir.wires).toHaveLength(2)
58
+ })
59
+ })
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx",
5
+ "jsxImportSource": "@grayhaven/nerve-react"
6
+ },
7
+ "include": [
8
+ "src",
9
+ "test"
10
+ ]
11
+ }