schematex 0.9.17 → 0.9.19
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/README.md +13 -0
- package/dist/ai/ai-sdk.cjs +9 -9
- package/dist/ai/ai-sdk.d.cts +3 -3
- package/dist/ai/ai-sdk.d.ts +3 -3
- package/dist/ai/ai-sdk.js +4 -4
- package/dist/ai/index.cjs +18 -18
- package/dist/ai/index.d.cts +4 -4
- package/dist/ai/index.d.ts +4 -4
- package/dist/ai/index.js +5 -5
- package/dist/{api-DAUFeETp.d.cts → api-DH9a1V6Q.d.cts} +1 -1
- package/dist/{api-C9ufsgIb.d.ts → api-DsAwn8ne.d.ts} +1 -1
- package/dist/browser.cjs +10 -10
- package/dist/browser.d.cts +3 -3
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +4 -4
- package/dist/{chunk-37WDY4G4.js → chunk-5IPT6OFE.js} +363 -52
- package/dist/chunk-5IPT6OFE.js.map +1 -0
- package/dist/{chunk-LUJ4IBEO.js → chunk-BP52JB7C.js} +4 -4
- package/dist/{chunk-LUJ4IBEO.js.map → chunk-BP52JB7C.js.map} +1 -1
- package/dist/{chunk-KHIPNN35.cjs → chunk-GJTD3RQE.cjs} +6 -6
- package/dist/{chunk-KHIPNN35.cjs.map → chunk-GJTD3RQE.cjs.map} +1 -1
- package/dist/{chunk-HVPSY7LV.js → chunk-JBNLZQP2.js} +47 -5
- package/dist/chunk-JBNLZQP2.js.map +1 -0
- package/dist/{chunk-24YHD4YI.cjs → chunk-JXPBZEFM.cjs} +362 -52
- package/dist/chunk-JXPBZEFM.cjs.map +1 -0
- package/dist/{chunk-6GVFKOSH.js → chunk-OZD4CYAK.js} +2 -2
- package/dist/{chunk-6GVFKOSH.js.map → chunk-OZD4CYAK.js.map} +1 -1
- package/dist/{chunk-ATN2WLSL.cjs → chunk-PZ5MNDVY.cjs} +49 -7
- package/dist/chunk-PZ5MNDVY.cjs.map +1 -0
- package/dist/{chunk-AWUUGDN4.cjs → chunk-RVPYIBBH.cjs} +2 -2
- package/dist/{chunk-AWUUGDN4.cjs.map → chunk-RVPYIBBH.cjs.map} +1 -1
- package/dist/{diagnostics-DSxLohjY.d.cts → diagnostics-CKacYRIE.d.cts} +1 -1
- package/dist/{diagnostics-DSxLohjY.d.ts → diagnostics-CKacYRIE.d.ts} +1 -1
- package/dist/diagrams/blockdiagram/index.d.cts +1 -1
- package/dist/diagrams/blockdiagram/index.d.ts +1 -1
- package/dist/diagrams/circuit/index.cjs +8 -8
- package/dist/diagrams/circuit/index.d.cts +3 -1
- package/dist/diagrams/circuit/index.d.ts +3 -1
- package/dist/diagrams/circuit/index.js +1 -1
- package/dist/diagrams/ecomap/index.d.cts +1 -1
- package/dist/diagrams/ecomap/index.d.ts +1 -1
- package/dist/diagrams/entity/index.d.cts +1 -1
- package/dist/diagrams/entity/index.d.ts +1 -1
- package/dist/diagrams/fishbone/index.d.cts +1 -1
- package/dist/diagrams/fishbone/index.d.ts +1 -1
- package/dist/diagrams/flowchart/index.d.cts +2 -2
- package/dist/diagrams/flowchart/index.d.ts +2 -2
- package/dist/diagrams/genogram/index.d.cts +1 -1
- package/dist/diagrams/genogram/index.d.ts +1 -1
- package/dist/diagrams/ladder/index.d.cts +1 -1
- package/dist/diagrams/ladder/index.d.ts +1 -1
- package/dist/diagrams/logic/index.d.cts +1 -1
- package/dist/diagrams/logic/index.d.ts +1 -1
- package/dist/diagrams/orgchart/index.d.cts +1 -1
- package/dist/diagrams/orgchart/index.d.ts +1 -1
- package/dist/diagrams/pedigree/index.d.cts +1 -1
- package/dist/diagrams/pedigree/index.d.ts +1 -1
- package/dist/diagrams/phylo/index.d.cts +1 -1
- package/dist/diagrams/phylo/index.d.ts +1 -1
- package/dist/diagrams/siteplan/index.d.cts +1 -1
- package/dist/diagrams/siteplan/index.d.ts +1 -1
- package/dist/diagrams/sld/index.cjs +7 -7
- package/dist/diagrams/sld/index.d.cts +1 -1
- package/dist/diagrams/sld/index.d.ts +1 -1
- package/dist/diagrams/sld/index.js +1 -1
- package/dist/diagrams/sociogram/index.d.cts +1 -1
- package/dist/diagrams/sociogram/index.d.ts +1 -1
- package/dist/diagrams/timing/index.d.cts +1 -1
- package/dist/diagrams/timing/index.d.ts +1 -1
- package/dist/diagrams/venn/index.d.cts +1 -1
- package/dist/diagrams/venn/index.d.ts +1 -1
- package/dist/{index-CZa2pU0T.d.ts → index-BmJxw0lf.d.ts} +1 -1
- package/dist/{index-CDDfbChc.d.cts → index-Dth_Wjwf.d.cts} +1 -1
- package/dist/index.cjs +45 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +8 -11
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +4 -4
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +3 -3
- package/dist/{tools-Bvw6dwIR.d.cts → tools-Bl6w3h3P.d.cts} +2 -2
- package/dist/{tools-DtuvE-K4.d.ts → tools-CBYFRF2a.d.ts} +2 -2
- package/package.json +1 -1
- package/dist/chunk-24YHD4YI.cjs.map +0 -1
- package/dist/chunk-37WDY4G4.js.map +0 -1
- package/dist/chunk-ATN2WLSL.cjs.map +0 -1
- package/dist/chunk-HVPSY7LV.js.map +0 -1
|
@@ -1458,6 +1458,7 @@ var SYMBOLS = {
|
|
|
1458
1458
|
voltmeter,
|
|
1459
1459
|
wattmeter,
|
|
1460
1460
|
motor,
|
|
1461
|
+
lamp,
|
|
1461
1462
|
speaker,
|
|
1462
1463
|
microphone,
|
|
1463
1464
|
buzzer,
|
|
@@ -1519,14 +1520,9 @@ var SYMBOLS = {
|
|
|
1519
1520
|
switch_dpdt,
|
|
1520
1521
|
oscilloscope,
|
|
1521
1522
|
port
|
|
1522
|
-
// Lamp reuses buzzer slot? No, needs its own entry but our CircuitComponentType
|
|
1523
|
-
// doesn't have "lamp". We map it via parser alias to "buzzer" or add specifically.
|
|
1524
|
-
};
|
|
1525
|
-
var EXTRA_SYMBOLS = {
|
|
1526
|
-
lamp
|
|
1527
1523
|
};
|
|
1528
1524
|
function getSymbol(t) {
|
|
1529
|
-
return SYMBOLS[t]
|
|
1525
|
+
return SYMBOLS[t];
|
|
1530
1526
|
}
|
|
1531
1527
|
function getNetlistPinOrder(t) {
|
|
1532
1528
|
const sym = getSymbol(t);
|
|
@@ -1590,7 +1586,10 @@ var TYPE_ALIASES = {
|
|
|
1590
1586
|
wireduct: "wire_duct",
|
|
1591
1587
|
wire_duct: "wire_duct",
|
|
1592
1588
|
trunking: "wire_duct",
|
|
1593
|
-
plc: "plc"
|
|
1589
|
+
plc: "plc",
|
|
1590
|
+
lamp: "lamp",
|
|
1591
|
+
light: "lamp",
|
|
1592
|
+
bulb: "lamp"
|
|
1594
1593
|
};
|
|
1595
1594
|
var GROUND_REF = /^(0|gnd|ground|earth|pe|agnd|dgnd|gnda|gndd|vss|com)(_\w+|\d+)?$/i;
|
|
1596
1595
|
function isGroundRef(s) {
|
|
@@ -1654,7 +1653,7 @@ function parseNetlist(body, title2) {
|
|
|
1654
1653
|
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
1655
1654
|
const raw = lines[lineIdx];
|
|
1656
1655
|
if (/^\s*\*/.test(raw)) continue;
|
|
1657
|
-
const stripped = raw.replace(
|
|
1656
|
+
const stripped = raw.replace(/[#;].*$/, "").trim();
|
|
1658
1657
|
if (!stripped) continue;
|
|
1659
1658
|
const tokens = tokenize(stripped);
|
|
1660
1659
|
if (tokens.length < 2) {
|
|
@@ -1885,6 +1884,7 @@ var COMPONENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
1885
1884
|
"thermal_overload",
|
|
1886
1885
|
"disconnect_switch",
|
|
1887
1886
|
"motor",
|
|
1887
|
+
"lamp",
|
|
1888
1888
|
"speaker",
|
|
1889
1889
|
"microphone",
|
|
1890
1890
|
"buzzer",
|
|
@@ -1949,18 +1949,16 @@ var ALIASES = {
|
|
|
1949
1949
|
overload: "thermal_overload",
|
|
1950
1950
|
thermal: "thermal_overload",
|
|
1951
1951
|
disconnect: "disconnect_switch",
|
|
1952
|
-
isolator: "disconnect_switch"
|
|
1952
|
+
isolator: "disconnect_switch",
|
|
1953
|
+
light: "lamp",
|
|
1954
|
+
bulb: "lamp"
|
|
1953
1955
|
};
|
|
1954
|
-
var EXTRA_TYPES = /* @__PURE__ */ new Set(["lamp"]);
|
|
1955
1956
|
function normalizeType(raw) {
|
|
1956
1957
|
const lower = raw.toLowerCase();
|
|
1957
1958
|
if (ALIASES[lower]) return ALIASES[lower];
|
|
1958
1959
|
if (COMPONENT_TYPES.has(lower)) {
|
|
1959
1960
|
return lower;
|
|
1960
1961
|
}
|
|
1961
|
-
if (EXTRA_TYPES.has(lower)) {
|
|
1962
|
-
return lower;
|
|
1963
|
-
}
|
|
1964
1962
|
return null;
|
|
1965
1963
|
}
|
|
1966
1964
|
var DIRECTIONS = /* @__PURE__ */ new Set(["right", "left", "up", "down"]);
|
|
@@ -2019,12 +2017,12 @@ function parseAttrs(rest) {
|
|
|
2019
2017
|
}
|
|
2020
2018
|
function parseCircuit(text2) {
|
|
2021
2019
|
const rawLines = text2.split("\n");
|
|
2022
|
-
const firstMeaningful = rawLines.map((l) => l.replace(
|
|
2020
|
+
const firstMeaningful = rawLines.map((l) => l.replace(/[#;].*$/, "").trim()).find((l) => l.length > 0) ?? "";
|
|
2023
2021
|
if (/^circuit\b.*\bnetlist\s*$/i.test(firstMeaningful)) {
|
|
2024
2022
|
const netlistTitle = matchQuotedTitle(firstMeaningful);
|
|
2025
2023
|
let headerIdx = -1;
|
|
2026
2024
|
for (let i = 0; i < rawLines.length; i++) {
|
|
2027
|
-
const s = rawLines[i].replace(
|
|
2025
|
+
const s = rawLines[i].replace(/[#;].*$/, "").trim();
|
|
2028
2026
|
if (s.length > 0) {
|
|
2029
2027
|
headerIdx = i;
|
|
2030
2028
|
break;
|
|
@@ -2042,7 +2040,7 @@ function parseCircuit(text2) {
|
|
|
2042
2040
|
let pendingAt;
|
|
2043
2041
|
const mkId = (prefix) => `${prefix}_${autoId++}`;
|
|
2044
2042
|
for (const rawLine of lines) {
|
|
2045
|
-
const stripped = rawLine.replace(
|
|
2043
|
+
const stripped = rawLine.replace(/[#;].*$/, "").trim();
|
|
2046
2044
|
if (!stripped) continue;
|
|
2047
2045
|
if (/^circuit\b/i.test(stripped)) {
|
|
2048
2046
|
const t = matchQuotedTitle(stripped);
|
|
@@ -2141,7 +2139,9 @@ function parseCircuit(text2) {
|
|
|
2141
2139
|
const typeStr = bareMatch[1];
|
|
2142
2140
|
const norm = normalizeType(typeStr);
|
|
2143
2141
|
if (!norm) {
|
|
2144
|
-
|
|
2142
|
+
throw new CircuitParseError(
|
|
2143
|
+
`Unknown component type: "${typeStr}". For SPICE-style connectivity (Id net1 net2 [value]), start the diagram with the \`netlist\` header: circuit "..." netlist.`
|
|
2144
|
+
);
|
|
2145
2145
|
}
|
|
2146
2146
|
const rest = bareMatch[2] ?? "";
|
|
2147
2147
|
const parsed = parseAttrs(rest);
|
|
@@ -2470,6 +2470,11 @@ var ROW_H = 80;
|
|
|
2470
2470
|
var LEFT_MARGIN = 70;
|
|
2471
2471
|
var TOP_MARGIN = 56;
|
|
2472
2472
|
var SHUNT_OFFSET = 28;
|
|
2473
|
+
var AC_LEFT_MARGIN = 96;
|
|
2474
|
+
var AC_LIVE_Y = 56;
|
|
2475
|
+
var AC_RETURN_Y = 150;
|
|
2476
|
+
var AC_SERIES_GAP = 58;
|
|
2477
|
+
var AC_TRAVELER_SPAN = 128;
|
|
2473
2478
|
function isPowerSource(c) {
|
|
2474
2479
|
return c.componentType === "voltage_source" || c.componentType === "current_source" || c.componentType === "ac_source" || c.componentType === "battery" || c.componentType === "vcc";
|
|
2475
2480
|
}
|
|
@@ -2496,8 +2501,334 @@ function extendBBox(bbox, pt) {
|
|
|
2496
2501
|
if (pt.x > bbox.maxX) bbox.maxX = pt.x;
|
|
2497
2502
|
if (pt.y > bbox.maxY) bbox.maxY = pt.y;
|
|
2498
2503
|
}
|
|
2504
|
+
function placeComponent(comp, x, y, fallbackDir) {
|
|
2505
|
+
const direction = comp.attrs?.dirExplicit === "true" ? comp.direction : fallbackDir ?? defaultDirection(comp);
|
|
2506
|
+
comp.direction = direction;
|
|
2507
|
+
const rot = rotationOf(direction);
|
|
2508
|
+
const sym = getSymbol(comp.componentType);
|
|
2509
|
+
const worldAnchors = {};
|
|
2510
|
+
if (sym) {
|
|
2511
|
+
for (const [name, pt] of Object.entries(sym.anchors)) {
|
|
2512
|
+
const rp = rotatePt(pt, rot);
|
|
2513
|
+
worldAnchors[name] = { x: x + rp.x, y: y + rp.y };
|
|
2514
|
+
}
|
|
2515
|
+
} else {
|
|
2516
|
+
worldAnchors.start = { x, y };
|
|
2517
|
+
worldAnchors.end = { x: x + 30, y };
|
|
2518
|
+
}
|
|
2519
|
+
return {
|
|
2520
|
+
component: comp,
|
|
2521
|
+
x,
|
|
2522
|
+
y,
|
|
2523
|
+
rotation: rot,
|
|
2524
|
+
length: sym?.length ?? 30,
|
|
2525
|
+
anchors: worldAnchors
|
|
2526
|
+
};
|
|
2527
|
+
}
|
|
2528
|
+
function placeMirroredComponent(comp, x, y) {
|
|
2529
|
+
const sym = getSymbol(comp.componentType);
|
|
2530
|
+
const length = sym?.length ?? 30;
|
|
2531
|
+
const worldAnchors = {};
|
|
2532
|
+
comp.direction = "left";
|
|
2533
|
+
if (sym) {
|
|
2534
|
+
for (const [name, pt] of Object.entries(sym.anchors)) {
|
|
2535
|
+
worldAnchors[name] = { x: x + length - pt.x, y: y + pt.y };
|
|
2536
|
+
}
|
|
2537
|
+
} else {
|
|
2538
|
+
worldAnchors.start = { x: x + length, y };
|
|
2539
|
+
worldAnchors.end = { x, y };
|
|
2540
|
+
}
|
|
2541
|
+
return {
|
|
2542
|
+
component: comp,
|
|
2543
|
+
x,
|
|
2544
|
+
y,
|
|
2545
|
+
rotation: 0,
|
|
2546
|
+
mirrorX: true,
|
|
2547
|
+
length,
|
|
2548
|
+
anchors: worldAnchors
|
|
2549
|
+
};
|
|
2550
|
+
}
|
|
2551
|
+
function pinEntries(pinMap, comp) {
|
|
2552
|
+
return Object.entries(pinMap[comp.id] ?? {});
|
|
2553
|
+
}
|
|
2554
|
+
function anchorForNet(pinMap, laid, netId) {
|
|
2555
|
+
const pin = Object.entries(pinMap[laid.component.id] ?? {}).find(
|
|
2556
|
+
([, net]) => net === netId
|
|
2557
|
+
)?.[0];
|
|
2558
|
+
return pin ? laid.anchors[pin] : void 0;
|
|
2559
|
+
}
|
|
2560
|
+
function compactPoints(points) {
|
|
2561
|
+
const out = [];
|
|
2562
|
+
for (const p of points) {
|
|
2563
|
+
const prev = out[out.length - 1];
|
|
2564
|
+
if (!prev || Math.abs(prev.x - p.x) > 0.5 || Math.abs(prev.y - p.y) > 0.5) {
|
|
2565
|
+
out.push(p);
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
return out;
|
|
2569
|
+
}
|
|
2570
|
+
function routeViaY(netId, a, b, y) {
|
|
2571
|
+
if (Math.abs(a.y - b.y) < 0.5) return { netId, points: [a, b] };
|
|
2572
|
+
return {
|
|
2573
|
+
netId,
|
|
2574
|
+
points: compactPoints([a, { x: a.x, y }, { x: b.x, y }, b])
|
|
2575
|
+
};
|
|
2576
|
+
}
|
|
2577
|
+
function routeViaX(netId, a, b, x) {
|
|
2578
|
+
if (Math.abs(a.x - b.x) < 0.5) return { netId, points: [a, b] };
|
|
2579
|
+
return {
|
|
2580
|
+
netId,
|
|
2581
|
+
points: compactPoints([a, { x, y: a.y }, { x, y: b.y }, b])
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2584
|
+
function isAutoGround(c) {
|
|
2585
|
+
return isGround(c) && c.attrs?.auto === "true";
|
|
2586
|
+
}
|
|
2587
|
+
function isTwoTerminal(pinMap, comp) {
|
|
2588
|
+
return pinEntries(pinMap, comp).length === 2;
|
|
2589
|
+
}
|
|
2590
|
+
function isLightingLoad(c) {
|
|
2591
|
+
return c.componentType === "lamp" || c.componentType === "pilot_light" || c.componentType === "motor" || c.componentType === "buzzer" || c.componentType === "speaker";
|
|
2592
|
+
}
|
|
2593
|
+
function traceTwoTerminalChain(pinMap, candidates, startNet, endNet) {
|
|
2594
|
+
const remaining = new Set(candidates.map((c) => c.id));
|
|
2595
|
+
const steps = [];
|
|
2596
|
+
const seenNets = /* @__PURE__ */ new Set([startNet]);
|
|
2597
|
+
let current = startNet;
|
|
2598
|
+
for (let guard = 0; guard <= candidates.length; guard++) {
|
|
2599
|
+
if (current === endNet) return { steps, used: new Set(steps.map((s) => s.comp.id)) };
|
|
2600
|
+
const hits = candidates.filter((c) => {
|
|
2601
|
+
if (!remaining.has(c.id) || !isTwoTerminal(pinMap, c)) return false;
|
|
2602
|
+
return pinEntries(pinMap, c).some(([, net]) => net === current);
|
|
2603
|
+
});
|
|
2604
|
+
if (hits.length !== 1) return null;
|
|
2605
|
+
const comp = hits[0];
|
|
2606
|
+
const nets = pinEntries(pinMap, comp).map(([, net]) => net);
|
|
2607
|
+
const next = nets[0] === current ? nets[1] : nets[0];
|
|
2608
|
+
if (!next || seenNets.has(next) && next !== endNet) return null;
|
|
2609
|
+
steps.push({ comp, inNet: current, outNet: next });
|
|
2610
|
+
remaining.delete(comp.id);
|
|
2611
|
+
seenNets.add(next);
|
|
2612
|
+
current = next;
|
|
2613
|
+
}
|
|
2614
|
+
return null;
|
|
2615
|
+
}
|
|
2616
|
+
function finalizeAutoLayout(items, routes) {
|
|
2617
|
+
const bbox = {
|
|
2618
|
+
minX: Infinity,
|
|
2619
|
+
minY: Infinity,
|
|
2620
|
+
maxX: -Infinity,
|
|
2621
|
+
maxY: -Infinity
|
|
2622
|
+
};
|
|
2623
|
+
for (const it of items) {
|
|
2624
|
+
for (const a of Object.values(it.anchors)) extendBBox(bbox, a);
|
|
2625
|
+
}
|
|
2626
|
+
for (const r of routes) {
|
|
2627
|
+
for (const p of r.points) extendBBox(bbox, p);
|
|
2628
|
+
}
|
|
2629
|
+
if (!isFinite(bbox.minX)) {
|
|
2630
|
+
bbox.minX = 0;
|
|
2631
|
+
bbox.minY = 0;
|
|
2632
|
+
bbox.maxX = 200;
|
|
2633
|
+
bbox.maxY = 200;
|
|
2634
|
+
}
|
|
2635
|
+
const pad = 52;
|
|
2636
|
+
const minX = bbox.minX - pad;
|
|
2637
|
+
const minY = bbox.minY - pad;
|
|
2638
|
+
const maxX = bbox.maxX + pad;
|
|
2639
|
+
const maxY = bbox.maxY + pad;
|
|
2640
|
+
return {
|
|
2641
|
+
width: maxX - minX,
|
|
2642
|
+
height: maxY - minY,
|
|
2643
|
+
offsetX: -minX,
|
|
2644
|
+
offsetY: -minY,
|
|
2645
|
+
items,
|
|
2646
|
+
routes
|
|
2647
|
+
};
|
|
2648
|
+
}
|
|
2649
|
+
function appendReturnRail(routes, pinMap, sourceLaid, loadLaid, returnNet) {
|
|
2650
|
+
const sourceReturn = anchorForNet(pinMap, sourceLaid, returnNet);
|
|
2651
|
+
const loadReturn = anchorForNet(pinMap, loadLaid, returnNet);
|
|
2652
|
+
if (!sourceReturn || !loadReturn) return false;
|
|
2653
|
+
routes.push({
|
|
2654
|
+
netId: returnNet,
|
|
2655
|
+
points: [
|
|
2656
|
+
{ x: sourceReturn.x, y: AC_RETURN_Y },
|
|
2657
|
+
{ x: loadReturn.x, y: AC_RETURN_Y }
|
|
2658
|
+
]
|
|
2659
|
+
});
|
|
2660
|
+
routes.push({
|
|
2661
|
+
netId: `${returnNet}.${sourceLaid.component.id}`,
|
|
2662
|
+
points: compactPoints([sourceReturn, { x: sourceReturn.x, y: AC_RETURN_Y }])
|
|
2663
|
+
});
|
|
2664
|
+
routes.push({
|
|
2665
|
+
netId: `${returnNet}.${loadLaid.component.id}`,
|
|
2666
|
+
points: compactPoints([loadReturn, { x: loadReturn.x, y: AC_RETURN_Y }])
|
|
2667
|
+
});
|
|
2668
|
+
return true;
|
|
2669
|
+
}
|
|
2670
|
+
function sourceLiveReturnNets(pinMap, source) {
|
|
2671
|
+
const pins = pinMap[source.id];
|
|
2672
|
+
if (!pins) return null;
|
|
2673
|
+
const liveNet = pins.plus ?? pins.end ?? Object.values(pins)[0];
|
|
2674
|
+
const returnNet = pins.minus ?? pins.start ?? Object.values(pins)[1];
|
|
2675
|
+
if (!liveNet || !returnNet || liveNet === returnNet) return null;
|
|
2676
|
+
return { liveNet, returnNet };
|
|
2677
|
+
}
|
|
2678
|
+
function layoutTwoWireSeriesLoop(ast, source, chain, load, liveNet, returnNet, loadLiveNet) {
|
|
2679
|
+
const pinMap = ast.pinMap ?? {};
|
|
2680
|
+
const items = [];
|
|
2681
|
+
const routes = [];
|
|
2682
|
+
const put = (comp, x, y, fallbackDir) => {
|
|
2683
|
+
const laid = placeComponent(comp, x, y, fallbackDir);
|
|
2684
|
+
items.push(laid);
|
|
2685
|
+
return laid;
|
|
2686
|
+
};
|
|
2687
|
+
const sourceLaid = put(source, AC_LEFT_MARGIN, AC_LIVE_Y + 62, "up");
|
|
2688
|
+
let cursorX = AC_LEFT_MARGIN + 86;
|
|
2689
|
+
let prevPt = anchorForNet(pinMap, sourceLaid, liveNet);
|
|
2690
|
+
if (!prevPt) return null;
|
|
2691
|
+
for (const step of chain) {
|
|
2692
|
+
const laid = put(step.comp, cursorX, AC_LIVE_Y, "right");
|
|
2693
|
+
const inPt = anchorForNet(pinMap, laid, step.inNet);
|
|
2694
|
+
const outPt = anchorForNet(pinMap, laid, step.outNet);
|
|
2695
|
+
if (!inPt || !outPt) return null;
|
|
2696
|
+
routes.push(routeViaY(step.inNet, prevPt, inPt, AC_LIVE_Y));
|
|
2697
|
+
prevPt = outPt;
|
|
2698
|
+
cursorX += laid.length + AC_SERIES_GAP;
|
|
2699
|
+
}
|
|
2700
|
+
const loadLaid = put(load, cursorX, AC_LIVE_Y, "right");
|
|
2701
|
+
const loadLive = anchorForNet(pinMap, loadLaid, loadLiveNet);
|
|
2702
|
+
if (!loadLive) return null;
|
|
2703
|
+
routes.push(routeViaY(loadLiveNet, prevPt, loadLive, AC_LIVE_Y));
|
|
2704
|
+
if (!appendReturnRail(routes, pinMap, sourceLaid, loadLaid, returnNet)) return null;
|
|
2705
|
+
return finalizeAutoLayout(items, routes);
|
|
2706
|
+
}
|
|
2707
|
+
function layoutTwoWayLightingLoop(ast, source, preChain, leftSwitch, rightSwitch, postChain, load, liveNet, returnNet, loadLiveNet) {
|
|
2708
|
+
const pinMap = ast.pinMap ?? {};
|
|
2709
|
+
const leftPins = pinMap[leftSwitch.id] ?? {};
|
|
2710
|
+
const rightPins = pinMap[rightSwitch.id] ?? {};
|
|
2711
|
+
const travelerNets = [leftPins.nc, leftPins.no].filter(Boolean);
|
|
2712
|
+
if (travelerNets.length !== 2 || !travelerNets.every((n) => n === rightPins.nc || n === rightPins.no)) {
|
|
2713
|
+
return null;
|
|
2714
|
+
}
|
|
2715
|
+
const items = [];
|
|
2716
|
+
const routes = [];
|
|
2717
|
+
const put = (comp, x, y, fallbackDir) => {
|
|
2718
|
+
const laid = placeComponent(comp, x, y, fallbackDir);
|
|
2719
|
+
items.push(laid);
|
|
2720
|
+
return laid;
|
|
2721
|
+
};
|
|
2722
|
+
const sourceLaid = put(source, AC_LEFT_MARGIN, AC_LIVE_Y + 62, "up");
|
|
2723
|
+
let cursorX = AC_LEFT_MARGIN + 86;
|
|
2724
|
+
let prevPt = anchorForNet(pinMap, sourceLaid, liveNet);
|
|
2725
|
+
if (!prevPt) return null;
|
|
2726
|
+
for (const step of preChain) {
|
|
2727
|
+
const laid = put(step.comp, cursorX, AC_LIVE_Y, "right");
|
|
2728
|
+
const inPt = anchorForNet(pinMap, laid, step.inNet);
|
|
2729
|
+
const outPt = anchorForNet(pinMap, laid, step.outNet);
|
|
2730
|
+
if (!inPt || !outPt) return null;
|
|
2731
|
+
routes.push(routeViaY(step.inNet, prevPt, inPt, AC_LIVE_Y));
|
|
2732
|
+
prevPt = outPt;
|
|
2733
|
+
cursorX += laid.length + AC_SERIES_GAP;
|
|
2734
|
+
}
|
|
2735
|
+
const leftLaid = put(leftSwitch, cursorX, AC_LIVE_Y, "right");
|
|
2736
|
+
const leftCommon = leftLaid.anchors.common;
|
|
2737
|
+
if (!leftCommon) return null;
|
|
2738
|
+
routes.push(routeViaY(leftPins.common ?? liveNet, prevPt, leftCommon, AC_LIVE_Y));
|
|
2739
|
+
const rightCommonX = leftLaid.x + leftLaid.length + AC_TRAVELER_SPAN + leftLaid.length;
|
|
2740
|
+
const sameTravelerOrder = leftPins.nc === rightPins.nc && leftPins.no === rightPins.no;
|
|
2741
|
+
const rightLength = getSymbol(rightSwitch.componentType)?.length ?? 30;
|
|
2742
|
+
const rightLaid = sameTravelerOrder ? placeMirroredComponent(rightSwitch, rightCommonX - rightLength, AC_LIVE_Y) : placeComponent(rightSwitch, rightCommonX, AC_LIVE_Y, "left");
|
|
2743
|
+
items.push(rightLaid);
|
|
2744
|
+
for (const net of travelerNets) {
|
|
2745
|
+
const a = anchorForNet(pinMap, leftLaid, net);
|
|
2746
|
+
const b = anchorForNet(pinMap, rightLaid, net);
|
|
2747
|
+
if (!a || !b) return null;
|
|
2748
|
+
routes.push(routeViaX(net, a, b, (a.x + b.x) / 2));
|
|
2749
|
+
}
|
|
2750
|
+
prevPt = rightLaid.anchors.common;
|
|
2751
|
+
if (!prevPt) return null;
|
|
2752
|
+
cursorX = rightCommonX + AC_SERIES_GAP;
|
|
2753
|
+
for (const step of postChain) {
|
|
2754
|
+
const laid = put(step.comp, cursorX, AC_LIVE_Y, "right");
|
|
2755
|
+
const inPt = anchorForNet(pinMap, laid, step.inNet);
|
|
2756
|
+
const outPt = anchorForNet(pinMap, laid, step.outNet);
|
|
2757
|
+
if (!inPt || !outPt) return null;
|
|
2758
|
+
routes.push(routeViaY(step.inNet, prevPt, inPt, AC_LIVE_Y));
|
|
2759
|
+
prevPt = outPt;
|
|
2760
|
+
cursorX += laid.length + AC_SERIES_GAP;
|
|
2761
|
+
}
|
|
2762
|
+
const loadLaid = put(load, cursorX, AC_LIVE_Y, "right");
|
|
2763
|
+
const loadLive = anchorForNet(pinMap, loadLaid, loadLiveNet);
|
|
2764
|
+
if (!loadLive) return null;
|
|
2765
|
+
routes.push(routeViaY(loadLiveNet, prevPt, loadLive, AC_LIVE_Y));
|
|
2766
|
+
if (!appendReturnRail(routes, pinMap, sourceLaid, loadLaid, returnNet)) return null;
|
|
2767
|
+
return finalizeAutoLayout(items, routes);
|
|
2768
|
+
}
|
|
2769
|
+
function tryLayoutTwoWireLighting(ast) {
|
|
2770
|
+
const pinMap = ast.pinMap ?? {};
|
|
2771
|
+
const sources = ast.components.filter(isPowerSource);
|
|
2772
|
+
if (sources.length !== 1) return null;
|
|
2773
|
+
const source = sources[0];
|
|
2774
|
+
const nets = sourceLiveReturnNets(pinMap, source);
|
|
2775
|
+
if (!nets || nets.liveNet === "GND" || nets.returnNet === "GND") return null;
|
|
2776
|
+
const { liveNet, returnNet } = nets;
|
|
2777
|
+
const loads = ast.components.filter((c) => {
|
|
2778
|
+
if (!isLightingLoad(c)) return false;
|
|
2779
|
+
const pins = pinEntries(pinMap, c);
|
|
2780
|
+
return pins.length === 2 && pins.some(([, net]) => net === returnNet);
|
|
2781
|
+
});
|
|
2782
|
+
if (loads.length !== 1) return null;
|
|
2783
|
+
const load = loads[0];
|
|
2784
|
+
const loadLiveNet = pinEntries(pinMap, load).find(([, net]) => net !== returnNet)?.[1];
|
|
2785
|
+
if (!loadLiveNet) return null;
|
|
2786
|
+
const excluded = /* @__PURE__ */ new Set([source.id, load.id]);
|
|
2787
|
+
const middle = ast.components.filter((c) => !excluded.has(c.id) && !isAutoGround(c));
|
|
2788
|
+
const spdts = middle.filter((c) => c.componentType === "switch_spdt");
|
|
2789
|
+
if (spdts.length === 0) {
|
|
2790
|
+
if (!middle.every((c) => isTwoTerminal(pinMap, c))) return null;
|
|
2791
|
+
const traced = traceTwoTerminalChain(pinMap, middle, liveNet, loadLiveNet);
|
|
2792
|
+
if (!traced || traced.used.size !== middle.length) return null;
|
|
2793
|
+
return layoutTwoWireSeriesLoop(ast, source, traced.steps, load, liveNet, returnNet, loadLiveNet);
|
|
2794
|
+
}
|
|
2795
|
+
if (spdts.length === 2) {
|
|
2796
|
+
const twoTerminal = middle.filter((c) => c.componentType !== "switch_spdt");
|
|
2797
|
+
if (!twoTerminal.every((c) => isTwoTerminal(pinMap, c))) return null;
|
|
2798
|
+
for (const [leftSwitch, rightSwitch] of [
|
|
2799
|
+
[spdts[0], spdts[1]],
|
|
2800
|
+
[spdts[1], spdts[0]]
|
|
2801
|
+
]) {
|
|
2802
|
+
const leftCommon = pinMap[leftSwitch.id]?.common;
|
|
2803
|
+
const rightCommon = pinMap[rightSwitch.id]?.common;
|
|
2804
|
+
if (!leftCommon || !rightCommon) continue;
|
|
2805
|
+
const pre = traceTwoTerminalChain(pinMap, twoTerminal, liveNet, leftCommon);
|
|
2806
|
+
if (!pre) continue;
|
|
2807
|
+
const postCandidates = twoTerminal.filter((c) => !pre.used.has(c.id));
|
|
2808
|
+
const post = traceTwoTerminalChain(pinMap, postCandidates, rightCommon, loadLiveNet);
|
|
2809
|
+
if (!post) continue;
|
|
2810
|
+
if (pre.used.size + post.used.size !== twoTerminal.length) continue;
|
|
2811
|
+
const rendered = layoutTwoWayLightingLoop(
|
|
2812
|
+
ast,
|
|
2813
|
+
source,
|
|
2814
|
+
pre.steps,
|
|
2815
|
+
leftSwitch,
|
|
2816
|
+
rightSwitch,
|
|
2817
|
+
post.steps,
|
|
2818
|
+
load,
|
|
2819
|
+
liveNet,
|
|
2820
|
+
returnNet,
|
|
2821
|
+
loadLiveNet
|
|
2822
|
+
);
|
|
2823
|
+
if (rendered) return rendered;
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
return null;
|
|
2827
|
+
}
|
|
2499
2828
|
function layoutCircuitNetlist(ast) {
|
|
2500
2829
|
const pinMap = ast.pinMap ?? {};
|
|
2830
|
+
const twoWireLighting = tryLayoutTwoWireLighting(ast);
|
|
2831
|
+
if (twoWireLighting) return twoWireLighting;
|
|
2501
2832
|
const isShunt = (c) => {
|
|
2502
2833
|
if (isPowerSource(c) || isGround(c)) return false;
|
|
2503
2834
|
const pins = pinMap[c.id];
|
|
@@ -2519,28 +2850,7 @@ function layoutCircuitNetlist(ast) {
|
|
|
2519
2850
|
const placed = /* @__PURE__ */ new Map();
|
|
2520
2851
|
const items = [];
|
|
2521
2852
|
const place = (comp, x, y, fallbackDir) => {
|
|
2522
|
-
const
|
|
2523
|
-
comp.direction = direction;
|
|
2524
|
-
const rot = rotationOf(direction);
|
|
2525
|
-
const sym = getSymbol(comp.componentType);
|
|
2526
|
-
const worldAnchors = {};
|
|
2527
|
-
if (sym) {
|
|
2528
|
-
for (const [name, pt] of Object.entries(sym.anchors)) {
|
|
2529
|
-
const rp = rotatePt(pt, rot);
|
|
2530
|
-
worldAnchors[name] = { x: x + rp.x, y: y + rp.y };
|
|
2531
|
-
}
|
|
2532
|
-
} else {
|
|
2533
|
-
worldAnchors.start = { x, y };
|
|
2534
|
-
worldAnchors.end = { x: x + 30, y };
|
|
2535
|
-
}
|
|
2536
|
-
const laid = {
|
|
2537
|
-
component: comp,
|
|
2538
|
-
x,
|
|
2539
|
-
y,
|
|
2540
|
-
rotation: rot,
|
|
2541
|
-
length: sym?.length ?? 30,
|
|
2542
|
-
anchors: worldAnchors
|
|
2543
|
-
};
|
|
2853
|
+
const laid = placeComponent(comp, x, y, fallbackDir);
|
|
2544
2854
|
items.push(laid);
|
|
2545
2855
|
placed.set(comp.id, laid);
|
|
2546
2856
|
return laid;
|
|
@@ -2757,20 +3067,21 @@ function renderItem(it, offX, offY) {
|
|
|
2757
3067
|
return `<rect x="${tx - 10}" y="${ty - 10}" width="20" height="20" fill="none" class="schematex-circuit-err" stroke-dasharray="3,2"/><text x="${tx}" y="${ty + 3}" text-anchor="middle" font-size="9" class="schematex-circuit-err">?${escapeXml(comp.componentType)}</text>`;
|
|
2758
3068
|
}
|
|
2759
3069
|
const body = sym.svg(comp.label, comp.value, comp.attrs);
|
|
2760
|
-
const transform = `translate(${tx}, ${ty}) rotate(${it.rotation})`;
|
|
3070
|
+
const transform = it.mirrorX ? `translate(${tx + it.length}, ${ty}) scale(-1, 1)` : `translate(${tx}, ${ty}) rotate(${it.rotation})`;
|
|
2761
3071
|
const labels = [];
|
|
2762
3072
|
if (comp.label || comp.value) {
|
|
2763
|
-
const
|
|
2764
|
-
const
|
|
2765
|
-
const
|
|
2766
|
-
const
|
|
2767
|
-
const
|
|
3073
|
+
const angle = it.rotation * Math.PI / 180;
|
|
3074
|
+
const midpointX = it.x + offX + it.length * Math.cos(angle) / 2;
|
|
3075
|
+
const midpointY = it.y + offY + it.length * Math.sin(angle) / 2;
|
|
3076
|
+
const vertical = Math.abs(Math.sin(angle)) > 0.5;
|
|
3077
|
+
const labelX = midpointX + (vertical ? 34 : 0);
|
|
3078
|
+
const labelY = midpointY - (vertical ? 2 : 18);
|
|
2768
3079
|
if (comp.label) {
|
|
2769
3080
|
labels.push(
|
|
2770
3081
|
text(
|
|
2771
3082
|
{
|
|
2772
|
-
x: labelX
|
|
2773
|
-
y: labelY
|
|
3083
|
+
x: labelX,
|
|
3084
|
+
y: labelY,
|
|
2774
3085
|
class: "schematex-circuit-label",
|
|
2775
3086
|
"text-anchor": "middle"
|
|
2776
3087
|
},
|
|
@@ -2782,8 +3093,8 @@ function renderItem(it, offX, offY) {
|
|
|
2782
3093
|
labels.push(
|
|
2783
3094
|
text(
|
|
2784
3095
|
{
|
|
2785
|
-
x: labelX
|
|
2786
|
-
y: labelY +
|
|
3096
|
+
x: labelX,
|
|
3097
|
+
y: labelY + 12,
|
|
2787
3098
|
class: "schematex-circuit-value",
|
|
2788
3099
|
"text-anchor": "middle"
|
|
2789
3100
|
},
|
|
@@ -2880,6 +3191,6 @@ var circuit = {
|
|
|
2880
3191
|
}
|
|
2881
3192
|
};
|
|
2882
3193
|
|
|
2883
|
-
export {
|
|
2884
|
-
//# sourceMappingURL=chunk-
|
|
2885
|
-
//# sourceMappingURL=chunk-
|
|
3194
|
+
export { SYMBOLS, circuit, layoutCircuit, layoutCircuitNetlist, lintCircuit, parseCircuit, parseNetlist, renderCircuit };
|
|
3195
|
+
//# sourceMappingURL=chunk-5IPT6OFE.js.map
|
|
3196
|
+
//# sourceMappingURL=chunk-5IPT6OFE.js.map
|