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