/** * LogicGateElements.ts — Custom Web Components for standard logic gates. * * Implements SVG-rendered logic gate elements for use in the Velxio simulator. * These do NOT exist in wokwi-elements, so we define them here. * * Tags defined: * wokwi-logic-and — 2-input AND gate * wokwi-logic-nand — 2-input NAND gate * wokwi-logic-or — 2-input OR gate * wokwi-logic-nor — 2-input NOR gate * wokwi-logic-xor — 2-input XOR gate * wokwi-logic-not — 1-input NOT (inverter) * * Pin layout (in CSS pixels, used by PinOverlay): * 2-input gates (72 × 48 px): A(0,14) B(0,34) Y(72,24) * NOT gate (56 × 36 px): A(0,18) Y(56,18) */ // ─── Shared colours ─────────────────────────────────────────────────────────── const FILL = '#e8f0fa'; const STROKE = '#3360b0'; const LEAD = '#555555'; const TEXT = '#1a3060'; const STYLE = ':host{display:inline-block;line-height:0}'; // ─── 2-input gate base ─────────────────────────────────────────────────────── function twoInputPinInfo() { return [ { name: 'A', x: 0, y: 14, number: 1, signals: [] }, { name: 'B', x: 0, y: 34, number: 2, signals: [] }, { name: 'Y', x: 72, y: 24, number: 3, signals: [] }, ]; } function leads2Input(): string { return ` `; } function outputLead(fromX: number): string { return ``; } function bubbleAndLead(bubbleCx: number): string { const r = 4; const lineStart = bubbleCx + r; return ` `; } function label(x: number, y: number, text: string): string { return `${text}`; } // ─── AND Gate (72×48) ───────────────────────────────────────────────────────── // Body: rectangle (20-42,6-42) + semicircle arc right side (radius 18, tip at x=60) class AndGateElement extends HTMLElement { readonly pinInfo = twoInputPinInfo(); constructor() { super(); this.attachShadow({ mode: 'open' }).innerHTML = ` ${leads2Input()} ${outputLead(60)} ${label(26, 28, '&')} `; } } // ─── NAND Gate (72×48) ──────────────────────────────────────────────────────── // AND body + inversion bubble at output (cx=64, r=4 → spans x60-x68) class NandGateElement extends HTMLElement { readonly pinInfo = twoInputPinInfo(); constructor() { super(); this.attachShadow({ mode: 'open' }).innerHTML = ` ${leads2Input()} ${bubbleAndLead(64)} ${label(26, 28, '&')} `; } } // ─── OR Gate (72×48) ────────────────────────────────────────────────────────── // Body: Q-bezier — top curve, bottom curve, concave left side // Tip at (54,24); output line from 54→72 class OrGateElement extends HTMLElement { readonly pinInfo = twoInputPinInfo(); constructor() { super(); this.attachShadow({ mode: 'open' }).innerHTML = ` ${leads2Input()} ${outputLead(54)} ${label(25, 28, '≥1')} `; } } // ─── NOR Gate (72×48) ───────────────────────────────────────────────────────── // OR body + inversion bubble at output (cx=58, r=4 → spans x54-x62) class NorGateElement extends HTMLElement { readonly pinInfo = twoInputPinInfo(); constructor() { super(); this.attachShadow({ mode: 'open' }).innerHTML = ` ${leads2Input()} ${bubbleAndLead(58)} ${label(25, 28, '≥1')} `; } } // ─── XOR Gate (72×48) ───────────────────────────────────────────────────────── // OR body + extra curved line to the left (the XOR distinguishing mark) class XorGateElement extends HTMLElement { readonly pinInfo = twoInputPinInfo(); constructor() { super(); this.attachShadow({ mode: 'open' }).innerHTML = ` ${leads2Input()} ${outputLead(54)} ${label(24, 28, '=1')} `; } } // ─── NOT Gate (56×36) ───────────────────────────────────────────────────────── // Triangle pointing right + inversion bubble at tip // Input A(0,18) → triangle base at x=4, tip at x=44 // Bubble cx=48,r=4 → extends to x=52; output lead x52→56; Pin Y(56,18) class NotGateElement extends HTMLElement { readonly pinInfo = [ { name: 'A', x: 0, y: 18, number: 1, signals: [] }, { name: 'Y', x: 56, y: 18, number: 2, signals: [] }, ]; constructor() { super(); this.attachShadow({ mode: 'open' }).innerHTML = ` ${label(10, 22, '1')} `; } } // ─── Register custom elements ───────────────────────────────────────────────── if (!customElements.get('wokwi-logic-and')) customElements.define('wokwi-logic-and', AndGateElement); if (!customElements.get('wokwi-logic-nand')) customElements.define('wokwi-logic-nand', NandGateElement); if (!customElements.get('wokwi-logic-or')) customElements.define('wokwi-logic-or', OrGateElement); if (!customElements.get('wokwi-logic-nor')) customElements.define('wokwi-logic-nor', NorGateElement); if (!customElements.get('wokwi-logic-xor')) customElements.define('wokwi-logic-xor', XorGateElement); if (!customElements.get('wokwi-logic-not')) customElements.define('wokwi-logic-not', NotGateElement);