schematex 0.9.18 → 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.
Files changed (90) hide show
  1. package/README.md +13 -0
  2. package/dist/ai/ai-sdk.cjs +9 -9
  3. package/dist/ai/ai-sdk.d.cts +3 -3
  4. package/dist/ai/ai-sdk.d.ts +3 -3
  5. package/dist/ai/ai-sdk.js +4 -4
  6. package/dist/ai/index.cjs +18 -18
  7. package/dist/ai/index.d.cts +4 -4
  8. package/dist/ai/index.d.ts +4 -4
  9. package/dist/ai/index.js +5 -5
  10. package/dist/{api-DAUFeETp.d.cts → api-DH9a1V6Q.d.cts} +1 -1
  11. package/dist/{api-C9ufsgIb.d.ts → api-DsAwn8ne.d.ts} +1 -1
  12. package/dist/browser.cjs +10 -10
  13. package/dist/browser.d.cts +3 -3
  14. package/dist/browser.d.ts +3 -3
  15. package/dist/browser.js +4 -4
  16. package/dist/{chunk-FA6Y4QRS.js → chunk-5IPT6OFE.js} +356 -47
  17. package/dist/chunk-5IPT6OFE.js.map +1 -0
  18. package/dist/{chunk-LZHLFNM3.js → chunk-BP52JB7C.js} +4 -4
  19. package/dist/{chunk-LZHLFNM3.js.map → chunk-BP52JB7C.js.map} +1 -1
  20. package/dist/{chunk-VLK5T7B7.cjs → chunk-GJTD3RQE.cjs} +6 -6
  21. package/dist/{chunk-VLK5T7B7.cjs.map → chunk-GJTD3RQE.cjs.map} +1 -1
  22. package/dist/{chunk-DSKPJYQO.js → chunk-JBNLZQP2.js} +47 -5
  23. package/dist/chunk-JBNLZQP2.js.map +1 -0
  24. package/dist/{chunk-AG4WA4NF.cjs → chunk-JXPBZEFM.cjs} +355 -47
  25. package/dist/chunk-JXPBZEFM.cjs.map +1 -0
  26. package/dist/{chunk-6GVFKOSH.js → chunk-OZD4CYAK.js} +2 -2
  27. package/dist/{chunk-6GVFKOSH.js.map → chunk-OZD4CYAK.js.map} +1 -1
  28. package/dist/{chunk-JWILBXGR.cjs → chunk-PZ5MNDVY.cjs} +49 -7
  29. package/dist/chunk-PZ5MNDVY.cjs.map +1 -0
  30. package/dist/{chunk-AWUUGDN4.cjs → chunk-RVPYIBBH.cjs} +2 -2
  31. package/dist/{chunk-AWUUGDN4.cjs.map → chunk-RVPYIBBH.cjs.map} +1 -1
  32. package/dist/{diagnostics-DSxLohjY.d.cts → diagnostics-CKacYRIE.d.cts} +1 -1
  33. package/dist/{diagnostics-DSxLohjY.d.ts → diagnostics-CKacYRIE.d.ts} +1 -1
  34. package/dist/diagrams/blockdiagram/index.d.cts +1 -1
  35. package/dist/diagrams/blockdiagram/index.d.ts +1 -1
  36. package/dist/diagrams/circuit/index.cjs +8 -8
  37. package/dist/diagrams/circuit/index.d.cts +3 -1
  38. package/dist/diagrams/circuit/index.d.ts +3 -1
  39. package/dist/diagrams/circuit/index.js +1 -1
  40. package/dist/diagrams/ecomap/index.d.cts +1 -1
  41. package/dist/diagrams/ecomap/index.d.ts +1 -1
  42. package/dist/diagrams/entity/index.d.cts +1 -1
  43. package/dist/diagrams/entity/index.d.ts +1 -1
  44. package/dist/diagrams/fishbone/index.d.cts +1 -1
  45. package/dist/diagrams/fishbone/index.d.ts +1 -1
  46. package/dist/diagrams/flowchart/index.d.cts +2 -2
  47. package/dist/diagrams/flowchart/index.d.ts +2 -2
  48. package/dist/diagrams/genogram/index.d.cts +1 -1
  49. package/dist/diagrams/genogram/index.d.ts +1 -1
  50. package/dist/diagrams/ladder/index.d.cts +1 -1
  51. package/dist/diagrams/ladder/index.d.ts +1 -1
  52. package/dist/diagrams/logic/index.d.cts +1 -1
  53. package/dist/diagrams/logic/index.d.ts +1 -1
  54. package/dist/diagrams/orgchart/index.d.cts +1 -1
  55. package/dist/diagrams/orgchart/index.d.ts +1 -1
  56. package/dist/diagrams/pedigree/index.d.cts +1 -1
  57. package/dist/diagrams/pedigree/index.d.ts +1 -1
  58. package/dist/diagrams/phylo/index.d.cts +1 -1
  59. package/dist/diagrams/phylo/index.d.ts +1 -1
  60. package/dist/diagrams/siteplan/index.d.cts +1 -1
  61. package/dist/diagrams/siteplan/index.d.ts +1 -1
  62. package/dist/diagrams/sld/index.cjs +7 -7
  63. package/dist/diagrams/sld/index.d.cts +1 -1
  64. package/dist/diagrams/sld/index.d.ts +1 -1
  65. package/dist/diagrams/sld/index.js +1 -1
  66. package/dist/diagrams/sociogram/index.d.cts +1 -1
  67. package/dist/diagrams/sociogram/index.d.ts +1 -1
  68. package/dist/diagrams/timing/index.d.cts +1 -1
  69. package/dist/diagrams/timing/index.d.ts +1 -1
  70. package/dist/diagrams/venn/index.d.cts +1 -1
  71. package/dist/diagrams/venn/index.d.ts +1 -1
  72. package/dist/{index-CZa2pU0T.d.ts → index-BmJxw0lf.d.ts} +1 -1
  73. package/dist/{index-CDDfbChc.d.cts → index-Dth_Wjwf.d.cts} +1 -1
  74. package/dist/index.cjs +45 -48
  75. package/dist/index.cjs.map +1 -1
  76. package/dist/index.d.cts +4 -4
  77. package/dist/index.d.ts +4 -4
  78. package/dist/index.js +8 -11
  79. package/dist/index.js.map +1 -1
  80. package/dist/react.cjs +4 -4
  81. package/dist/react.d.cts +2 -2
  82. package/dist/react.d.ts +2 -2
  83. package/dist/react.js +3 -3
  84. package/dist/{tools-Bvw6dwIR.d.cts → tools-Bl6w3h3P.d.cts} +2 -2
  85. package/dist/{tools-DtuvE-K4.d.ts → tools-CBYFRF2a.d.ts} +2 -2
  86. package/package.json +1 -1
  87. package/dist/chunk-AG4WA4NF.cjs.map +0 -1
  88. package/dist/chunk-DSKPJYQO.js.map +0 -1
  89. package/dist/chunk-FA6Y4QRS.js.map +0 -1
  90. package/dist/chunk-JWILBXGR.cjs.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] ?? EXTRA_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) {
@@ -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"]);
@@ -2474,6 +2472,11 @@ var ROW_H = 80;
2474
2472
  var LEFT_MARGIN = 70;
2475
2473
  var TOP_MARGIN = 56;
2476
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;
2477
2480
  function isPowerSource(c) {
2478
2481
  return c.componentType === "voltage_source" || c.componentType === "current_source" || c.componentType === "ac_source" || c.componentType === "battery" || c.componentType === "vcc";
2479
2482
  }
@@ -2500,8 +2503,334 @@ function extendBBox(bbox, pt) {
2500
2503
  if (pt.x > bbox.maxX) bbox.maxX = pt.x;
2501
2504
  if (pt.y > bbox.maxY) bbox.maxY = pt.y;
2502
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
+ }
2503
2830
  function layoutCircuitNetlist(ast) {
2504
2831
  const pinMap = ast.pinMap ?? {};
2832
+ const twoWireLighting = tryLayoutTwoWireLighting(ast);
2833
+ if (twoWireLighting) return twoWireLighting;
2505
2834
  const isShunt = (c) => {
2506
2835
  if (isPowerSource(c) || isGround(c)) return false;
2507
2836
  const pins = pinMap[c.id];
@@ -2523,28 +2852,7 @@ function layoutCircuitNetlist(ast) {
2523
2852
  const placed = /* @__PURE__ */ new Map();
2524
2853
  const items = [];
2525
2854
  const place = (comp, x, y, fallbackDir) => {
2526
- const direction = comp.attrs?.dirExplicit === "true" ? comp.direction : fallbackDir ?? defaultDirection(comp);
2527
- comp.direction = direction;
2528
- const rot = rotationOf(direction);
2529
- const sym = getSymbol(comp.componentType);
2530
- const worldAnchors = {};
2531
- if (sym) {
2532
- for (const [name, pt] of Object.entries(sym.anchors)) {
2533
- const rp = rotatePt(pt, rot);
2534
- worldAnchors[name] = { x: x + rp.x, y: y + rp.y };
2535
- }
2536
- } else {
2537
- worldAnchors.start = { x, y };
2538
- worldAnchors.end = { x: x + 30, y };
2539
- }
2540
- const laid = {
2541
- component: comp,
2542
- x,
2543
- y,
2544
- rotation: rot,
2545
- length: sym?.length ?? 30,
2546
- anchors: worldAnchors
2547
- };
2855
+ const laid = placeComponent(comp, x, y, fallbackDir);
2548
2856
  items.push(laid);
2549
2857
  placed.set(comp.id, laid);
2550
2858
  return laid;
@@ -2761,20 +3069,21 @@ function renderItem(it, offX, offY) {
2761
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>`;
2762
3070
  }
2763
3071
  const body = sym.svg(comp.label, comp.value, comp.attrs);
2764
- 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})`;
2765
3073
  const labels = [];
2766
3074
  if (comp.label || comp.value) {
2767
- const labelX = it.x + offX + it.length * Math.cos(it.rotation * Math.PI / 180) / 2;
2768
- const labelY = it.y + offY + it.length * Math.sin(it.rotation * Math.PI / 180) / 2;
2769
- const perpDX = Math.sin(it.rotation * Math.PI / 180);
2770
- const perpDY = -Math.cos(it.rotation * Math.PI / 180);
2771
- const off = 16;
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);
2772
3081
  if (comp.label) {
2773
3082
  labels.push(
2774
3083
  chunk3WNW5Y7P_cjs.text(
2775
3084
  {
2776
- x: labelX + perpDX * off,
2777
- y: labelY + perpDY * off - 2,
3085
+ x: labelX,
3086
+ y: labelY,
2778
3087
  class: "schematex-circuit-label",
2779
3088
  "text-anchor": "middle"
2780
3089
  },
@@ -2786,8 +3095,8 @@ function renderItem(it, offX, offY) {
2786
3095
  labels.push(
2787
3096
  chunk3WNW5Y7P_cjs.text(
2788
3097
  {
2789
- x: labelX + perpDX * off,
2790
- y: labelY + perpDY * off + 10,
3098
+ x: labelX,
3099
+ y: labelY + 12,
2791
3100
  class: "schematex-circuit-value",
2792
3101
  "text-anchor": "middle"
2793
3102
  },
@@ -2884,7 +3193,6 @@ var circuit = {
2884
3193
  }
2885
3194
  };
2886
3195
 
2887
- exports.EXTRA_SYMBOLS = EXTRA_SYMBOLS;
2888
3196
  exports.SYMBOLS = SYMBOLS;
2889
3197
  exports.circuit = circuit;
2890
3198
  exports.layoutCircuit = layoutCircuit;
@@ -2893,5 +3201,5 @@ exports.lintCircuit = lintCircuit;
2893
3201
  exports.parseCircuit = parseCircuit;
2894
3202
  exports.parseNetlist = parseNetlist;
2895
3203
  exports.renderCircuit = renderCircuit;
2896
- //# sourceMappingURL=chunk-AG4WA4NF.cjs.map
2897
- //# sourceMappingURL=chunk-AG4WA4NF.cjs.map
3204
+ //# sourceMappingURL=chunk-JXPBZEFM.cjs.map
3205
+ //# sourceMappingURL=chunk-JXPBZEFM.cjs.map