The label lookup in drawComponentGate read from gate.component (potentially
stale copy) while gateOutputCount read from state.customComponents (updated
definition), causing a mismatch — fewer ports but old outputIds, so the
first (deleted) output's label was shown instead of the surviving one.
Three fixes:
- renderer: use customComponents as authoritative source for label lookup
- saveLoad: re-link gate.component refs to customComponents after loading
- components: update existing instances even when a "new" component
overwrites an existing definition with the same name
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BUS_IN has input pins only (left side), BUS_OUT has output pins
only (right side). No internal connections between them — BUS_OUT
reads values directly from its paired BUS_IN via busPairId. The
bus cable between them is purely visual, representing the grouped
signal bundle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Click and drag on empty space to draw a selection rectangle. Gates
inside the box get selected (cyan dashed outline). Drag any selected
gate to move all of them together. Delete/Backspace removes all
selected gates and their connections. Escape clears the selection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of a single pass-through gate, shift+drag now creates two
BUS terminals (IN and OUT) connected by a thick bus cable. Internal
connections between terminals are hidden and rendered as a single
cable with /N notation and a diagonal slash. Each terminal is a
thin cyan bar that can be moved independently.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hold Shift and drag across wires to create a BUS gate that groups
them together. The cut line shows a live preview with wire count.
BUS gates are pass-through (each input maps to its output) and
render as a thin cyan bar with ports on each side.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Selected gate type stays active after placing, allowing multiple
gates of the same type without re-selecting. Right-click or Escape
to cancel placing mode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Auto-saves every 3 seconds and on page unload. Restores the full
state (circuit, camera, custom components) on page load.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Double-click rename for INPUT/OUTPUT/CLOCK gates now only triggers
when inside the component editor, not in the main circuit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Opens the component editor with the internal circuit loaded for
modification. On save, updates the component definition and all
existing instances in the main circuit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show input/output labels next to ports on custom component chips,
and persist internal gate state between evaluations so latches and
flip-flops retain their values correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Major fixes for custom components when used in the main circuit:
- Add outputValues[] array for multi-output component gates, so each
output port carries its own independent value
- readSourcePort() reads the correct port value from source gates
instead of always reading gate.value
- evaluateComponent() now uses iterative fixed-point evaluation
(matching main evaluateAll) instead of a simple 10-pass loop
- Store inputIds/outputIds in component definition for consistent
port-to-gate mapping across save/load
- Renderer reads per-port values for connection color and port glow
- Added debug logs for component save and evaluation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Double-click any INPUT, OUTPUT, or CLOCK gate to assign a custom label.
Labels are shown inside the gate and used in waveform viewer instead of
generic IN_0/OUT_0 names. Example circuits now ship with meaningful
labels (S, R, D, EN, Q, Q̅, CLK).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lower component editor overlay z-index from 105 to 90 so toolbar
dropdown menus (z-index 150) appear on top of it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace single-pass recursive evaluation with iterative fixed-point
evaluation that runs multiple passes until all gate values stabilize.
Crucially, gate values are NO LONGER reset to 0 before evaluation,
which preserves latch/flip-flop memory state.
Add console logs for toggle, wire, and evaluation stability debugging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 4 example circuits accessible from a new toolbar dropdown:
- SR Flip-Flop (NOR) — basic set-reset latch
- SR Flip-Flop (NAND) — active-low variant
- D Latch (1-bit Memory) — gated latch with enable
- D Flip-Flop (Master-Slave) — edge-triggered with CLK
Each example shows name + description in the dropdown and loads
the full circuit with proper gate placement and wiring.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
recordSample() (triggered by user INPUT toggle) now only advances
timeStep when the simulation is stopped. When sim is running, it
records at the current timeStep without advancing it, so the clock's
regular tick cadence is never stolen by manual interactions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace setInterval with requestAnimationFrame loop that tracks elapsed
time via performance.now(). Clock ticks now fire based on real time
rather than assuming perfect interval spacing, so user interactions
(toggling inputs, dragging gates) no longer cause the clock to stutter
or pause.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace horizontal toolbar sections with dropdown buttons (I/O, Gates,
Components). Each opens a dropdown menu on click, keeping the toolbar
clean and compact. Dropdowns close on outside click or after selecting
a gate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redesign toolbar sections to use horizontal button rows instead of
vertical stacking. Fix component placement by attaching click handlers
directly to dynamically created buttons and passing correct gate object
shape to getComponentWidth/Height.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Redesigned toolbar with I/O, Gates, and Components sections
- Component editor: sub-canvas mode to design reusable chips
- Save/Cancel with main circuit state preservation
- Components persist in localStorage
- Custom components render as purple chips with dynamic I/O ports
- Component evaluation simulates internal circuit as black box
- Toolbar height increased to 56px for section labels
- All height references updated consistently
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- INPUT/CLOCK gates can now be dragged (click-without-move = toggle,
click-and-drag = move). Uses 4px movement threshold.
- Waveform only records samples on intentional actions (INPUT toggle,
manual step, simulation tick), not on gate placement/movement/connections.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Puzzle panel now shifts canvas and waveform viewer right (340px) instead of
overlapping them, using body class toggle and CSS transitions
- Canvas resize accounts for sidebar width
- Progress (completed/unlocked levels, custom components) persists in localStorage
- Level cards refresh on each panel open to reflect current progress
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add progressive puzzle mode alongside the existing sandbox:
- 8 levels from basic gates to 2-bit adder
- Truth table verification with pass/fail feedback
- Gate restrictions per level
- Custom components system (save circuits as reusable chips)
- Save/load circuits as JSON
- Level selection sidebar with difficulty ratings
- Mode toggle: Sandbox (free play) vs Puzzle (guided levels)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restores the real-time ms-based waveform that correctly reflects
clock speed in wave width. Keeps the always-follow auto-scroll fix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- timeStep increments by 1 per tick (not by simSpeed ms)
- waveZoom = pixels per step directly (zoom changes wave width)
- Speed control only changes real-time interval between ticks
- Auto-scroll always follows latest data regardless of zoom level
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each simulation tick now advances timeStep by 1 instead of by simSpeed ms.
waveZoom directly controls pixels per step, so changing clock speed
(the real-time interval) doesn't affect visual wave width, but zooming does.
This matches GTKWave behavior where the x-axis represents clock cycles.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- CLOCK gate auto-toggles 0→1→0 during simulation
- Run/Stop button in waveform toolbar
- Adjustable speed (50ms to 2000ms per tick)
- Click CLOCK to toggle manually when sim is stopped
- Waveform auto-opens when sim starts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>