Add views, import/duplicate, DRC, jumps toggle, multi-wire select, auto-route, delete view tabs

- Roadmap #22: File→Import JSON to restore a diagram (drag-drop or file picker)
- Roadmap #23: Duplicate diagram from diagram list
- Roadmap #24: DRC panel with collapsible categories (unconnected pins, dup refs, no length, no P/N)
- Multi-view tabs: named views per diagram with independent device/wire layouts; snapshot-on-entry prevents bleed
- Keyboard arrow nudge for selected device(s)
- Undo for move, duplicate, label/property changes
- Wire jump arcs toggle (⌒ Jumps button in toolbar)
- Shift+click multi-wire selection; right-click bulk clear waypoints or auto-route
- Auto-route: obstacle-avoiding ortho routing for single or bulk selected wires
- Delete view tab with × button; right-click context menu for rename/delete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-24 19:18:39 -04:00
parent f43cd3409c
commit e4a80dc0e6
11 changed files with 823 additions and 25 deletions
+57 -3
View File
@@ -74,6 +74,38 @@ body { background: #12121c; color: #c8ccee; }
}
.diagram-item:hover .di-del-btn { opacity: 1; }
.di-del-btn:hover { background: #3a1414; border-color: #aa3333; }
.di-dup-btn {
flex-shrink: 0; opacity: 0; padding: 1px 5px; font-size: 13px; line-height: 1;
background: transparent; border-color: transparent; color: #88aaff;
transition: opacity .15s; margin-left: 4px;
}
.diagram-item:hover .di-dup-btn { opacity: 1; }
.di-dup-btn:hover { background: #1a1a40; border-color: #4466aa; }
/* ── View tab bar ────────────────────────────────────────────────────────── */
#view-tab-bar {
display: flex; align-items: center; gap: 2px;
padding: 3px 8px; background: #0c0c1c; border-bottom: 1px solid #2a2a44;
flex-shrink: 0;
}
.view-tab {
padding: 3px 12px; font-size: 11px; border-radius: 4px 4px 0 0;
background: #1a1a30; border: 1px solid #2a2a44; border-bottom: none;
color: #8888aa; cursor: pointer;
}
.view-tab { display: inline-flex; align-items: center; gap: 4px; }
.view-tab.active { background: #1e2a4a; border-color: #4466aa; color: #c0c8f0; }
.view-tab:hover:not(.active) { background: #1e1e38; color: #aaa; }
.view-tab-close {
font-size: 13px; line-height: 1; opacity: 0.4; padding: 0 2px;
border-radius: 3px;
}
.view-tab-close:hover { opacity: 1; background: rgba(255,80,80,0.25); color: #ff8888; }
#btn-add-view {
padding: 2px 8px; font-size: 14px; background: transparent;
border: 1px dashed #333355; border-radius: 4px; color: #556; cursor: pointer;
}
#btn-add-view:hover { border-color: #5566aa; color: #99aadd; }
/* ── Device library ───────────────────────────────────────────────────────── */
#device-library { padding: 6px; display: flex; flex-direction: column; gap: 3px; }
@@ -98,9 +130,9 @@ body { background: #12121c; color: #c8ccee; }
.conn-meta { font-size: 10px; color: #556688; margin-top: 1px; }
/* ── Canvas area ──────────────────────────────────────────────────────────── */
#canvas-area { flex: 1; position: relative; overflow: hidden; }
#canvas-area { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
#canvas-container {
width: 100%; height: 100%;
flex: 1; width: 100%;
background-color: #131320;
background-image: radial-gradient(circle, #2e2e50 1px, transparent 1px);
background-size: 20px 20px;
@@ -228,7 +260,7 @@ button:active { background: #1a1a3a; }
.conn-edit-btn:hover { background: #2a2a5a; border-color: #6666aa; }
/* ── Modal ───────────────────────────────────────────────────────────────── */
#connector-modal {
#connector-modal, #drc-modal {
position: fixed; inset: 0; background: rgba(0,0,0,0.65); z-index: 1000;
align-items: center; justify-content: center;
}
@@ -250,6 +282,28 @@ button:active { background: #1a1a3a; }
display: flex; align-items: center; gap: 8px; flex-shrink: 0;
}
/* ── DRC ────────────────────────────────────────────────────────────────── */
.drc-category { border: 1px solid #2a2a44; border-radius: 5px; overflow: hidden; }
.drc-cat-header {
display: flex; align-items: center; gap: 8px;
padding: 8px 12px; background: #1a1a30; cursor: pointer;
user-select: none;
}
.drc-cat-header:hover { background: #1e1e3a; }
.drc-cat-icon { font-size: 13px; }
.drc-cat-label { flex: 1; font-size: 12px; font-weight: 600; color: #c0c4e8; }
.drc-cat-count {
font-size: 11px; font-weight: 700; background: #2a2a50;
padding: 1px 7px; border-radius: 10px; color: #9090cc;
}
.drc-cat-body { padding: 4px 0; background: #0e0e1e; }
.drc-row {
padding: 5px 14px; font-size: 11px; color: #a0a4c8;
border-bottom: 1px solid #151528;
}
.drc-row:last-child { border-bottom: none; }
.drc-none { color: #444466; font-style: italic; }
.cm-label {
display: block; font-size: 10px; font-weight: 600; text-transform: uppercase;
letter-spacing: .06em; color: #555577; margin-bottom: 4px;